Skip to content
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

Fill in a more detailed sketch for GC/DOM/Web API integration #275

Merged
merged 4 commits into from
Aug 5, 2015

Conversation

lukewagner
Copy link
Member

Over the last few weeks, I had several chances to talk to Mozilla DOM/WebIDL folks about how WebAssembly/Web API integration could work. This PR is a sketch of the basic plan we discussed which breaks down the overall goal of "GC/DOM integration" into two WebAssembly features (independent of JS/Web) and then how these features would integrate with the Web platform. Definitely interested in feedback, esp. from more people with Web API experience.

types* that were similar to and symmetric with
[opaque reference types](FutureFeatures.md#opaque-reference-types)
(just not opaque).
* The GC heap would be semantically distinct from linear memory and thus
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious if there is precedent for this model, of having both a linear memory and a GC heap, in the same VM. I can't think of one offhand.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++/CLI :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, yes. IIUC, in C++/CLI, one can allocate e.g. C# structs on the regular C++ stack, which seems quite different than for us. Although I suppose that might have been mostly a syntactic sugar issue, and the compiler did actually manage two separate stacks, and so we are closer to the output of the C++/CLI compiler than its input.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC .NET maintains a single native stack, which is safe-enough because the only way to get the address of something on the stack (or read/write directly from addresses) is to drop into unsafe mode. Anyone using pointers in C# is interacting with this too, even though C++/CLI's access is more powerful.

.NET structs allocated on the GC heap either live in a box or inside a reference type, so they're never actually allocated directly on the GC heap. They are effectively native values, just like in C. They do have the ability to hold object references, though, so in my experience the runtime rejects any attempt to store any struct containing GC references into the native heap - only allowed to put it on the stack or in the GC heap.

I think their model works pretty well, but we have more stringent safety/robustness requirements, and we can't protect the stack as easily as they can since raw memory access is a baseline for us.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC (not a C# expert), C# structs are value types and so you cannot point at them with a reference. Thus, to compile a C# struct to wasm, we could decompose the struct into scalar locals such that all field references were just local accesses. (I guess array-typed fields of structs would require the heap-stack unless we extended wasm with fixed-size array local types... maybe not a bad idea :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, @kg beat me to it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI about .NET value types (C# structs):

  • Normally C# structs are located on the stack, or 'inline' inside other objects (reference types). But you can also 'box' a value type and then it will be located "directly" on the heap (with a 2-word header, like a reference type). IIRC C++/CLI (but not C#) allows you to interact with boxed value types.
  • You can make references directly to C# structs (located either on the stack or on the heap). Such references can only exist on the stack. Such a "managed pointer" is used as the 'this' pointer when you call a method on a value type, as well as when you pass a value type by reference. C# only allows such references to be created as part of a method call, but CIL bytecode lets you create them at any time.

Oh, and D has a more relaxed model than .NET, with pointers that don't care if they point to GC memory or not (compared to 'managed pointers', the key difference is that such pointers can exist inside heap objects).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so in the case of struct methods or by-reference passing, C# structs would need to go on the heap-stack unless wasm provided a similar sort of feature.

@lukewagner
Copy link
Member Author

@davemichael I think weak handles should definitely be considered for both WebAssembly and JS and there is long-standing demand from JS. It's easy to miss, but this is explicitly mentioned as an alternative to consider in the "Opaque reference types" section by the "Cells that hold a weak reference." bullet. But this could be generalized so that not just cells, but also fields of GC objects could be weak.

It's great to see your GDoc, iiuc, coming to a similar conclusion as what is proposed here.

For the last question, I have a proposal buried in #104 for a hybrid model that, I believe, offers the best of both worlds. From the perspective of WebIDL bindings, though, you can identify threads with workers which really simplifies the story for the rest of the browser.

@davemichael
Copy link

Thanks! Overall, I really like this proposal, thanks for writing it and working on it.

Re: the proposal about the thread model... (i.e., what threads can use what opaque handles and what APIs). In particular...
"What happens when a non-main thread calls an import that (in a browser) is JS? (This whole idea from @ncbray) The calling thread would block and the call would be executed on the main thread of the module"
This is interesting. I'm assuming the developer has access to this main thread of the module (it's not hidden; they can schedule timeouts there, etc), and can make calls from there? This bears some similarity to how Pepper handled threads. Virtually all APIs could be used on all threads. The main thread was "special" in that it needed to not hang so that calls could come and go appropriately. For that reason, we had this model of completion callbacks:
https://code.google.com/p/chromium/codesearch#chromium/src/ppapi/c/pp_completion_callback.h&l=93
...that allowed you to make calls in a "blocking" way, but only on non-main threads. Another useful option was "OPTIONAL", which matters for things like IO. If there's data in the buffer, you can deal with it immediately instead of having to pop the stack and handle a callback later. Not sure if a similar concept would be useful in the bindings for WebAssembly.

Is the main thread of the module (for cases where there is a JS context) actually going to run on the same thread that the JS context lives on? It seems like it should, to avoid any extra overhead when interacting with JS. It would obviously always be an "event loop" type of wasm thread.

Sorry if I'm asking stupid questions addressed elsewhere ;-). If there's any chance our battle scars with Pepper matter here, I wanted to offer some info on what worked for us and what didn't. I think ncbray knows enough about Pepper, though, that he's probably largely filled you in.

@lukewagner
Copy link
Member Author

The completion callback idea makes sense and seems similar to what we'll need to do for callback function types. The "OPTIONAL" strategy sounds useful; I think to add that we'd need to add it to the Web API itself, not at the wasm/WebIDL-integration level.

Is the main thread of the module (for cases where there is a JS context) actually going to run on the
same thread that the JS context lives on?

Yes, and synchronous calls to/from JS/Web APIs would share the same (trusted) stack.

Sorry if I'm asking stupid questions addressed elsewhere ;-). If there's any chance our battle
scars with Pepper matter here, I wanted to offer some info on what worked for us and what didn't.

Happy to have all these constructive questions and learn from Pepper experience. I realize that there are some things still lacking, viz., being able to directly share a resource between threads without doing this blocking-cross-thread communication. My expectation here is that we should have a v.1 which makes minimal asks of the rest of the browser and then build on that by proposing new Web APIs (perhaps a MutableFile that was directly shareable between threads).

@lukewagner
Copy link
Member Author

(rebased) Any more comments to address before merging or objections?

@jfbastien
Copy link
Member

I defer to @ncbray and @davemichael's wisdom in this area.

@titzer
Copy link

titzer commented Aug 4, 2015

I think the discussion of cells for holding opaque reference types is too
detailed and that we should preserve the mystery about how exactly opaque
reference types are mapped to integers and back for storage into the linear
memory. Therefore I would advocate dropping that language about cells.

Let's avoid being too detailed in Future Features itself. Maybe split off a
separate document and file some issues for discussion?

On Tue, Aug 4, 2015 at 2:55 AM, JF Bastien [email protected] wrote:

I defer to @ncbray https://github.com/ncbray and @davemichael
https://github.com/davemichael's wisdom in this area.


Reply to this email directly or view it on GitHub
#275 (comment).

@lukewagner
Copy link
Member Author

@titzer Done

@titzer
Copy link

titzer commented Aug 5, 2015

lgtm

On Tue, Aug 4, 2015 at 9:07 PM, Luke Wagner [email protected]
wrote:

@titzer https://github.com/titzer Done


Reply to this email directly or view it on GitHub
#275 (comment).

@lukewagner
Copy link
Member Author

Merging, based on lgtm from @titzer and positive comments from @davemichael. Happy to iterate further in future PRs, of course.

lukewagner added a commit that referenced this pull request Aug 5, 2015
Fill in a more detailed sketch for GC/DOM/Web API integration
@lukewagner lukewagner merged commit 15ede79 into master Aug 5, 2015
@lukewagner lukewagner deleted the fill-in-webidl branch August 5, 2015 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants