0

This is a follow-up from another question.

I think the following code should not use monotonic_buffer_resource, but in the generated assembly there are references to it.

void default_pmr_alloc(std::pmr::polymorphic_allocator<int>& alloc) {
    (void)alloc.allocate(1);
}

godbolt

I looked into the source code of the header files and libstdc++, but could not find how monotonic_buffer_resource was selected to be used by the default pmr allocator.

ggg
  • 1,857
  • 2
  • 21
  • 33

1 Answers1

1

The assembly tells the story. In particular, this:

cmp     rax, OFFSET FLAT:_ZNSt3pmr25monotonic_buffer_resource11do_allocateEmm
jne     .L11

This appears to be a test to see if the memory resource is a monotonic_buffer_resource. This seems to be done by checking the do_allocate member of the vtable. If it is not such a resource (ie: if do_allocate in the memory resource is not the monotonic one), then it jumps down to this:

.L11:
        mov     rdi, rbx
        mov     edx, 4
        mov     esi, 4
        pop     rbx
        jmp     rax

This appears to be a vtable call.

The rest of the assembly appears to be an inlined version of monotonic_buffer_resource::do_allocate. Which is why it conditionally calls std::pmr::monotonic_buffer_resource::_M_new_buffer.

So overall, this implementation of polymorphic_resource::allocate seems to have some built-in inlining of monotonic_buffer_resource::do_allocate if the resource is appropriate for that. That is, it won't do a vtable call if it can determine that it should call monotonic_buffer_resource::do_allocate.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • do you know what is the name of this optimization technique? Or is it a special case optimization? – ggg Oct 30 '22 at 15:40
  • @ggg: It's some form of devirtualization. It's likely that the compiler did it for some reason (since it's directly accessing the vtable), but I can't say what caused it to happen. The easiest thing to do would be to just look at the implementation. – Nicol Bolas Oct 30 '22 at 15:52