-
Notifications
You must be signed in to change notification settings - Fork 701
Description
At the moment we have function tables where every element has the same type, and a call_indirect operation that takes a static table index and dynamic element index. This means C++ vftables translate to static data in VM memory. Calling a virtual function must first load the address of the vftable, then load the function index from the vftable, then make the indirect call, which has to validate the function index because it came from VM memory. Compared to native there's an extra level of indirection because the vtable in untrusted VM memory must store a function index instead of a direct pointer.
I propose that we add heterogeneously typed function tables (HTFT), i.e. function tables that allow each element to have a different type, and interface tables (IT), i.e. tables of HTFTs with the same types.
Also add an operation that calls a static element index of a dynamic HTFT index of a static IT. This should cost roughly the same as the present call_indirect: it can statically validate the element index and IT index, and at runtime must mask the HTFT index, load the function pointer from a flat table for the IT*, and call it.
These changes would allow C++ vftables to be stored in trusted memory, so only the vftable index comes from untrusted VM memory. That means there isn't any indirection necessary beyond what is otherwise implied by calling through a statically unknown vftable.
So that new operation has the same cost as call_indirect, but it can implement a call to vftable without first loading an index from VM memory. That should allow implementing C++ virtual function calls with roughly the same performance as native.
To avoid having too many concepts, you could replace the existing homogeneously typed function tables as an interface table containing function tables with only a single function.
This can be polyfilled in ASM.JS if it can allocate space (see #306) to store the ITs on the heap. It would be storing indices into the function tables rather than direct pointers, so it wouldn't be a perf win, but it shouldn't be any slower than the current implementation.