diff --git a/js/src/jit-test/tests/jaeger/recompile/bug639508.js b/js/src/jit-test/tests/jaeger/recompile/bug639508.js new file mode 100644 index 00000000000..a25a70c601f --- /dev/null +++ b/js/src/jit-test/tests/jaeger/recompile/bug639508.js @@ -0,0 +1,2 @@ +var o = 2; +o = o.p; diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index bc2fdc6d928..e95c2f3ff86 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1394,7 +1394,7 @@ mjit::Compiler::generateMethod() frame.pop(); if (!target) { - frame.push(Value(BooleanValue(result))); + frame.push(Value(BooleanValue(result)), pushedTypeSet(0)); } else { if (fused == JSOP_IFEQ) result = !result; @@ -1751,7 +1751,7 @@ mjit::Compiler::generateMethod() { uint32 index = fullAtomIndex(PC); double d = script->getConst(index).toDouble(); - frame.push(Value(DoubleValue(d))); + frame.push(Value(DoubleValue(d)), pushedTypeSet(0)); } END_CASE(JSOP_DOUBLE) @@ -1759,20 +1759,20 @@ mjit::Compiler::generateMethod() { JSAtom *atom = script->getAtom(fullAtomIndex(PC)); JSString *str = ATOM_TO_STRING(atom); - frame.push(Value(StringValue(str))); + frame.push(Value(StringValue(str)), pushedTypeSet(0)); } END_CASE(JSOP_STRING) BEGIN_CASE(JSOP_ZERO) - frame.push(Valueify(JSVAL_ZERO)); + frame.push(Valueify(JSVAL_ZERO), pushedTypeSet(0)); END_CASE(JSOP_ZERO) BEGIN_CASE(JSOP_ONE) - frame.push(Valueify(JSVAL_ONE)); + frame.push(Valueify(JSVAL_ONE), pushedTypeSet(0)); END_CASE(JSOP_ONE) BEGIN_CASE(JSOP_NULL) - frame.push(NullValue()); + frame.push(NullValue(), pushedTypeSet(0)); END_CASE(JSOP_NULL) BEGIN_CASE(JSOP_THIS) @@ -1780,11 +1780,11 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_THIS) BEGIN_CASE(JSOP_FALSE) - frame.push(Value(BooleanValue(false))); + frame.push(Value(BooleanValue(false)), pushedTypeSet(0)); END_CASE(JSOP_FALSE) BEGIN_CASE(JSOP_TRUE) - frame.push(Value(BooleanValue(true))); + frame.push(Value(BooleanValue(true)), pushedTypeSet(0)); END_CASE(JSOP_TRUE) BEGIN_CASE(JSOP_OR) @@ -2446,6 +2446,10 @@ mjit::Compiler::findCallSite(const CallSite &callSite) for (uint32 i = 0; i < callSites.length(); i++) { InternalCallSite &cs = callSites[i]; if (cs.pc == script->code + callSite.pcOffset && cs.id == callSite.id) { +#ifdef DEBUG + for (i++; i < callSites.length(); i++) + JS_ASSERT(cs.pc != callSites[i].pc || cs.id != callSites[i].id); +#endif if (cs.ool) return oolPath + cs.returnOffset; return ilPath + cs.returnOffset; @@ -3212,6 +3216,10 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew) void mjit::Compiler::addCallSite(const InternalCallSite &site) { +#ifdef DEBUG + for (unsigned i = 0; i < callSites.length(); i++) + JS_ASSERT(site.pc != callSites[i].pc || site.id != callSites[i].id); +#endif callSites.append(site); } @@ -3287,7 +3295,10 @@ bool mjit::Compiler::emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused) { fixDoubleTypes(Uses(2)); - frame.syncAndForgetEverything(); + if (target) + frame.syncAndForgetEverything(); + else + frame.syncAndKill(Uses(2)); prepareStubCall(Uses(2)); INLINE_STUBCALL(stub); @@ -3470,7 +3481,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, types::TypeSet stubcc.leave(); passICAddress(&pic); - pic.slowPathCall = OOL_STUBCALL(ic::GetProp); + pic.slowPathCall = OOL_STUBCALL(usePropCache ? ic::GetProp : ic::GetPropNoCache); CHECK_OOL_SPACE(); /* Load the base slot address. */ @@ -3505,6 +3516,14 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, types::TypeSet stubcc.rejoin(Changes(1)); + if (recompiling) { + if (usePropCache) + OOL_STUBCALL(stubs::GetProp); + else + OOL_STUBCALL(stubs::GetPropNoCache); + stubcc.rejoin(Changes(1)); + } + pics.append(pic); return true; } @@ -3619,6 +3638,11 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) stubcc.rejoin(Changes(2)); pics.append(pic); + if (recompiling) { + OOL_STUBCALL(stubs::CallProp); + stubcc.rejoin(Changes(2)); + } + return true; } diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index 806997ca1df..52079891bb5 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -227,10 +227,11 @@ FrameState::rawPush() } inline void -FrameState::push(const Value &v) +FrameState::push(const Value &v, types::TypeSet *typeSet) { FrameEntry *fe = rawPush(); fe->setConstant(Jsvalify(v)); + fe->typeSet = typeSet; } inline void diff --git a/js/src/methodjit/FrameState.h b/js/src/methodjit/FrameState.h index a801ac7dd2e..3866389bab7 100644 --- a/js/src/methodjit/FrameState.h +++ b/js/src/methodjit/FrameState.h @@ -260,7 +260,7 @@ class FrameState /* * Pushes a constant value. */ - inline void push(const Value &v); + inline void push(const Value &v, types::TypeSet *typeSet = NULL); /* * Loads a value from memory and pushes it. diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 3c154240c64..e9ae40cf97c 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -1741,6 +1741,17 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) f.regs.sp[-1] = v; } +void JS_FASTCALL +ic::GetPropNoCache(VMFrame &f, ic::PICInfo *pic) +{ + /* + * The PIC stores whether to use the property cache or not. We use two different + * stub calls so we can distinguish uncached calls made to construct this from + * any cached calls at the first opcode in a script. + */ + GetProp(f, pic); +} + template static void JS_FASTCALL DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic) diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index d08e4d057d5..4d11cd53850 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -549,6 +549,7 @@ struct PICInfo : public BasePolyIC { #ifdef JS_POLYIC void PurgePICs(JSContext *cx, JSScript *script); void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *); +void JS_FASTCALL GetPropNoCache(VMFrame &f, ic::PICInfo *); void JS_FASTCALL SetProp(VMFrame &f, ic::PICInfo *); void JS_FASTCALL CallProp(VMFrame &f, ic::PICInfo *); void JS_FASTCALL Name(VMFrame &f, ic::PICInfo *);