I use switch/case to get virtual function pointer and call it later.
void Application::OnEvent(Event* e)
{
bool(Layer::* p)(Event*)=nullptr;
EventType type = e->GetEventType();
switch (type)
{
case Hazel::EventType::MouseMoved:
p = &Layer::OnMouseMovedEvent;
break;
case Hazel::EventType::MouseButtonPressed:
p = &Layer::OnMouseButtonPressedEvent;
break;
case Hazel::EventType::MouseButtonReleased:
p = &Layer::OnMouseButtonReleasedEvent;
break;
}
LayerStackOnEvent(p, e);
}
void Application::LayerStackOnEvent(bool(Layer::*p)(Event*), Event* e) {
for (auto iter = m_LayerStack.rbegin(); iter != m_LayerStack.rend(); iter++) {
if (((*iter)->*p)(e) == true)
break;
}
}
Visual Studio Disassembly:
lea rdi,[Hazel::Layer::`vcall'{48}' (07FFD86991890h)]
lea rdi,[Hazel::Layer::`vcall'{40}' (07FFD86991898h)]
lea rdi,[Hazel::Layer::`vcall'{56}' (07FFD869918A0h)]
…………
Loops start
mov rcx,qword ptr [rbx-8] //
add rbx,0FFFFFFFFFFFFFFF8h // rcx=*iter--
call rdi
……//Loops end,check if rbx(iter) reach the end.
call rdi go to one of the following
00007FFD86991890 mov rax,qword ptr [rcx]
00007FFD86991893 jmp qword ptr [rax+30h]
00007FFD86991896 int 3
00007FFD86991897 int 3
00007FFD86991898 mov rax,qword ptr [rcx]
00007FFD8699189B jmp qword ptr [rax+28h]
00007FFD8699189E int 3
00007FFD8699189F int 3
00007FFD869918A0 mov rax,qword ptr [rcx]
00007FFD869918A3 jmp qword ptr [rax+38h]
I wonder if there is some way to optimize it into something like this
lea rdi,[30h]
lea rdi,[28h]
lea rdi,[38h]
…………loop start
00007FFD63E717D0 mov rcx,qword ptr [rbx-8] // rcx=*--iter
00007FFD63E717D4 add rbx,0FFFFFFFFFFFFFFF8h //
00007FFD86991890 mov rax,qword ptr [rcx]
00007FFD86991893 jmp qword ptr [rax+rdi]
…………loop end
The sequence of functions in vftable seems to depend on the sequence they are declared in the Base Class. So if this .cpp includes the Base.h , it should know the offset of a certain virtual function.