- Where: zoom.us
- When: October 13th, 4pm-5pm UTC (October 13th, 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.
- Announce next SOIL Seminar presentation for Friday, Oct 23rd (Ross Tate) [2 min]
- Discussion on relaxed dead code validation (Conrad Watt) [30 min]
- SIMD-specific feature detection (Thomas Lively) [15 min]
- Closure
None
None
Thomas Lively Alon Zakai Andreas Rossberg Sam Clegg Fatih Bakir Daniel Hillerström Arun Purushan Ioanna Dimitriou Zalim Bashorov Ben Titzer Francis McCabe Ryan Hunt Lars Hansen Petr Penzin Rick Battagline Mitch Moore Yury Delendik Sergey Rubanov Ross Tate Sabine Paolo Severin Heejin Ahn Conrad Watt Paul Dworzanski Yuri Iozzelli Jay Phelps Emanuel Ziegler Luke Imhoff Adam Klein Mingqiu Sun Asumu Takikawa Rich Winterton Zhi An Ng Till Schneidereit Manos Koukoutos Pat Hickey Luke Wagner Nick Fitzgerald Steve Alex Crichton Jacob Mischka
Zhi An Ng volunteers.
Arun Purushan seconds.
RT: TL gave the first seminar, link to recording, http://soil-initiative.org/seminar/#20201012, next meeting is Fri Oct 23. Donald, student of Arjun, presenting wasm-k. Adding continuations to Wasm, implemented in wasmtime.
Discussion on relaxed dead code validation (Conrad Watt) [30 min]
CW: Following from the previous discussion. Detailed discussion and flag off edge cases.Presenting..
AR: Can you repeat that?
CW: the way currently proposing to handle bottom type is in the rule for appending instruction sequences. If you have e1* and e2*, result of e1* if it has a bottom, it can be subtype into value types or ref types.
AR: yup
CW: issue is, memref type, if you’re within a module that declares no memory type, then no possible memref type you can pick. You just want to skip it. If we had load.memref the current won’t work anymore.
AR: original wasm didn't have this problem as every instruction was self describing. With Gc there will be a lot of annotations.
CW: something i want to speak about. This load.memref example is not real, it’s the cleanest example. There are already instructions in pipeline that are missing annotations. From my POV, we are only adding them in to handle dead code typing, with this proposal we wouldn’t need them.
AR: ben’s argument was that he wants them for an interpreter, doesn’t want to have to look to the actual value in the interpreter
CW: in interpreter during validation, you can tag validation with the type. Maybe I shouldn’t try to argue.
AR: side remark, agree with general analysis.
BT: the point of having more type annotations on instructions is so that you don’t require values to have metadata that you wouldn’t otherwise need. Something that is statically derivable by checking types, the interpreter doesn’t have that, you need to attach that to values. It’s not just performance overhead, and also memory overhead.
CW: depends how the interpreter implements validation. If validation is ahead, then can set it up.
RT: side topic
CW: we have 30mins
BT: try to save memory as much as possible, interpreter typically does not have another pr of the code other than bytes. Maybe side table (small) to annotate some instructions, but not every instruction, waste code space.
RT: annotations you are adding to the side table are annotations you would have to have in the original code anyway. Think this is a side discussion.
CW: this is quite related for interpreters. Already the case that the select instr needs this information, depending on repr of values in the interpreter, some implementations may need to tag select.
<BACK TO SLIDES, last slide on “NOT this meeting - phase 2 poll”>
AR: do you have a slide showing change in typing rules for this proposal?
CW: I can just show it in the proposal I wrote. There is a cheap way to change typing rules that is rather fragile. For the MVP, you could get away with the following change. For things like funcrefs, special case for them, or more involved change.
RT: the bottom row covers boilerplate cases, can add special cases for things like memref
AR: what is OT?
CW: defined above, stealing your operand type thing.
AR: there the OT was slightly different. Not sure how OT is related, it can be anything?
CW: it needs to be OT to match the result type of enclosing block.
BT: something you might have glossed over that i recently realized. If you open a new block in dead code, new block’s body is not dead code anymore. Within the new block, the new code is dead, with this proposal.
CW: we can talk about what we want to have, the rules we have written here haven’t considered that yet. We can change the rules.
BT: won’t work if you have a bytecode iterator, it would have to keep track of control structure, and drop back to regular validation algorithm.
AR: wish we had notes when we discussed it first time round, various cases we weren’t sure what the nicest definition is.
CW: nested block in dead code is not something we thought about, have to go away and think
RT: according to our rules, the block will be typed with what it annotated with, thats sound, can make it better by special case block when input type is bottom
TL: under the current proposed rules, the nested dead block body would not be typed as dead code, will be type of block
CW: also matches the implementation sketch, Ben sketched earlier, the current type stack effect marks as dead, the new block doesn’t have a dead bit set.
AR: you have to remember what is outside
CW: you already have to do that, you have to set the bit
?: not always a stack
RT: can add a rule for blocks. Block has a special rule, if input is bot, ignore the annotated type
CW: the thing that most closely matches what current impl do, is to type the body of a block as not dead.
RT: probably
BT: my interest is making it dead obvious that actual impl of validation is correct and least amount of work with dead code. Allowing blocks in dead code to not be typed as dead code means you have to switch back when you enter a nested block, and seems more complicated.
CW: you already have to do that
BT: a decoder , once reached unreachable, goes to end, don’t mix up validation of imms with validation of type stack.
CW: i talked a bit about it before, my high level intuition is that more code sharing if we just switch off some checks. Impl has logic to switch on opcodes…
BT: don’t think you want to write two versions of validation and put it into the same switch case. You want to factor it such that for an immediate type, you can go from opcode to immediate type, and for immd type you skip, or validate and skip. You don’t want two versions of every bytecode.
RT: currently if you have a block after unreachable, you wil step in, typecheck, step out, then back into a poly stack case. Figuring out how this introduces complexities that aren’t there.
BT: pick any one bytecode, i32.add. If this doesn’t get type check in unreachable, you won’t even push or pop.
CW: in terms of burden on existing impl, v8 already templates validation case pushing and popping. Webkit also has a template that doesn’t push/pop.
AR: wonder why, though
CW: no idea, i’ll use it to my advantage
RT: ref interp, 1 line change
CW: delta for current impl isn’t big.
BT: wrote a substantial part of v8 validator as it is, it is 4k LOC, templated like crazy, for 3 different execution tiers can use it. Don’t think this is the right way to use a validation algorithm. It is this way for a different purpose.
CW: A complicated thing gets a bit less complicated, but not as far as the less complicated thing you’re advocating for.
RT: currently, instructions have to have rules…
CW: in most cases, for current mvp, you can hide a lot behind push and pop. I get Ben's point on code hygiene. A lot of people won’t be set up to deal with that if we go with Ben’s item. This idea doesn’t expose any different between instruction syntax and validation.
AR: with current approach, you can hide completely push and pop.
RT: not true
CW: not true for post-mvp, e.g. load memref
AR: agree, with proposed change, you can’t do that anymore. You have to check every instruction
RT: in ref interpreter, abstraction
AR: ref interpreter is not how you’ll do it
CW: extra slides here to concretize. How SpiderMonkey does the fused decode validate loop.
RT: if type stack is bottom then remains bottom
BT: validation of other immediates, like nesting depth of target of br, suppose you have dead br in unreachable code, invalid depth, you have to track control depth. Which means you need to mix all the logic into the decoding invalidation loop. Cannot make it bytecode iteration thing. At this point you will probably save 0 lines of code in any validation algorithm in any engine.
CW: don’t care as much about LOC, but save some brain power. Which is what this proposal is trying to do.
BT: from implementers, they want confidence that they have handled dead code properly. Up till now, you can hide behind push/pop, but not going to fly. You need to handle dead code directly.
RT: typestack.push can prefers the stack abstraction, if it is bottom it remains bottom
CW: that is true for MVP instructions. But for load.memref you need to condition more, need to condition more on the memref.
RT: if it’s a bottom type there you have to do the same thing anyway.
CW: we both agree, Ben's proposal goes further, have a flat bytecode skipper, chew up opcodes and immediates without doing any sort of checks.
RT: something even more relaxed
CW: essentially
BT: which i think is off the table, because you have to check contro depth to validate br targets.
CW: it’s clear you have an alternative version
AR: can’t just be skipped bytes, you need to at least match brackets.
CW: true, much more simply with a counter, if you’re doing a naive
AR: yea.
BT: canonical example why this breaks down, which we discussed on an issue, return call ref. Tail call where it pops a first-class fn, you need to check that its return type matches enclosing fn. The actual validation algorithm has to check if you are unreachable, no real type you can return, even bottom. You have to have a rule that bottom matches any function return type. That’s ugly.
CW: analogous to how you have to implement memref. Have to condition how you pop immediate.
RT: boilerplate rule, otherwise the validator has to check reachable/unreachable
CW: sounds like we have two philosophies… aren’t strong objections to doing any kind of change, but division between whether we should do this as “switching off individual checks” in the existing decode-validate logic (current proposal), or a separate simple skip-bytes algorithm. Maybe I should write both ideas, have implementers feedback on github issue. Sounds like a good summary?
BT: i would phrase differently, i think the skip-bytes thing is dying a slow death.
CW: selfishly that works for me, would still like to hear from others.
AR: i fear it would have additional problems, just an intuition, can’t point at anything. Would make the distinction between decoding and validation even…
CW: starker
AR: yea.
TL: end of time
CW: 30s plead, rather light on input from people who need to make these changes in the browser. Would like people to comment whether okay or not, a general thumbs up or down.
AR: in practice they won’t find out until they actually try.
SIMD-specific feature detection (Thomas Lively) [15 min]
AR: it is a bit difficult to answer that without seeing how the proposal looks like
TL: true. The concrete thing is extremely strange, no sugar coating. Didn’t get into technical details, we might want to change it later. If we can’t come up with something CG approves before Phase 4, then we won’t do it. More of a question for CG, should this be a goal.
BT: are you asking if it is acceptable to include feature detection in SIMD?
TL: yes, current simd proposal
PP: the danger is we end up with the same overload, one class of instructions per day
TL: yea, we will need to come back to the CG with the updates on instructions
RT: will this feature detection help you with that?
TL: hard to say, not something we can tell people so far. If we have a good story for deferring instructions to post-mvp, will help us finalize the instruction set
PP: that’s the logic we told people, danger to some degree, scope creep on all the extra instructions, need to extend to 256 bits, non-det and so on.
AR: similar question i wanted to ask, underlying this proposal seems to be that SIMD will keep growing, or is that a wrong perception. I find that scary in itself, separate of FD.
TL: can’t keep growing without CG’s blessing. We have pressure from users to continue growing the set, business needs to keep growing. There will be new proposals to keep growing it.
FM: slippery slope argument, one reason why people are not expressing an opinion. We are starting down a slippery slope which might be an innocuous idea. If you have any kind of variability or optionality, you have the combinatorial explosion, not solving anything by permitting that.
TL: e.g. webgl extensions are an existing case on the web, pretty good experience so far for users. Problem is that the combinatorial explosions exposed to users due to the many builds they have to deal with. Feature detection can hide that.
FM: that’s the main issue, instead of combinatorial explosion, anticipate only incremental changes, if new extension, it’s on top of all the other extensions.
PP: that post from marat supporting both sse and neon, it should be incremental.
LW: speak in favor, hard problem in general, if you zoom into SIMD, you can have a local polyfill, purely computation, does become different and solvable problem
AR: question this a bit, will we ever need this in function sigs. Can’t put that into separate fns
LW: different fns, use but trap.
TL: I can make a more concrete design and come back to present.