Stream: wit-bindgen

Topic: ✔ Return area for struct


view this post on Zulip Zihang Ye (Aug 12 2024 at 03:58):

Hi,

I have a question about when a post-return is needed, especially for the case of a struct.

Suppose I have the following WIT:

world app {
  record point {
    x: u32,
    y: u32,
  }
  export add: func(a: point, b: point) -> point;
}

It seems that since it's returning a struct containing two fields, a return pointer is needed. However, the guest_export_needs_post_return decided that it does not need post-return since neither the field inside the struct needs one. So my question is, who is responsible for freeing this area? Because I didn't see a cabi_realloc call in the transpiled js, either.

Thanks.

view this post on Zulip Alex Crichton (Aug 12 2024 at 14:31):

The guest_export_needs_post_return function is mostly a heuristic and it's not required to be used. The post-return feature is always optional. Rust for example allocates this return area in static memory so it doesn't need a dynamic allocation, but other languages can customize as needed.

view this post on Zulip Zihang Ye (Aug 13 2024 at 05:00):

Alex Crichton said:

The guest_export_needs_post_return function is mostly a heuristic and it's not required to be used. The post-return feature is always optional. Rust for example allocates this return area in static memory so it doesn't need a dynamic allocation, but other languages can customize as needed.

I see. But is there a size there will be big enough? For example, if there's a struct containing 100 fields with u64?

view this post on Zulip Zihang Ye (Aug 13 2024 at 05:14):

Also I tried to add post-return function, and this is what I got with the transpiled JS:

function add(arg0, arg1) {
  var {x: v0_0, y: v0_1 } = arg0;
  var {x: v1_0, y: v1_1 } = arg1;
  const ret = exports0.add(toUint32(v0_0), toUint32(v0_1), toUint32(v1_0), toUint32(v1_1));
  postReturn0(ret);
  return {
    x: dataView(memory0).getInt32(ret + 0, true) >>> 0,
    y: dataView(memory0).getInt32(ret + 4, true) >>> 0,
  };
}

I wonder who's responsible for freeing the point?

I mean, if the post return is called before the dataView is accessed?

view this post on Zulip Alex Crichton (Aug 13 2024 at 17:31):

The return area is allocated per-function IIRC and is appropriately sized to that function. Either that or it's a maximal size for a set of functions, I forget which. Regardless though you would have to make sure it's big enough yeah.

view this post on Zulip Alex Crichton (Aug 13 2024 at 17:31):

I mean, if the post return is called before the dataView is accessed?

ah yes postReturn0 would have to be called after the return value is constructed

view this post on Zulip Zihang Ye (Aug 14 2024 at 01:51):

Alex Crichton said:

I mean, if the post return is called before the dataView is accessed?

ah yes postReturn0 would have to be called after the return value is constructed

I created an issue about this: https://github.com/bytecodealliance/jco/issues/484

Observation inside echo.component.js: function run() { const ret = exports0.run(); postReturn0(ret); // <- Here, the post return is called before the data gets constructed return { x: dataView(memo...

view this post on Zulip Zihang Ye (Aug 14 2024 at 01:54):

Alex Crichton said:

The return area is allocated per-function IIRC and is appropriately sized to that function. Either that or it's a maximal size for a set of functions, I forget which. Regardless though you would have to make sure it's big enough yeah.

I see what you mean. I suppose that's also what teavm-java has done. I'll see what I can do on my side.

view this post on Zulip Zihang Ye (Aug 14 2024 at 02:27):

I may be wrong, but from what I see, the abi::Generator.post_return doesn't seem to deallocate the pointer of the return area either.

I think this ought to be pointed out in the documentation that the return area is not expected to be allocated/deallocated dynamically for exportation.

view this post on Zulip Alex Crichton (Aug 14 2024 at 14:40):

whether or not it's allocated dynamically is up to the guest, the component model doesn't prescribe that it either is or isn't. In Rust at least the area is statically allocated so post-return is cleaning up the return values rather than the area itself. There's no reason it couldn't be dynamically allocated though

view this post on Zulip Notification Bot (Aug 15 2024 at 02:00):

Zihang Ye has marked this topic as resolved.


Last updated: Dec 23 2024 at 12:05 UTC