Giter Site home page Giter Site logo

Comments (17)

martindevans avatar martindevans commented on June 17, 2024 1

The binaryen pass modifies the WASM code to support the async machinery.

Then _internal_sched_yield is written by me to invoke that machinery. Essentially it calls asyncify_start_unwind and then catches it with asyncify_stop_unwind when it returns out of the tick call. Next frame the sim will call asyncify_start_rewind and then call tick again, which will restore the stack and finally the yield call "returns" to normal execution as if nothing had happened.

from assemblyscript.

CountBleck avatar CountBleck commented on June 17, 2024

Can you provide more info about the code itself?

Also, what if you add a store<i32>(3, load<i32>(3)); to some parts of the code?

from assemblyscript.

martindevans avatar martindevans commented on June 17, 2024

Can you provide more info about the code itself?

Sure, I'll try to provide more of an overview (and again, sorry this is so convoluted and not a good reproduction at all).

Here's some snippets of the program, stitched together into something representative of what's going on:

// Import a method from the C# sim
@external("protologic", "sharedmemory_set_readaddress")
declare function _internal_sharedmemory_set_readaddress(addr: StaticArray<u8>, len: i32): void;

// Setup some memory on the heap
let _data: usize = heap.alloc(DATA_SIZE);

// Tell the sim about this address
_internal_sharedmemory_set_readaddress(_data, DATA_SIZE);

// There are lots of methods like this, that load from known offsets
get_some_important_number(): i32
{
    // Note alignment of one, some values in the buffer are unaligned so we tried loading every value
    // with this alignment, but it made no difference. The number we're looking at here _is_ correctly
    // aligned anyway.
    return load<i32>(_data, 52, 1);
}

// This method is called once at the start of the sim
export function tick(): void
{
    while (true)
    {
        // Depending on exactly how other bits of seemingly unrelated code are arranged, this may or
        // may not get the right value. e.g. simply printing out some other values, dependant on the value
        // read here might change the result!
        let number = get_some_important_number();

        // This causes the C# engine to do an asyncify unwind, and then rewind back in here next frame. In
        // this way the program is "always running" for the entire duration of the sim. While the WASM is
        // suspended fresh data will be written to the buffer that was registered with 
        // `_internal_sharedmemory_set_readaddress`.
        yield();
    }
}

// The C# sim implements sched_yield to trigger an asyncify unwind
@external("wasi_snapshot_preview1", "sched_yield")
declare function _internal_sched_yield(): i32;

function yield()
{
    _internal_sched_yield();

    // We've tried a few things here. e.g. calling `_internal_sharedmemory_set_readaddress` again every
    // frame just before or just after yielding. This changed the results, but it was never correct - e.g. in
    // some cases the reads after the yield would be wrong, in others reads before the yield would be
    // wrong! No combination (even doing it before _and_ after) got correct results.
}

store<i32>(3, load<i32>(3));

I can try that, do you want me to add any logging of results or anything?

from assemblyscript.

CountBleck avatar CountBleck commented on June 17, 2024

Just see if that fixes the issue.

from assemblyscript.

HerrCai0907 avatar HerrCai0907 commented on June 17, 2024

Which assemblyscript version did you use?

Which target did you use to execute? According to your description I guess it is compiled wasm binary directly.

from assemblyscript.

HerrCai0907 avatar HerrCai0907 commented on June 17, 2024
@external("protologic", "sharedmemory_set_readaddress")
declare function _internal_sharedmemory_set_readaddress(addr: StaticArray<u8>, len: i32): void;

StaticArray<u8> in API definition is very suspicious.

I propose if you want to communicate between AS and lower runtime, the best practice is use C like memory manage solution. You can call heap.alloc / heap.free / memory.data. And pass this address as usize/u32 to lower runtime.

wasi is a good example to handle it.
https://github.com/AssemblyScript/wasi-shim/blob/main/assembly/wasi_internal.ts#L11

from assemblyscript.

CountBleck avatar CountBleck commented on June 17, 2024

@HerrCai0907 He has tried both heap.alloc and memory.data. Technically StaticArray<u8> works, since it directly points to the data (like ArrayBuffer and String).

from assemblyscript.

martindevans avatar martindevans commented on June 17, 2024

StaticArray in API definition is very suspicious.

Sorry that was a mistake! We tried StaticArray as another option instead of heap.alloc. It should be a usize parameter.

Which assemblyscript version did you use?

Version 0.27.22

According to your description I guess it is compiled wasm binary directly.

That's correct, it's compiled to a wasm binary and then passed through binaryen to apply asyncify. Obviously we can't turn off binaryen (since asyncify is critical to the whole thing) but we have tried running both AS and Binaryen with no optimisations (just i case it was some kind of misoptimisation, which it does feel like).

from assemblyscript.

martindevans avatar martindevans commented on June 17, 2024

store<i32>(3, load<i32>(3));

Adding this into the yield function (both before and after the actual sched_yield call) made no difference.

from assemblyscript.

HerrCai0907 avatar HerrCai0907 commented on June 17, 2024

@martindevans Who provide _internal_sched_yield?
Is it binaryen async pass will transform it to normal wasm code or C# runtime provide this API function.

from assemblyscript.

CountBleck avatar CountBleck commented on June 17, 2024

store<i32>(3, load<i32>(3));

Adding this into the yield function (both before and after the actual sched_yield call) made no difference.

Did you try adding it inside get_some_important_number before the load?

from assemblyscript.

Avril112113 avatar Avril112113 commented on June 17, 2024

Yes, that was tested, both directly before and after the load() call.

from assemblyscript.

github-actions avatar github-actions commented on June 17, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in one week if no further activity occurs. Thank you for your contributions!

from assemblyscript.

HerrCai0907 avatar HerrCai0907 commented on June 17, 2024

This problem may be due to incompatibility between AS gc and binaryen async, but it is just a guess and I has not tested it.

from assemblyscript.

github-actions avatar github-actions commented on June 17, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in one week if no further activity occurs. Thank you for your contributions!

from assemblyscript.

CountBleck avatar CountBleck commented on June 17, 2024

@martindevans did you fix the issue?

from assemblyscript.

martindevans avatar martindevans commented on June 17, 2024

Unfortunately not. I never managed to pin it down to anything more specific than the very vague issue I described in the initial post.

from assemblyscript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.