Loading js/src/jit/BaselineIC.cpp +13 −8 Original line number Diff line number Diff line Loading @@ -783,6 +783,8 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ RootedScript script(cx, frame->script()); jsbytecode* pc = stub->icEntry()->pc(frame->script()); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); JSOp op = JSOp(*pc); FallbackICSpew(cx, stub, "GetElem(%s)", CodeName[op]); Loading @@ -797,7 +799,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs)) return false; if (isOptimizedArgs) TypeScript::Monitor(cx, frame->script(), pc, res); TypeScript::Monitor(cx, script, pc, types, res); } bool attached = false; Loading Loading @@ -828,7 +830,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ if (!isOptimizedArgs) { if (!GetElementOperation(cx, op, lhsCopy, rhs, res)) return false; TypeScript::Monitor(cx, frame->script(), pc, res); TypeScript::Monitor(cx, script, pc, types, res); } // Check if debug mode toggling made the stub invalid. Loading @@ -836,7 +838,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (attached) Loading Loading @@ -1372,14 +1374,15 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_ return false; } TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (!attached) Loading Loading @@ -2450,14 +2453,15 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint res.set(callArgs.rval()); } TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; // If 'callee' is a potential Call_StringSplit, try to attach an Loading Loading @@ -2509,7 +2513,8 @@ DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_ return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (!handled) Loading js/src/jit/SharedIC.cpp +36 −24 Original line number Diff line number Diff line Loading @@ -456,9 +456,9 @@ ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx, ICStubSpace* space) bool ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val) StackTypeSet* types, HandleValue val) { return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, val); return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, types, val); } bool Loading Loading @@ -2059,14 +2059,15 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_ if (!ComputeGetPropResult(cx, frame, op, name, val, res)) return false; TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (attached) Loading Loading @@ -2173,8 +2174,11 @@ BaselineScript::noteAccessedGetter(uint32_t pcOffset) // bool ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val) ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val) { MOZ_ASSERT(types); bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr; MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0); Loading Loading @@ -2298,7 +2302,10 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac jsbytecode* pc = stub->icEntry()->pc(script); TypeFallbackICSpew(cx, stub, "TypeMonitor"); if (value.isMagic()) { // Copy input value to res. res.set(value); if (MOZ_UNLIKELY(value.isMagic())) { // It's possible that we arrived here from bailing out of Ion, and that // Ion proved that the value is dead and optimized out. In such cases, // do nothing. However, it's also possible that we have an uninitialized Loading @@ -2306,7 +2313,6 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac if (value.whyMagic() == JS_OPTIMIZED_OUT) { MOZ_ASSERT(!stub->monitorsThis()); res.set(value); return true; } Loading @@ -2317,32 +2323,38 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac MOZ_ASSERT(stub->monitorsThis() || *GetNextPc(pc) == JSOP_CHECKTHIS || *GetNextPc(pc) == JSOP_CHECKRETURN); if (stub->monitorsThis()) TypeScript::SetThis(cx, script, TypeSet::UnknownType()); else TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType()); return true; } // Note: ideally we would merge this if-else statement with the one below, // but that triggers an MSVC 2015 compiler bug. See bug 1363054. StackTypeSet* types; uint32_t argument; if (stub->monitorsThis()) { MOZ_ASSERT(pc == script->code()); if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) TypeScript::SetThis(cx, script, TypeSet::UnknownType()); if (stub->monitorsArgument(&argument)) types = TypeScript::ArgTypes(script, argument); else if (stub->monitorsThis()) types = TypeScript::ThisTypes(script); else TypeScript::SetThis(cx, script, value); } else if (stub->monitorsArgument(&argument)) { types = TypeScript::BytecodeTypes(script, pc); if (stub->monitorsArgument(&argument)) { MOZ_ASSERT(pc == script->code()); MOZ_ASSERT(!value.isMagic(JS_UNINITIALIZED_LEXICAL)); TypeScript::SetArgument(cx, script, argument, value); } else if (stub->monitorsThis()) { MOZ_ASSERT(pc == script->code()); TypeScript::SetThis(cx, script, value); } else { if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType()); else TypeScript::Monitor(cx, script, pc, value); TypeScript::Monitor(cx, script, pc, types, value); } if (!stub->invalid() && !stub->addMonitorStubForValue(cx, frame, value)) return false; // Copy input value to res. res.set(value); if (MOZ_UNLIKELY(stub->invalid())) return true; return stub->addMonitorStubForValue(cx, frame, types, value); } typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*, Loading js/src/jit/SharedIC.h +4 −2 Original line number Diff line number Diff line Loading @@ -1208,7 +1208,8 @@ class ICMonitoredFallbackStub : public ICFallbackStub public: MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val); inline ICTypeMonitor_Fallback* fallbackMonitorStub() const { return fallbackMonitorStub_; Loading Loading @@ -1468,7 +1469,8 @@ class ICTypeMonitor_Fallback : public ICStub // Create a new monitor stub for the type of the given value, and // add it to this chain. MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val); void resetMonitorStubChain(Zone* zone); Loading js/src/vm/TypeInference-inl.h +11 −0 Original line number Diff line number Diff line Loading @@ -489,6 +489,8 @@ MarkObjectStateChange(JSContext* cx, JSObject* obj) /* Interface helpers for JSScript*. */ extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type); extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, TypeSet::Type type); extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval); ///////////////////////////////////////////////////////////////////// Loading Loading @@ -589,6 +591,15 @@ TypeScript::Monitor(JSContext* cx, const js::Value& rval) Monitor(cx, script, pc, rval); } /* static */ inline void TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, const js::Value& rval) { TypeSet::Type type = TypeSet::GetValueType(rval); if (!types->hasType(type)) TypeMonitorResult(cx, script, pc, types, type); } /* static */ inline void TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id) { Loading js/src/vm/TypeInference.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -3341,6 +3341,22 @@ js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet:: types->addType(cx, type); } void js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, TypeSet::Type type) { assertSameCompartment(cx, script, type); AutoEnterAnalysis enter(cx); MOZ_ASSERT(types == TypeScript::BytecodeTypes(script, pc)); MOZ_ASSERT(!types->hasType(type)); InferSpew(ISpewOps, "bytecodeType: %p %05" PRIuSIZE ": %s", script, script->pcToOffset(pc), TypeSet::TypeString(type)); types->addType(cx, type); } void js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval) { Loading Loading
js/src/jit/BaselineIC.cpp +13 −8 Original line number Diff line number Diff line Loading @@ -783,6 +783,8 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ RootedScript script(cx, frame->script()); jsbytecode* pc = stub->icEntry()->pc(frame->script()); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); JSOp op = JSOp(*pc); FallbackICSpew(cx, stub, "GetElem(%s)", CodeName[op]); Loading @@ -797,7 +799,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs)) return false; if (isOptimizedArgs) TypeScript::Monitor(cx, frame->script(), pc, res); TypeScript::Monitor(cx, script, pc, types, res); } bool attached = false; Loading Loading @@ -828,7 +830,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ if (!isOptimizedArgs) { if (!GetElementOperation(cx, op, lhsCopy, rhs, res)) return false; TypeScript::Monitor(cx, frame->script(), pc, res); TypeScript::Monitor(cx, script, pc, types, res); } // Check if debug mode toggling made the stub invalid. Loading @@ -836,7 +838,7 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_ return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (attached) Loading Loading @@ -1372,14 +1374,15 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_ return false; } TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (!attached) Loading Loading @@ -2450,14 +2453,15 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint res.set(callArgs.rval()); } TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; // If 'callee' is a potential Call_StringSplit, try to attach an Loading Loading @@ -2509,7 +2513,8 @@ DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_ return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (!handled) Loading
js/src/jit/SharedIC.cpp +36 −24 Original line number Diff line number Diff line Loading @@ -456,9 +456,9 @@ ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx, ICStubSpace* space) bool ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val) StackTypeSet* types, HandleValue val) { return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, val); return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, types, val); } bool Loading Loading @@ -2059,14 +2059,15 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_ if (!ComputeGetPropResult(cx, frame, op, name, val, res)) return false; TypeScript::Monitor(cx, script, pc, res); StackTypeSet* types = TypeScript::BytecodeTypes(script, pc); TypeScript::Monitor(cx, script, pc, types, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) return true; // Add a type monitor stub for the resulting value. if (!stub->addMonitorStubForValue(cx, frame, res)) if (!stub->addMonitorStubForValue(cx, frame, types, res)) return false; if (attached) Loading Loading @@ -2173,8 +2174,11 @@ BaselineScript::noteAccessedGetter(uint32_t pcOffset) // bool ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val) ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val) { MOZ_ASSERT(types); bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr; MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0); Loading Loading @@ -2298,7 +2302,10 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac jsbytecode* pc = stub->icEntry()->pc(script); TypeFallbackICSpew(cx, stub, "TypeMonitor"); if (value.isMagic()) { // Copy input value to res. res.set(value); if (MOZ_UNLIKELY(value.isMagic())) { // It's possible that we arrived here from bailing out of Ion, and that // Ion proved that the value is dead and optimized out. In such cases, // do nothing. However, it's also possible that we have an uninitialized Loading @@ -2306,7 +2313,6 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac if (value.whyMagic() == JS_OPTIMIZED_OUT) { MOZ_ASSERT(!stub->monitorsThis()); res.set(value); return true; } Loading @@ -2317,32 +2323,38 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac MOZ_ASSERT(stub->monitorsThis() || *GetNextPc(pc) == JSOP_CHECKTHIS || *GetNextPc(pc) == JSOP_CHECKRETURN); if (stub->monitorsThis()) TypeScript::SetThis(cx, script, TypeSet::UnknownType()); else TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType()); return true; } // Note: ideally we would merge this if-else statement with the one below, // but that triggers an MSVC 2015 compiler bug. See bug 1363054. StackTypeSet* types; uint32_t argument; if (stub->monitorsThis()) { MOZ_ASSERT(pc == script->code()); if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) TypeScript::SetThis(cx, script, TypeSet::UnknownType()); if (stub->monitorsArgument(&argument)) types = TypeScript::ArgTypes(script, argument); else if (stub->monitorsThis()) types = TypeScript::ThisTypes(script); else TypeScript::SetThis(cx, script, value); } else if (stub->monitorsArgument(&argument)) { types = TypeScript::BytecodeTypes(script, pc); if (stub->monitorsArgument(&argument)) { MOZ_ASSERT(pc == script->code()); MOZ_ASSERT(!value.isMagic(JS_UNINITIALIZED_LEXICAL)); TypeScript::SetArgument(cx, script, argument, value); } else if (stub->monitorsThis()) { MOZ_ASSERT(pc == script->code()); TypeScript::SetThis(cx, script, value); } else { if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType()); else TypeScript::Monitor(cx, script, pc, value); TypeScript::Monitor(cx, script, pc, types, value); } if (!stub->invalid() && !stub->addMonitorStubForValue(cx, frame, value)) return false; // Copy input value to res. res.set(value); if (MOZ_UNLIKELY(stub->invalid())) return true; return stub->addMonitorStubForValue(cx, frame, types, value); } typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*, Loading
js/src/jit/SharedIC.h +4 −2 Original line number Diff line number Diff line Loading @@ -1208,7 +1208,8 @@ class ICMonitoredFallbackStub : public ICFallbackStub public: MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val); inline ICTypeMonitor_Fallback* fallbackMonitorStub() const { return fallbackMonitorStub_; Loading Loading @@ -1468,7 +1469,8 @@ class ICTypeMonitor_Fallback : public ICStub // Create a new monitor stub for the type of the given value, and // add it to this chain. MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val); MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, StackTypeSet* types, HandleValue val); void resetMonitorStubChain(Zone* zone); Loading
js/src/vm/TypeInference-inl.h +11 −0 Original line number Diff line number Diff line Loading @@ -489,6 +489,8 @@ MarkObjectStateChange(JSContext* cx, JSObject* obj) /* Interface helpers for JSScript*. */ extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type); extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, TypeSet::Type type); extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval); ///////////////////////////////////////////////////////////////////// Loading Loading @@ -589,6 +591,15 @@ TypeScript::Monitor(JSContext* cx, const js::Value& rval) Monitor(cx, script, pc, rval); } /* static */ inline void TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, const js::Value& rval) { TypeSet::Type type = TypeSet::GetValueType(rval); if (!types->hasType(type)) TypeMonitorResult(cx, script, pc, types, type); } /* static */ inline void TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id) { Loading
js/src/vm/TypeInference.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -3341,6 +3341,22 @@ js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet:: types->addType(cx, type); } void js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types, TypeSet::Type type) { assertSameCompartment(cx, script, type); AutoEnterAnalysis enter(cx); MOZ_ASSERT(types == TypeScript::BytecodeTypes(script, pc)); MOZ_ASSERT(!types->hasType(type)); InferSpew(ISpewOps, "bytecodeType: %p %05" PRIuSIZE ": %s", script, script->pcToOffset(pc), TypeSet::TypeString(type)); types->addType(cx, type); } void js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval) { Loading