Stream: wasm

Topic: ✔ typed funcrefs "undeclared" if not used in init exprs?


view this post on Zulip Chris Fallin (Feb 23 2024 at 17:17):

Hi all! I'm playing with typed funcrefs to see about using them for efficient indirection (ICs); specifically I want globals that are mutable typed non-nullable funcrefs.

I've hit some perplexing behavior that I can't square with anything I see in the proposal doc; specifically, a ref.func instruction yields an "undeclared function reference" error when validated by wasm-tools if the func it refers to is not also used in an init expression for a global or in a table element segment.

This validates:

(module
  (type $ic (func (param i32 i32 i32 i32) (result i32)))

  (global $ic1 (mut (ref $ic)) (ref.func $icfunc1))
  (global $ic2 (mut (ref $ic)) (ref.func $icfunc2))

  (func $icfunc1 (param i32 i32 i32 i32) (result i32)
        local.get 0)
  (func $icfunc2 (param i32 i32 i32 i32) (result i32)
        local.get 1)

  (func (export "setup")
        ref.func $icfunc2
        global.set $ic1))

but this does not:

(module
  (type $ic (func (param i32 i32 i32 i32) (result i32)))

  (global $ic1 (mut (ref $ic)) (ref.func $icfunc1))

  (func $icfunc1 (param i32 i32 i32 i32) (result i32)
        local.get 0)
  (func $icfunc2 (param i32 i32 i32 i32) (result i32)
        local.get 1)

  (func (export "setup")
        ref.func $icfunc2
        global.set $ic1))

which looks like weird action-at-a-distance to me (removing global $ic2 affects validation of a function that doesn't mention it at all). Any thoughts @fitzgen (he/him) / @Alex Crichton / anyone else?

(validating with latest main of wasm-tools, using wasm-tools validate -f all file.wat)

view this post on Zulip fitzgen (he/him) (Feb 23 2024 at 17:18):

Any function that isn’t exported needs to be in an (elem declare …) element for you to ref.func it

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:18):

Ah yeah this is expected behavior (albeit with a bad error message), this came about with the reference-types proposal

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:19):

IIRC the intention was to enable runtimes to, before the code section has arrived, be able to enumerate functions which could "escape" through globals/tables/etc

view this post on Zulip Chris Fallin (Feb 23 2024 at 17:19):

ah, great, I had missed that; thanks!

view this post on Zulip Notification Bot (Feb 23 2024 at 17:20):

Chris Fallin has marked this topic as resolved.

view this post on Zulip Joel Dice (Feb 23 2024 at 17:22):

Thanks for working on this @Chris Fallin. I naively tried to use typed funcrefs in componentize-py before realizing they weren't implemented yet. I look forward to revisiting that.

view this post on Zulip Chris Fallin (Feb 23 2024 at 17:22):

yup, I had a realization that they are exactly what I want for "just call a native function pointer with no checks plzkthx" performance

view this post on Zulip Chris Fallin (Feb 23 2024 at 17:22):

thanks folks (fitzgen I think?) for implementing them :-)

view this post on Zulip Joel Dice (Feb 23 2024 at 17:24):

Should I take that to mean typed funcrefs already work in recent versions of Wasmtime? If so, that's awesome.

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:25):

I think that call_ref should work yeah, but I'll also note that the perf isn't quite there yet. Right now call_ref still does the fully general typecheck

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:25):

I don't think we've implemented the optimization where the type information from validation flows directly into translation

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:25):

that's what would enable completely skipping typechecks and such

view this post on Zulip Chris Fallin (Feb 23 2024 at 17:25):

my experiments last night showed a null check still (and there's a comment in visit_call_ref about removing it by threading type info, yeah), but no typecheck?

view this post on Zulip Alex Crichton (Feb 23 2024 at 17:26):

oh I must be misremembering the instruction then, I thought call_ref took a funcref as opposed to a (ref $ty)

view this post on Zulip Joel Dice (Feb 23 2024 at 17:26):

Does anyone happen to know if typed funcrefs work in Node and/or recent browsers (e.g. if I were to use them in componentize-py and run the result with Jco)?

view this post on Zulip fitzgen (he/him) (Feb 23 2024 at 17:27):

https://webassembly.org/features/

view this post on Zulip Chris Fallin (Feb 23 2024 at 17:27):

they're a prereq for GC, so according to that ^^ at least FF and Chrome, but not Safari I guess

view this post on Zulip fitzgen (he/him) (Feb 23 2024 at 17:28):

it pretty much folded into the gc proposal, and browsers don't generally differentiate at this point


Last updated: Dec 23 2024 at 12:05 UTC