-
Notifications
You must be signed in to change notification settings - Fork 695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define a start function. #398
Comments
I think it makes sense for two reasons: first of all, as you say in a non web-based world, it makes sense to have such a method to be able to go there. Second, if we have that, it can help perform bigger tests than what the assert system allows (especially since the asserts are now considered only to use constants :)). However, if this is out of scope of the MVP or not is a different question. In my mind, I think you have defined it well:
You would have to add a bit more information since you can have multiple modules, it seems important to state that multiple main methods would then be semantically wrong, in order to define only at maximum one point of entry to a WASM method |
This is actually something we've talked about a few times, including on the Web. ES6 modules already have a We could leave the exact timing of the execution of |
I have then so many questions because I'm very interested in this issue. Does this then belong in the design document? |
The idea of performance hints seems promising. Maybe we could generalize to On Mon, Oct 12, 2015 at 12:00 PM, jcbeyler notifications@github.com wrote:
|
@titzer I think "cold start" has thrown you off ;-)
I think we'd want to leave it open so that the host environment can call it whenever, just so long as On a random note, @sunfishcode pointed out that |
#119 contains some previous discussion on the platform-specific bits of this issue. Worth thinking carefully about which stuff should be in the wasm module's main and which stuff should run in the host (native or JS or otherwise). I think anything browser-specific shouldn't be specced to live in the module's function table (a web-only |
@lukewagner : if I wanted to add this to the MVP, how would I go about it and am I welcome to try? :) I like the export declaration attribute to do this in a "transparent" manner. |
@kg We're talking about something not browser-specific here. @jcbeyler You are indeed most welcome. First step is to add to the design docs, probably Modules.md (intro section) and Modules.md#integration-with-es6-modules to mention this extension. Thinking a bit more about the specifics, I would probably decouple the start function from exports and instead say that modules have (in their header) an optional "start function" identified by index into the main function table (thus, no specific name imposed). This way, your start function isn't necessarily exposed for arbitrary calls by the outside world (which exports are). Then, if you're feeling brave, you could add it to spec/ml-proto along with some tests :) |
Seems to be no need to distinguish between a cold and warm start etc as the wasm code can easily note the state once started so the same function could be used for a cold and warm start. |
I'm not sure I understand this proposal. Could you clarify the sequence of events leading to initialization of a program (what the VM does, which developer code is called). It sounds similar to How does it interact with dynamic linking? |
If a module declares a start function in its module header, that start function would be executed after the instance is initialized and before the host calls any exports (if any). A Unix-style shell program could use
This function would not be supplied any arguments nor have any return value. If a host environment wanted to provide
dylibs could have start functions too that would be called when you'd expect (at load-time or before returning from |
OK, so it sounds like there are two things worth borrowing from UNIX-y systems:
|
@jfbastien Yes, that is what we're talking about. It seems worth discussing whether we actually need a separate start function and array of functions that run before start; it seems simpler to just give the module a single start function and let it do the rest. |
Agreed that the moral equivalent of FWIW Windows does interesting stuff with |
Yeah, it's definitely worth considering having a "thread start function" when we have threads. |
Ok, sounds good to me and I agree with the _start being the idea of what we want. I like not having the name exposed but instead can be defined as an attribute of the module. I'll start on this later this week most likely :) |
Would you define a list of attributes, or just the one? That's probably something @dschuff should participate in, since it has to do with dynamic linking. |
I was going to define one attribute for the module. We do have to think of order since the file can contain multiple modules it seems that you would want to have determinism in the order of each module's _start. |
@jfbastien I was thinking this would just be another module top-level declaration (sibling to @jcbeyler The .wast file format consumed by ml-proto should be considered a host-specific detail, not part of the wasm spec (that's why |
I'm not sure I like having a top-level statement in the module, versus having a function attribute. |
If you're just talking about TextFormat.md, then sure, I'm not talking about that above. But in the AST/s-expr format, I think a top-level statement is subjectively better because:
|
OK I see your point: |
Is it wise to limit it to 1? Wouldn't that prevent static linking of libraries that each have their own |
We discussed this briefly above. Agreed static linker should be able to do the gluing. |
Started this in the design first: I've started getting "unrusty" with OCaml but would rather get the details of the design handled to ensure I'm doing the right thing in the spec/ml-proto :) So criticize and comment away, I've kept it simple for now and letting you tell me what you would like to see: more details, etc. |
@jcbeyler Sorry for the delay. I think that looks great! Could you create a PR in this repo? |
And now it's me that apologizes. It seems I totally missed this conversation moving forward. Here is the PR #495 |
With #495 merged, this is fixed. |
Copy/pasted from #495 We've started some discussion about how this should integrate with emscripten in emscripten-core/emscripten#4218 It's not really clear from the current text in the design repo how it should work with the web embedding. e.g. when you instantiate the module, is the VM expected to call the start function automatically (if so, when? before Wasm.instantiateModule returns?), or should that be done by the enclosing JS code? I think it should be put under the control of the JS code. For example (as a strawman) the instance object returned by Wasm.instantiateModule could have a way to determine which function is the start function, and then the JS would have to call that function before calling anything else on the instance. Or just have a method with the same name on every instance that is called by the JS, which itself calls the start function. Or whatever. The point is that it would allow the JS to instantiate the module, then modify the linear memory and do whatever JS wrapper stuff it would need to, then call the wasm start function (which would presumably then call its own global initializer functions). |
@dschuff What I had in mind was supporting code that could both run in a web browser and stand-alone, so that the start function be called in a manner that would work in both contexts and independent of a scripting language in the embedded. If the embedder is doing a lot of preparation work then this would not fit this model, rather the preparation is intended to be done by the wasm instance when starting. |
You could specify it in a way that would work for both use cases. Actually you'd want to support standalone applications in both web and non-web environments, plus "library"-type applications (where the expected use case would be that the wasm module has a bunch of exports and JS just calls what it wants). e.g. you could say that compliant implementations must ensure that the start function is called before any other import. For standalone non-web implementations, that could still have multiple interpretations; e.g. an AOT compiler could compile the whole thing to a linux executable with the start function being called by some main() wrapper function. Or if you had an interpreter shell, it would call the start function itself. In the browser the VM could instantiate the module without calling the start function itself, but throw an error if the JS code tried to call an import before calling that. |
@dschuff I don't see why the app should be controlled differently when embedded in a browser versus being embedded elsewhere? So long as both environments support the required APIs then the app would be expected to run. If the wasm app is designed to be able to bootstrap itself from the start function then why shouldn't it do so when run in a browser too? I think the higher level design of wasm is going in the wrong direction, too web developer centric and depending on a web scripting embedded even for download and pre-assembly, rather there should be wasm mode of operation that does not depend on a web scripting embedder but still works on web browsers. What are the challenges that block the wasm code bootstrapping itself from the start function? |
Allowing the instantiation (i.e. allocation, validation, possibly compilation) to be separated from actually running the module's code has advantages even if the module requires no special outside initialization. For example if the compilation is expected to take a long time, it could use an asynchronous API to avoid blocking the main JS thread. (Furthermore, allowing allocation to be split from validation and compilation would allow re-use of compiled module code for more than one instance of the same module). I totally agree that an app should just run if the environment supports all of the APIs it needs. If the app is designed to bootstrap itself, then the environment (be it web, node, or non-JS) would just instantiate it and then call the start function. Arguably the wording in the design doc allows this already, and it is outside the scope of the spec. I'm just advocating that we take it into account when designing the web embedding, so that we can achieve both goals: things that can work everywhere do work everywhere, and things that need or benefit from different handling in the web environment can work also. As to your question, @kripken can say more, but in the emscripten case, emscripten needs to modify the application's linear memory (for example, to preload file contents into memory) before the application's code starts. If there is just one call that allocates the linear memory, compiles, and runs the module, then that will not be possible. But as I mentioned in my first paragraph I still think there are benefits to allowing it to be split, even independently of that. |
The spec says this about the start function:
Which suggests it can be called lazily, some time after initialization, but before anything else is called. This is fine except that
My suggestion is that the start function execute immediately after initialization, i.e., synchronously. In practice, that means emscripten wouldn't use a start method, it would just export what it needs for initialization, and then it can call it at the right time, which might be later e.g. if the application preloads files or has other async dependencies, as mentioned above by @dschuff. |
We haven't implemented the start function yet in SM, but my expectation was that it would simply be called at the end of Being able to do async initialization is an important use case, though. For lack of support, apparently many node.js modules have an implicit race condition between the completion of an async operation fired off during their module initialization and the first time one of their exports is called. To address this, iiuc, the tentative JS plan is to allow the new |
While wasm can export functions, a use case might be running a stand-alone wasm application and if so then it seems appropriate to define a cold-start function. This could be used in self contained wasm code that does not depend on wrapper user code to launch it. What if the wrapper code itself were wasm code - this needs an entry point. What do people think, should a
main
cold-start entry point be defined in the spec, or is this out of scope?The text was updated successfully, but these errors were encountered: