author | Kannan Vijayan <kvijayan@mozilla.com> |
Tue, 10 Sep 2013 12:26:47 -0400 | |
changeset 146444 | 7284c374c28d1333edd1b22873ef7d482d9ea6ba |
parent 146443 | 12141799ef109e6d03d47398d647d0f609c51183 |
child 146445 | 5f52bbf813be121c857176759d8a5299ba664829 |
push id | 25260 |
push user | ryanvm@gmail.com |
push date | Wed, 11 Sep 2013 00:29:30 +0000 |
treeherder | mozilla-central@f73bed2856a8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | efaust |
bugs | 913978 |
milestone | 26.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -374,19 +374,19 @@ IsInlinableFallback(ICFallbackStub *icEn { return icEntry->isCall_Fallback() || icEntry->isGetProp_Fallback() || icEntry->isSetProp_Fallback(); } static inline void* GetStubReturnAddress(JSContext *cx, jsbytecode *pc) { - if (IsGetterPC(pc)) + if (IsGetPropPC(pc)) return cx->compartment()->ionCompartment()->baselineGetPropReturnAddr(); - if (IsSetterPC(pc)) + if (IsSetPropPC(pc)) return cx->compartment()->ionCompartment()->baselineSetPropReturnAddr(); // This should be a call op of some kind, now. JS_ASSERT(IsCallPC(pc)); return cx->compartment()->ionCompartment()->baselineCallReturnAddr(); } // For every inline frame, we write out the following data: // @@ -656,26 +656,26 @@ InitFromBailout(JSContext *cx, HandleScr JSOp op = JSOp(*pc); JS_ASSERT_IF(excInfo, op == JSOP_ENTERBLOCK); // Fixup inlined JSOP_FUNCALL, JSOP_FUNAPPLY, and accessors on the caller side. // On the caller side this must represent like the function wasn't inlined. uint32_t pushedSlots = 0; AutoValueVector savedCallerArgs(cx); - bool needToSaveArgs = op == JSOP_FUNAPPLY || IsGetterPC(pc) || IsSetterPC(pc); + bool needToSaveArgs = op == JSOP_FUNAPPLY || IsGetPropPC(pc) || IsSetPropPC(pc); if (iter.moreFrames() && (op == JSOP_FUNCALL || needToSaveArgs)) { uint32_t inlined_args = 0; if (op == JSOP_FUNCALL) inlined_args = 2 + GET_ARGC(pc) - 1; else if (op == JSOP_FUNAPPLY) inlined_args = 2 + blFrame->numActualArgs(); else - inlined_args = 2 + IsSetterPC(pc); + inlined_args = 2 + IsSetPropPC(pc); JS_ASSERT(exprStackSlots >= inlined_args); pushedSlots = exprStackSlots - inlined_args; IonSpew(IonSpew_BaselineBailouts, " pushing %u expression stack slots before fixup", pushedSlots); for (uint32_t i = 0; i < pushedSlots; i++) { @@ -720,17 +720,17 @@ InitFromBailout(JSContext *cx, HandleScr } // Save the actual arguments. They are needed on the callee side // as the arguments. Else we can't recover them. if (!savedCallerArgs.resize(inlined_args)) return false; for (uint32_t i = 0; i < inlined_args; i++) savedCallerArgs[i] = iter.read(); - if (IsSetterPC(pc)) { + if (IsSetPropPC(pc)) { // We would love to just save all the arguments and leave them // in the stub frame pushed below, but we will lose the inital // argument which the function was called with, which we must // return to the caller, even if the setter internally modifies // its arguments. Stash the initial argument on the stack, to be // later retrieved by the SetProp_Fallback stub. Value initialArg = savedCallerArgs[inlined_args - 1]; IonSpew(IonSpew_BaselineBailouts, " pushing setter's initial argument"); @@ -788,17 +788,17 @@ InitFromBailout(JSContext *cx, HandleScr uint32_t expectedDepth = js_ReconstructStackDepth(cx, script, resumeAfter ? GetNextPc(pc) : pc); if (op != JSOP_FUNAPPLY || !iter.moreFrames() || resumeAfter) { if (op == JSOP_FUNCALL) { // For fun.call(this, ...); the reconstructStackDepth will // include the this. When inlining that is not included. // So the exprStackSlots will be one less. JS_ASSERT(expectedDepth - exprStackSlots <= 1); - } else if (iter.moreFrames() && (IsGetterPC(pc) || IsSetterPC(pc))) { + } else if (iter.moreFrames() && (IsGetPropPC(pc) || IsSetPropPC(pc))) { // Accessors coming out of ion are inlined via a complete // lie perpetrated by the compiler internally. Ion just rearranges // the stack, and pretends that it looked like a call all along. // This means that the depth is actually one *more* than expected // by the interpreter, as there is now a JSFunction, |this| and [arg], // rather than the expected |this| and [arg] // Note that none of that was pushed, but it's still reflected // in exprStackSlots. @@ -1023,17 +1023,17 @@ InitFromBailout(JSContext *cx, HandleScr JS_ASSERT(IsIonInlinablePC(pc)); unsigned actualArgc; if (needToSaveArgs) { // For FUNAPPLY or an accessor, the arguments are not on the stack anymore, // but they are copied in a vector and are written here. if (op == JSOP_FUNAPPLY) actualArgc = blFrame->numActualArgs(); else - actualArgc = IsSetterPC(pc); + actualArgc = IsSetPropPC(pc); JS_ASSERT(actualArgc + 2 <= exprStackSlots); JS_ASSERT(savedCallerArgs.length() == actualArgc + 2); for (unsigned i = 0; i < actualArgc + 1; i++) { size_t arg = savedCallerArgs.length() - (i + 1); if (!builder.writeValue(savedCallerArgs[arg], "ArgVal")) return false; }
--- a/js/src/jit/Ion.h +++ b/js/src/jit/Ion.h @@ -369,17 +369,17 @@ IsIonEnabled(JSContext *cx) cx->typeInferenceEnabled(); } inline bool IsIonInlinablePC(jsbytecode *pc) { // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites) // GETPROP, CALLPROP, and LENGTH. (Inlined Getters) // SETPROP, SETNAME, SETGNAME (Inlined Setters) - return IsCallPC(pc) || IsGetterPC(pc) || IsSetterPC(pc); + return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc); } void ForbidCompilation(JSContext *cx, JSScript *script); void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode); uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc); void PurgeCaches(JSScript *script, JS::Zone *zone); size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf);
--- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -1369,19 +1369,19 @@ InlineFrameIteratorMaybeGC<allowGC>::fin JS_ASSERT(IsIonInlinablePC(pc_)); // Recover the number of actual arguments from the script. if (JSOp(*pc_) != JSOP_FUNAPPLY) numActualArgs_ = GET_ARGC(pc_); if (JSOp(*pc_) == JSOP_FUNCALL) { JS_ASSERT(GET_ARGC(pc_) > 0); numActualArgs_ = GET_ARGC(pc_) - 1; - } else if (IsGetterPC(pc_)) { + } else if (IsGetPropPC(pc_)) { numActualArgs_ = 0; - } else if (IsSetterPC(pc_)) { + } else if (IsSetPropPC(pc_)) { numActualArgs_ = 1; } JS_ASSERT(numActualArgs_ != 0xbadbad); // Skip over non-argument slots, as well as |this|. unsigned skipCount = (si_.slots() - 1) - numActualArgs_ - 1; for (unsigned j = 0; j < skipCount; j++) @@ -1438,17 +1438,17 @@ bool InlineFrameIteratorMaybeGC<allowGC>::isConstructing() const { // Skip the current frame and look at the caller's. if (more()) { InlineFrameIteratorMaybeGC<allowGC> parent(GetIonContext()->cx, this); ++parent; // Inlined Getters and Setters are never constructing. - if (IsGetterPC(parent.pc()) || IsSetterPC(parent.pc())) + if (IsGetPropPC(parent.pc()) || IsSetPropPC(parent.pc())) return false; // In the case of a JS frame, look up the pc from the snapshot. JS_ASSERT(IsCallPC(parent.pc())); return (JSOp)*parent.pc() == JSOP_NEW; } @@ -1467,30 +1467,31 @@ IonFrameIterator::isConstructing() const ++parent; } while (!parent.done() && !parent.isScripted()); if (parent.isOptimizedJS()) { // In the case of a JS frame, look up the pc from the snapshot. InlineFrameIterator inlinedParent(GetIonContext()->cx, &parent); //Inlined Getters and Setters are never constructing. - if (IsGetterPC(inlinedParent.pc()) || IsSetterPC(inlinedParent.pc())) + if (IsGetPropPC(inlinedParent.pc()) || IsSetPropPC(inlinedParent.pc())) return false; JS_ASSERT(IsCallPC(inlinedParent.pc())); return (JSOp)*inlinedParent.pc() == JSOP_NEW; } if (parent.isBaselineJS()) { jsbytecode *pc; parent.baselineScriptAndPc(NULL, &pc); - //Inlined Getters and Setters are never constructing. - if (IsGetterPC(pc) || IsSetterPC(pc)) + // Inlined Getters and Setters are never constructing. + // Baseline may call getters from [GET|SET]PROP or [GET|SET]ELEM ops. + if (IsGetPropPC(pc) || IsSetPropPC(pc) || IsGetElemPC(pc) || IsSetElemPC(pc)) return false; JS_ASSERT(IsCallPC(pc)); return JSOp(*pc) == JSOP_NEW; } JS_ASSERT(parent.done());
--- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -279,17 +279,19 @@ CodeGeneratorShared::encode(LSnapshot *s #ifdef DEBUG if (GetIonContext()->cx) { uint32_t stackDepth = js_ReconstructStackDepth(GetIonContext()->cx, script, bailPC); if (JSOp(*bailPC) == JSOP_FUNCALL) { // For fun.call(this, ...); the reconstructStackDepth will // include the this. When inlining that is not included. // So the exprStackSlots will be one less. JS_ASSERT(stackDepth - exprStack <= 1); - } else if (JSOp(*bailPC) != JSOP_FUNAPPLY && !IsGetterPC(bailPC) && !IsSetterPC(bailPC)) { + } else if (JSOp(*bailPC) != JSOP_FUNAPPLY && + !IsGetPropPC(bailPC) && !IsSetPropPC(bailPC)) + { // For fun.apply({}, arguments) the reconstructStackDepth will // have stackdepth 4, but it could be that we inlined the // funapply. In that case exprStackSlots, will have the real // arguments in the slots and not be 4. // With accessors, we have different stack depths depending on whether or not we // inlined the accessor, as the inlined stack contains a callee function that should // never have been there and we might just be capturing an uneventful property site,
--- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -586,30 +586,44 @@ IsGlobalOp(JSOp op) inline bool IsEqualityOp(JSOp op) { return op == JSOP_EQ || op == JSOP_NE || op == JSOP_STRICTEQ || op == JSOP_STRICTNE; } inline bool -IsGetterPC(jsbytecode *pc) +IsGetPropPC(jsbytecode *pc) { JSOp op = JSOp(*pc); return op == JSOP_LENGTH || op == JSOP_GETPROP || op == JSOP_CALLPROP; } inline bool -IsSetterPC(jsbytecode *pc) +IsSetPropPC(jsbytecode *pc) { JSOp op = JSOp(*pc); return op == JSOP_SETPROP || op == JSOP_SETNAME || op == JSOP_SETGNAME; } inline bool +IsGetElemPC(jsbytecode *pc) +{ + JSOp op = JSOp(*pc); + return op == JSOP_GETELEM || op == JSOP_CALLELEM; +} + +inline bool +IsSetElemPC(jsbytecode *pc) +{ + JSOp op = JSOp(*pc); + return op == JSOP_SETELEM; +} + +inline bool IsCallPC(jsbytecode *pc) { return js_CodeSpec[*pc].format & JOF_INVOKE; } static inline int32_t GetBytecodeInteger(jsbytecode *pc) {