webassembly / call-tags Goto Github PK
View Code? Open in Web Editor NEWLicense: Other
License: Other
An application could have an internal and external function table, one that it reserves for internal access, and one that it exports, containing functions that it is "okay" with other modules calling and using.
How does, or doesn't having multiple tables solve the problem that this proposal is attempting to solve?
Hi, I'm working on optimization of indirect calls [https://bugzilla.mozilla.org/show_bug.cgi?id=1639153] and happy to leave some comments about call_tags:
calls are efficient (just an additional push, pop, and bitwise equality check compared to a typed function call, which has been evaluated to produce no measurable overhead)
Well, right now it works as you described, with a few low-level details. So, we don't need call_tags here.
modules can restrict how their functions can be called indirectly (e.g. ensure no other module can indirectly call a particular function)
Yes, this is useful, there is an motivational example for C++ -> wasm:
class Base {
public:
virtual int foo() { return 1; }
};
class Derived : public Base {
public:
int foo() override { return 2; }
};
int Bar(Base* base) {
return base->foo();
}
The Bar
function will be compiled to call_indirect
and wasm engine can't optimize it because call_indirect
target can be from different instance or from js [https://godbolt.org/z/41M9rc8jK]. We can optimize this case via call-tags
or we can use private tables and do the same stuff via existing mechanism.
When an engine (let it be SpiderMonkey) populates the table with pointers it can deduce what this table is.
If the table has been created in the current module and it hasn't been exported than we can fill the table with raw pointers to the specified functions.
We don't need to switch instances in that case too and so, call_indirect
for this case can be as effective as simple call
+ signature check.
Since we can declare any number of tables we can restrict how our functions will be called via call_indirect
.
Could you clarify benefits of call-tags vs tables for this case? @RossTate
call_indirect $table $functype is simply the special case call_with_tag (call_tag.canon $functype) (table.get $table)
table.get $table
is really expensive one because we should create JS wrapper for that function as we don't now how we will use that reference - does it flow out to JS or stay in wasm realm?
BTW,
Looking at a function's definition alone, it's not apparent if a function can be indirectly called via call_indirect. One has to do some analysis to check if a reference to that function is made. And once a function reference has been made, it can be very difficult to ensure even something as simple as the function is only accessed by its own module.
In any case we need to track what function is referenced because we need to create some JS wrappers for that function, so this information is already available.
In WebAssembly/gc#243 (comment) and in other recent discussions, call tags have been raised as a potential solution for various performance problems that come up when compiling to Wasm GC. The call tags explainer describes call tags primarily as a mechanism for enforcing program invariants rather than performance, so it would be good to have the performance motivations written up as well.
Thinking about callee-checked call tags vs. caller-checked casting from funcref
to typed function references via ref.cast
, both seem valuable for optimizing different cases. The former can efficiently capture situations like interface dispatch, as presented. The latter can allow a type check to hoisted so it is performed once, followed by multiple typed (unchecked) calls.
It seems like one can support both by specifying:
funcref
) as an "overload set" of N other functions (i.e., dispatch_func
from #1346)funcref
s can be downcast via ref.cast
rtt
call_indirect
for passing an rtt
(call_funcref
from #1346)
rtt
srtt
call_indirect $t
behaves as if using the new call_indirect
variant, passing rtt.canon $t
, which means it also works for overload setsI think it would be possible to implement this feature with purely caller-side checking (reducing the two call_indirect
variants into a ref.cast
followed by call_ref
), but I think it would be somewhat more efficient for the implementation to implement the two call_indirect
s as a callee-side check. In any case, to support ref.cast
on an overload-set funcref
, the implementation would need to have the list of rtt
s efficiently reachable from the funcref
, which seems doable.
Anyhow, this is just a sketch of an idea for how to achieve both of these goals. Maybe I'm neglecting some details.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.