On Wed, May 13, 2020 at 7:54 PM Jason Orendorff <joren...@mozilla.com
> Jan, I'd like to know what you think about this.
Approach 2 is what we used to do before the big generator rewrite that
resulted in Baseline JIT support. Problems I see with bringing it back:
- It ties the generator's heap representation to JIT internals resulting
in weird edge cases. For example: what happens if we execute in the
Baseline JIT, yield from the generator, discard the BaselineScript on GC,
then resume? We'd need to fix up the heap-allocated frame somehow or
Baseline-compile immediately. Debugger and profiler make these things worse.
- There are places
where we calculate the BaselineFrame's size based on FP/SP distance. This
especially matters for blinterp because it doesn't know anything about the
- blinterp /must/ access expression stack slots via SP because the
offset from FP isn't statically known (depends on number of locals and
expression stack slots).
- It makes Ion/Warp support hard because its frame layout is very
different (regalloc spills to 'arbitrary' stack slots).
For approach 1 we could potentially share get/set opcodes for
locals/formals because it's a single array (or maybe not due to
Here's a hybrid approach 3:
- GeneratorObject owns a list-of-Values (for formals and locals) as in
approach 1, but InterpreterFrame and BaselineFrame store a raw pointer to
- We'd need different get/set opcodes for generator locals, but they'd
only be a single load (fp->generatorArray) slower than normal locals .
- Maybe we could implement this by ensuring the "list of Values" == "the
GeneratorObject's dynamic slots". That way we get things like nursery
allocation of that array for free.
- For expression stack slots: the list-of-Values could reserve space for
them (based on script->nslots) and then we emit store ops before the yield
and load + push ops after. This way yield/resume with expression stack
slots would be faster than what we do now (ArrayObject allocation..) and if
there are no expression stack slots we don't have any runtime overhead.
This could potentially be optimized in the frontend so that if you have a
yield right after another yield, you only have to emit stores for the part
of the expression stack that actually changed.
 For each approach: we probably want to avoid pre-barriers and
post-barriers when storing generator locals while executing. The old code
had some complexity around pre-barriers, it's probably worth trying to
understand what it did.
> dev-tech-js-engine-internals mailing list