- Where: zoom.us
- When: July 21st, 4pm-5pm UTC (July 21st, 9am-10am Pacific Daylight Time)
- Location: link on calendar invite
None required if you've attended before. Send an email to the acting WebAssembly CG chair to sign up if it's your first time. The meeting is open to CG members only.
The meeting will be on a zoom.us video conference. Installation is required, see the calendar invite.
- Opening, welcome and roll call
- Opening of the meeting
- Introduction of attendees
- Find volunteers for note taking (acting chair to volunteer)
- Adoption of the agenda
- Proposals and discussions
- Review of action items from prior meeting.
- Phase 1 Proposal for Dispatch Tags (Ross Tate) [15 minutes]
- Ideally with vote
- Discussion of stack inspection (Ross Tate) [15 minutes]
- Need CG feedback in preparation for stack-switching design
- Closure
None
None
- Adam Klein
- Alex Syrotenko
- Alon Zakai
- Andreas Rossberg
- Arun Purushan
- Ben Smith
- Conrad Watt
- David Piepgrass
- Derek Schuff
- Francis McCabe
- Heejin Ahn
- Ioanna Dimitrou
- Jacob Mischka
- Jakob Kummerow
- Jay Phelps
- Jlbirch
- Keith Miller
- Luke Imhoff
- Luke Wagner
- Mingqiu Sun
- Nick Fitzgerald
- Paolo Severini
- Paul Dworzanski
- Petr Penzin
- Rich Winterton
- Rick
- Ross Tate
- Ryan Hunt
- Sabine
- Sam Clegg
- Sergey Rubanov
- Sven Sauleau
- Syvatoslav Kuzmich
- Thomas Lively
- Tobias Tebbi
- Wouter Van Oortmersson
- Zalim Basharov
- Zhi An Ng
Francis McCabe seconds
Phase 1 Proposal for Dispatch Tags (Ross Tate) [15 minutes]
Slides for Dispatch Tags (pdf) (pptx)
[Ross discussing capability leaking slide]
AR: That's not what's going to happen in the current proposal…
RT: You're describing the new process where you're sealing and unsealing a type, but it can still happen. It's also just one of the issues that can happen here.
[Back to slides]
AR: How is that different from the RTT in the GC proposal. Seems similar, except it also allows you to specify tag on function definition. Then call_indirect is downcast.
RT: RTT currently has a nesting depth, and array lookup, etc. This is much smaller.
AR: I agree, that is more general… is it a subset of that?
RT: There's no connection to GC for this
AR: In what sense?
RT: This could just be a code pointer, if you're in a setting where a funcref is just a code pointer.
AR: I agree, it's just about GC types. You could factor out RTT from GC proposal, and so I think it's kind of the same thing.
KM: Does the GC proposal give you a way to show that a tag doesn't escape the module?
AR: Escaping means that you export it or pass it out in some other way. There's no difference there.
KM: i can fork my tag, they are identical tag, one is internal and another is exported, how would you say the same thing in the GC proposal, maybe i’m just confused.
RT: Another thing is that you can do multiple tags, useful for OO, you have a tag for each interface method. They don't have to have a subtype relationship.
LW: call_indirect will do a sequence for each interface method
RT: If we do allow multitag thing -- then the receiver has associated multiple tags then it can do multiple checks, it could be a switch or some other way. I can go into more detail later.
LW: can see how the more general case can allow more general things, nice thing about current RTT (with the number to order), you can always do the check in a single constant load comp, if tag, it is as certain offset, constant instruction to do the check regardless of how many tags it has
RT: Generally with this strategy its the callee that does the tag checking. The applications of this -- the tags are all the same depth.
AR: isn’t it an implementation detail who does the actual check?
RT: It's an implementation detail, yeah.
LW: even if callee does the check (with RTT), seems like callee can do a single constant time check, could they?
RT: With the RTT one you have to cast on the first side, to know if you even want to do it.
AR: Here you kind of fuse these two operations, which gives you the ability to do it on the other side, I wonder what you gain by it. So far it looks like we don’t gain anything. Will be the same check on either side.
RT: Right now it's a little hard to compare against something that doesn't exist yet -- your function ref proposal has meta information that is associated with it. This requires two indirect reads.
RT: no rtt with this
AR: but the object has one, if it’s not in the object, it is in the function prefix. Different function type then.
RT: let me go with the extension. Will concretize.
BS: usually we will timebox, but you have both agenda items.
[Ross presenting extension slides]
AR: These functions, if you want to do the dispatch callee-side, you need the tag. Which means that they have different calling conventions, so they would need other types as well.
RT: the way this is implemented, for interface method systems. You push all args on stack, also push tag onto stack, then receever looks at tag, then it check if it’s the tag it is looking for. If it is not the one, it traps.
AR: I mean that this assumes that both sides know -- callee knows and caller knows that they have an indirect dispatch call.
LW: need a separate indirect_call entry point, there is a separate prologue called by call indirect as a constant offset from typed entry point. For n=1 how we implement call indirect, if stack matches it is the right layout, callee starts with a branch. If we add more tags it will be a sequence of checks.
AR: So every function in your implementation has this extra prefix that allows it to be called with call_indirect.
LW: only a few bytes, can optimize using is_alias predicate
AR: This would become a required implementation technique, then.
LW: if you add dispatch funcs, seems useful in general, powerful tool
BS: unanimous vote for phase 1?
No objections, proceed to phase 1.
Slides for Stack Inspection (pdf) (pptx)
RT: Discussion I want to have: do we want stack inspection or not? What are the challenges? This will affect how we design stack switching.
FM: looking at slide on two-phase exception handling, the last call_stack_from $outer, the function you’re calling is at the bottom of the stack (most recent part), “this” function is executing at the bottom of the stack
RT: call_stack_from to ignore part of the stack, start searching from this place up
FM: Ah, I see. That's complicated to figure out how to do...
RT: one more slide on stack walking
[Ross presenting "Stack Walking" slide]
AR: Meta-thing -- on the web you have to be very careful with features like this. In JS, they tried to restrict the things you can learn about the stack. .caller and .properties, those were very....
RT: you can only look for very specific information (based on the tag)
AR: You might still want to be able to protect against -- there have to be boundaries. When you use delimited continuations, it allows you to put in those boundaries.
RT: there’s stack walls, can’t walk up past this point, like timing behavior, leaks information. There are devices people use to limit stack walking, trying to get at the basics here.
AR: I think once you put that all into place, it seems like it will end up being delimited continuations or effect handlers. I'm just curious if that will solve the problem, instead of specialized mechanisms. It's unclear how they would all work together. W.R.T. stack walking, on the web at least is that the stack is heterogeneous, you'll have host stack frames or JS frames, or from wasm stack frames from another runtime. There might be some of your own further up. If you want to implement GC with this, I think you'll have to answer some hard questions about this, walking stack for frames you don't understand.
RT: already answered, you can only look for tags you can answer. You explicitly state what you look for, people have to explicitly state they have information for a tag.
KM: host function that has a mean to give it some reference, some callback that can vend you back an object pointer. Holding it in some heterogenous frame you don’t know about. I”m module A, I need to call some host function that has a callback which will call me later, at some future time, e.g. schedule task on run loop, need to give it my object. I need to know that the closure variable is in the other frame. Either the caller has to flush it somewhere (like ref count).
RT: It sounds like what you're talking about is a linear memory GC, not stack walking. Yeah, if you give one of your objects elsewhere, you need to give a root.
KM: it wouldn’t solve all your problems..
RT: Right, it would solve some problems, like the problem of dealing with a shadow stack (which is inefficient)...
KM: I’m unconvinced it is inefficient. You’re maintaining a shadow stack of all your frames to iterate, you only have to flush whenever you make a call, identical to what the VM is doing, vm has to save values somewhere it can find value later.
AR: Storing all these answer handlers won't be cheap either.
KM: you need a stack map, hash map of stack maps for values and where you save them, there are possibly optimizations you can do, you can allow callee saved registers, and asked callee where it was saved, only possible optimization VM can do that shadow stack can do, not convinced it is valuable.
RT: are you saying vms, does Java vm maintain a stack trace wherever you go? Do you think java maintains a shadow stack everytime it executes the code.
KM: You can recover that already from existing things -- at least in the web VMs, you can get the wasm stack, and recover the information from it.
RT: you can do that
KM: java vm can do that
RT: java vm can do that because it knows return address
KM: I could write a Java VM in wasm that could recompute this data. You would need to know what java line offset maps to which wasm offset.
RT: you have to maintain the return address. You’re asking people to maintain that, which the host vm has.
LI: Have either of you gone to the debugging meeting? They have a way to handle code mapping with DWARF that already works. There's a meeting this Thursday.
LW: the debugging support isn’t exposed to live content, only activated from browser debuggers, what RT is talking about there is a first class feature
LI: Only for the debugging purpose. For other stack walking… Keith what you're talking about is what the debugging DWARF support does.
KM: you can still implement… today if you want you can implement this, not saying there’s never any world you wouldn’t want this first-class in Wasm. This functionality exists. I don’t know how performance sensitive that is. Agree that it will be a large burden on producers to do it the way I was describing.
RT: Similar to exception handling. We could implement EH as it is, but it's way better for code compactness, for performance,...
AR: i don’t think you can implement it, can you. Heterogenous stack problem, how do you unwind over host frames.
KM: You just need to know your own frames, right?
RT: composability issue. The shadow stack works well if you code stays within itself. Once you go into someone else, it’s much more difficult to coordinate the unwinding across modules.
AR: The problem isn't the shadow stack, the problem is convincing the other code to unwind...
RT: coordination
AR: you cannot do that without exposing… e.g. higher-order functions, you cannot do that without changing its type, not a local transformation. Exceptions are adding expressively.
RT: But that also applies to everything I have here [AR: I agree] So if we agree that exceptions require this, then it seems weird to say stack inspection doesn't.
AR: q isn’t what way you want to provide, whether ad-hoc, whether it is expressible with more general - that is an effect handler isn’t it, you are invoking an effect, and handler answers
RT: The details matter, your effect handler mechanism requires continuations...
AR: more general, this is one of the specific cases. Have one general case, rather than specific ones, and how they interact
RT: To be clear, your mechanism says that to build this requires a new continuation, right?
AR: not necessarily, i’m not saying i have all the answers, i’m asking how many of these special mechanisms we want to have. One thing clear to me is, you want to separate the general part where you need continuations, from the specific part where you don’t need separate stacks. There are two mechanisms, do we need more than that? E.g. current EH proposal, with a simple resume mechanism which is not first-class, that is equivalent to what you are describing - answer is a try.
RT: High level, you agree that we need stack inspection, but the question is how to do it.
AR: more generally, you want to be able to express stack inspection, but does that require specialized mechanism
RT: not sure how to implement these except what KM suggested
AR: For example, if you add restricted resumption to EH then you have an equivalent thing.
FM: beg to differ, how would you use that for debugging
AR: for debugging, we need to be careful, separate from language semantics. There are things debugging should include that the language shouldn’t, need to keep them separate. Might have reasons to include some features in both.
FM: important principle there that when you are debugging, you want to be doing it in the semantics of the language you are debugging (source), not Wasm.
AR: you want to expose source level
RT: you want to be able to …
AR: agree that debugging interface, whether language feature or not, has to have a place to do that
LW: debugging subgroup working on this, and has made progress, and +1 to separate debugging interface with core language
BS: RT, do you feel like you have some answers?
RT: no definitive answer, discussion went productively
KM: one possible useful point, regardless of my feelings on stack inspection, I can guarantee that i will be blocked from shipping this (by my bosses), until GC proposals is in place, for the fear that people will use this
BS: more discussion should go on GitHub issue.