Closed
Bug 1169743
Opened 6 years ago
Closed 4 years ago
Make classes with extends work in the Jits
Categories
(Core :: JavaScript Engine: JIT, defect, P1)
Core
JavaScript Engine: JIT
Tracking
()
RESOLVED
FIXED
People
(Reporter: efaust, Assigned: tcampbell)
References
(Blocks 3 open bugs)
Details
(Keywords: perf)
Attachments
(3 files, 3 obsolete files)
No description provided.
| Reporter | ||
Comment 1•5 years ago
|
||
| Reporter | ||
Comment 2•5 years ago
|
||
Attachment #8708572 -
Flags: review?(jdemooij)
| Reporter | ||
Comment 3•5 years ago
|
||
Comment on attachment 8708572 [details] [diff] [review] Part 2: Implement remaining JSOPs to allow class decls with extends in Baseline. Review of attachment 8708572 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jit/BaselineCompiler.cpp @@ +4365,5 @@ > +BaselineCompiler::emit_JSOP_FUNWITHPROTO() > +{ > + frame.syncStack(0); > + > + masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg()); This makes no sense. It worked by serendipity for me, as I test on x64. This should be |masm.unboxObject|, as written, though probably frame.popRegsAndSync(1); Register proto = masm.extractObject(R0, R2,scratchReg()); with the pop() below removed or so is better.
Comment 4•5 years ago
|
||
Comment on attachment 8708572 [details] [diff] [review] Part 2: Implement remaining JSOPs to allow class decls with extends in Baseline. Review of attachment 8708572 [details] [diff] [review]: ----------------------------------------------------------------- Nice. ::: js/src/jit/BaselineCompiler.cpp @@ +4366,5 @@ > +{ > + frame.syncStack(0); > + > + masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg()); > + masm.loadPtr(frame.addressOfScopeChain(), R1.scratchReg()); Yeah I think popRegsAndSync instead of syncStack(0) makes sense.
Attachment #8708572 -
Flags: review?(jdemooij) → review+
Comment 5•5 years ago
|
||
Comment on attachment 8708570 [details] [diff] [review] Part 1: Rework JSOP_CLASSHERITAGE to be jit-friendly. Review of attachment 8708570 [details] [diff] [review]: ----------------------------------------------------------------- r=me, and this was fine! From our conversation I felt I should expect something much worse. But geez, have you *seen* our frontend? This is nothing... :) ::: js/src/frontend/BytecodeEmitter.cpp @@ +8458,5 @@ > + // throw if heritage isn't either null or a non-generator constructor > + if (!emit1(JSOP_CHECKCLASSHERITAGE)) > + return false; > + > + if (!emit1(JSOP_DUP)) A little comment here showing the JS pseudocode for what we're doing here wouldn't suck. I think it's: base !== null ? <base, base.prototype> : <%FunctionPrototype%, null> @@ +8471,5 @@ > + if (!newSrcNote(SRC_IF_ELSE, ¬eIndex)) > + return false; > + > + ptrdiff_t nullOffset; > + if (!emitJump(JSOP_IFNE, 0, &nullOffset)) `if` statements and ternary expressions use JSOP_IFEQ, so just for uniformity I'd probably emit STRICTNEQ IFEQ instead of STRICTEQ IFNE. But if that seems stupid to you, never mind. :) @@ +8486,5 @@ > + > + // Our stack depth calculations are not smart enough to understand branches, > + // so decrement the stackDepth to account for the value pushed above. > + this->stackDepth--; > + MOZ_ASSERT(this->stackDepth == ifDepth); Two things. 1. To my mind, this adjustment belongs after the emitJump(JSOP_GOTO). That's how emitConditionalExpression does it. 2. The comment could maybe point out that emitConditionalExpression does the same thing, and explain why we're only adjusting by 1 instead of 2, even though our if-expression produces 2 values. (It's because we are also consuming the value just below us on the stack.) ::: js/src/js.msg @@ +106,5 @@ > MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|") > MSG_DEF(JSMSG_UNINITIALIZED_THIS, 1, JSEXN_REFERENCEERR, "|this| used uninitialized in {0} class constructor") > MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}") > MSG_DEF(JSMSG_NOT_SELFHOSTED, 1, JSEXN_TYPEERR, "callFunction() used on non self-hosted builtin {0}") > +MSG_DEF(JSMSG_BAD_HERITAGE, 2, JSEXN_TYPEERR, "class heritage {0} is {1}") "heritage" is spec-jargon. consider using "superclass" or "base class"?
Attachment #8708570 -
Flags: review?(jorendorff) → review+
| Reporter | ||
Comment 6•5 years ago
|
||
uhm...why didn't this land? ni? me until I figure out where I dropped this on the floor.
Flags: needinfo?(efaustbmo)
Updated•5 years ago
|
Assignee: efaustbmo → nobody
Status: ASSIGNED → NEW
Flags: needinfo?(efaustbmo)
Priority: P2 → P1
Updated•4 years ago
|
Flags: needinfo?(hv1989)
Updated•4 years ago
|
Flags: needinfo?(hv1989)
Priority: P2 → P1
| Assignee | ||
Updated•4 years ago
|
Assignee: nobody → tcampbell
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
| Assignee | ||
Updated•4 years ago
|
Attachment #8708570 -
Attachment is obsolete: true
| Assignee | ||
Updated•4 years ago
|
Attachment #8708572 -
Attachment is obsolete: true
| Assignee | ||
Comment 10•4 years ago
|
||
I've cleaned up these patches and brought them up to date. Requesting re-reviews since a number of APIs have changed.
| Assignee | ||
Updated•4 years ago
|
Attachment #8871011 -
Flags: review?(jdemooij)
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
Comment 14•4 years ago
|
||
| mozreview-review | ||
Comment on attachment 8871011 [details] Bug 1169743 - Implement class decls with extends in Baseline https://reviewboard.mozilla.org/r/142578/#review147890 Looks good, sorry for the delay.
Attachment #8871011 -
Flags: review?(jdemooij) → review+
| Assignee | ||
Updated•4 years ago
|
Attachment #8871010 -
Flags: review?(shu)
Comment 15•4 years ago
|
||
| mozreview-review | ||
Comment on attachment 8871010 [details] Bug 1169743 - Rework JSOP_CLASSHERITAGE to be jit-friendly. https://reviewboard.mozilla.org/r/142576/#review149854 Looks good generally. Would like to see new version with stack comments for the BCE codegen. ::: js/src/frontend/BytecodeEmitter.cpp:10680 (Diff revision 2) > + IfThenElseEmitter ifThenElse(this); > + > if (!emitTree(heritageExpression)) > return false; > - if (!emit1(JSOP_CLASSHERITAGE)) > + > + // throw if heritage isn't either null or a non-generator constructor Awkward sentence, just "Heritage must be null or a non-generator constructor" would be clearer. ::: js/src/frontend/BytecodeEmitter.cpp:10684 (Diff revision 2) > - if (!emit1(JSOP_CLASSHERITAGE)) > + > + // throw if heritage isn't either null or a non-generator constructor > + if (!emit1(JSOP_CHECKCLASSHERITAGE)) > return false; > - if (!emit1(JSOP_OBJWITHPROTO)) > + > + // [IF] (heritage !== null) The convention in BCE is to list the pseudo-code algorithm in a block comment above the emitted code, and for each emitted bytecode, document the stack state to the right. See something like emitDestructuringOpsArray for a thorough example. ::: js/src/vm/Interpreter.cpp:975 (Diff revision 2) > MOZ_ASSERT(v.isSymbol()); > return JSTYPE_SYMBOL; > } > > +bool > +js::CheckClassHeritage(JSContext* cx, HandleValue heritage) Because of the error reporting behavior where it tries to decompile an on-stack value, please name this CheckClassHeritageOperation. ::: js/src/vm/Interpreter.cpp:978 (Diff revision 2) > > +bool > +js::CheckClassHeritage(JSContext* cx, HandleValue heritage) > +{ > + if (heritage.isObject()) { > + if (!heritage.toObject().isConstructor()) { !IsConstructor(heritage) is nicer. ::: js/src/vm/Interpreter.cpp:4139 (Diff revision 2) > } > END_CASE(JSOP_ARRAYPUSH) > > -CASE(JSOP_CLASSHERITAGE) > +CASE(JSOP_CHECKCLASSHERITAGE) > { > - ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]); > + ReservedRooted<Value> heritage(&rootValue0, REGS.sp[-1]); stackHandleAt ::: js/src/vm/Interpreter.cpp:4150 (Diff revision 2) > > - funcProto = &val.toObject(); > - > - if (!GetProperty(cx, funcProto, funcProto, cx->names().prototype, &objProto)) > - goto error; > - > +CASE(JSOP_BUILTINPROTO) > +{ > + ReservedRooted<JSObject*> builtin(&rootObject0); > + JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(REGS.pc)); > + MOZ_ASSERT(key < JSProto_LIMIT); I admit I'm not clear on the C++ enum semantics here. Should this assert be checked on the bare uint8 argument with JSProto_LIMIT cast to uint8? That is -- I'm worried by casting to JSProtoKey first, if the C++ standard permits the compiler to clamp to values <= JSProto_LIMIT.
Attachment #8871010 -
Flags: review?(shu)
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
Comment 20•4 years ago
|
||
| mozreview-review | ||
Comment on attachment 8871010 [details] Bug 1169743 - Rework JSOP_CLASSHERITAGE to be jit-friendly. https://reviewboard.mozilla.org/r/142576/#review150400 ::: js/src/frontend/BytecodeEmitter.cpp:10706 (Diff revision 4) > + // if defined <BaseExpression> { > + // cons = DefaultDerivedConstructor(proto=homeObject, funProto=funProto); > + // } else { > + // cons = DefaultConstructor(proto=homeObject); > + // } > + // } Awesome comment. ::: js/src/frontend/BytecodeEmitter.cpp:10802 (Diff revision 4) > - if (!emitAtomOp(name, JSOP_CLASSCONSTRUCTOR)) > + if (!emitAtomOp(name, JSOP_CLASSCONSTRUCTOR)) // ... HOMEOBJ CONSTRUCTOR > return false; > } > } > > - if (!emit1(JSOP_SWAP)) > + if (!emit1(JSOP_SWAP)) // ... CONS HOBJ Consistency trumps staying within the 100 column limits here imo. Please keep using CONSTRUCTOR and HOMEOBJ and just go over the max width. ::: js/src/vm/Interpreter.cpp:977 (Diff revision 4) > } > > +bool > +js::CheckClassHeritageOperation(JSContext* cx, HandleValue heritage) > +{ > + if (heritage.isObject()) { This would return true for non-constructor objects. if (heritage.isNull()) return true; if (IsConstructor(heritage)) return true; report(...); return false; ::: js/src/vm/Opcodes.h:494 (Diff revision 4) > * Operands: > * Stack: callee, this, args => rval > */ \ > macro(JSOP_STRICTSPREADEVAL, 50, "strict-spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \ > /* > - * Writes the [[Prototype]] objects for both a class and its .prototype to > + * Ensure the result of a class's heritage expression is either null or a constructor. Nit: Ensures
Attachment #8871010 -
Flags: review?(shu) → review+
Comment 21•4 years ago
|
||
| mozreview-review | ||
Comment on attachment 8871010 [details] Bug 1169743 - Rework JSOP_CLASSHERITAGE to be jit-friendly. https://reviewboard.mozilla.org/r/142576/#review150406 Great comments, thanks for adding the stack state comments to parts that didn't have them before. r=me with the logic in CheckHeritageOperation fixed.
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
Comment 24•4 years ago
|
||
Pushed by tcampbell@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/bc64157bced9 Rework JSOP_CLASSHERITAGE to be jit-friendly. r=shu https://hg.mozilla.org/integration/autoland/rev/c1ae34baf77a Implement class decls with extends in Baseline r=jandem
| Assignee | ||
Updated•4 years ago
|
Keywords: leave-open
| Assignee | ||
Comment 25•4 years ago
|
||
This patch adds three more opcodes needed to support derived classes (and default constructors) in Baseline. With this, top-level code that defines classes is JIT-able. Individual methods that use |super| will be supported in other bugs.
Attachment #8875450 -
Flags: review?(jdemooij)
| Assignee | ||
Comment 26•4 years ago
|
||
Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=2825ed1b8b7261bca55302c635b58592b7f0df13
| Assignee | ||
Comment 27•4 years ago
|
||
Some tests still fail. Will look into them tomorrow.
| Assignee | ||
Comment 28•4 years ago
|
||
Respin of patch with missing write barriers in Baseline INITHOMEOBJECT. Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=eab95d04774eec4e65f08784cbc012bdd3b2b622
Attachment #8875450 -
Attachment is obsolete: true
Attachment #8875450 -
Flags: review?(jdemooij)
Attachment #8875578 -
Flags: review?(jdemooij)
Comment 29•4 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/bc64157bced9 https://hg.mozilla.org/mozilla-central/rev/c1ae34baf77a
Comment 30•4 years ago
|
||
Comment on attachment 8875578 [details] [diff] [review] 0001-Bug-1169743-Implement-class-decls-with-extends-in-Ba.patch Review of attachment 8875578 [details] [diff] [review]: ----------------------------------------------------------------- Great to have these ops finally implemented in Baseline. ::: js/src/jit/BaselineCompiler.cpp @@ +4729,5 @@ > + masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), func); > + > + // Set HOMEOBJECT_SLOT > + Address addr(func, FunctionExtended::offsetOfMethodHomeObjectSlot()); > + masm.guardedCallPreBarrier(addr, MIRType::Value); Is HOMEOBJECT_SLOT always undefined at this point? If yes we don't need a pre-barrier and could assert this in debug builds.
Attachment #8875578 -
Flags: review?(jdemooij) → review+
Comment 31•4 years ago
|
||
Pushed by tcampbell@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/24191914f43b Implement class decls with extends in Baseline (cont.) r=jandem
Comment 32•4 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/24191914f43b
| Assignee | ||
Comment 33•4 years ago
|
||
Closing bug as this is fixed for Baseline and seems stable in nightly. I'll open a new bug to discuss Ion support of classes.
Status: NEW → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Comment 34•3 years ago
|
||
Removing leave-open keyword from resolved bugs, per :sylvestre.
Keywords: leave-open
You need to log in
before you can comment on or make changes to this bug.
Description
•