Loading js/src/jsinfer.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -2205,15 +2205,15 @@ TypeCompartment::addPendingRecompile(JSContext *cx, JSScript *script, jsbytecode RecompileInfo info; info.script = script; if (script->jitNormal) { if (script->jitHandleNormal.isValid()) { info.constructing = false; info.chunkIndex = script->jitNormal->chunkIndex(pc); info.chunkIndex = script->jitHandleNormal.getValid()->chunkIndex(pc); addPendingRecompile(cx, info); } if (script->jitCtor) { if (script->jitHandleCtor.isValid()) { info.constructing = true; info.chunkIndex = script->jitCtor->chunkIndex(pc); info.chunkIndex = script->jitHandleCtor.getValid()->chunkIndex(pc); addPendingRecompile(cx, info); } #endif Loading js/src/jsscript.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1689,7 +1689,7 @@ void JSScript::recompileForStepMode(FreeOp *fop) { #ifdef JS_METHODJIT if (jitNormal || jitCtor) { if (hasJITCode()) { mjit::Recompiler::clearStackReferences(fop, this); mjit::ReleaseScriptCode(fop, this); } Loading js/src/jsscript.h +92 −37 Original line number Diff line number Diff line Loading @@ -272,9 +272,13 @@ namespace JSC { class ExecutablePool; } #define JS_UNJITTABLE_SCRIPT (reinterpret_cast<void*>(1)) namespace js { namespace mjit { struct JITScript; class CallCompiler; } } namespace js { namespace mjit { struct JITScript; } } #endif namespace js { Loading Loading @@ -343,18 +347,61 @@ struct JSScript : public js::gc::Cell static const uint32_t stepFlagMask = 0x80000000U; static const uint32_t stepCountMask = 0x7fffffffU; /* * We order fields according to their size in order to avoid wasting space * for alignment. */ public: // This type wraps JITScript. It has three possible states. // - "Empty": no compilation has been attempted and there is no JITScript. // - "Unjittable": compilation failed and there is no JITScript. // - "Valid": compilation succeeded and there is a JITScript. class JITScriptHandle { // CallCompiler must be a friend because it generates code that uses // UNJITTABLE. friend class js::mjit::CallCompiler; // The exact representation: // - NULL means "empty". // - UNJITTABLE means "unjittable". // - Any other value means "valid". // UNJITTABLE = 1 so that we can check that a JITScript is valid // with a single |> 1| test. It's defined outside the class because // non-integral static const fields can't be defined in the class. static const js::mjit::JITScript *UNJITTABLE; // = (JITScript *)1; js::mjit::JITScript *value; /* Larger-than-word-sized fields. */ public: JITScriptHandle() { value = NULL; } bool isEmpty() { return value == NULL; } bool isUnjittable() { return value == UNJITTABLE; } bool isValid() { return value > UNJITTABLE; } js::mjit::JITScript *getValid() { JS_ASSERT(isValid()); return value; } void setEmpty() { value = NULL; } void setUnjittable() { value = const_cast<js::mjit::JITScript *>(UNJITTABLE); } void setValid(js::mjit::JITScript *jit) { value = jit; JS_ASSERT(isValid()); } static void staticAsserts(); }; // // We order fields according to their size in order to avoid wasting space // for alignment. // // Larger-than-word-sized fields. public: js::Bindings bindings; /* names of top-level variables in this script (and arguments if this is a function script) */ /* Word-sized fields. */ // Word-sized fields. public: jsbytecode *code; /* bytecodes and their immediate operands */ Loading Loading @@ -388,16 +435,10 @@ struct JSScript : public js::gc::Cell /* Persistent type information retained across GCs. */ js::types::TypeScript *types; public: #ifdef JS_METHODJIT // Fast-cached pointers to make calls faster. These are also used to // quickly test whether there is JIT code; a NULL value means no // compilation has been attempted. A JS_UNJITTABLE_SCRIPT value means // compilation failed. Any value is the arity-check entry point. void *jitArityCheckNormal; void *jitArityCheckCtor; js::mjit::JITScript *jitNormal; /* Extra JIT info for normal scripts */ js::mjit::JITScript *jitCtor; /* Extra JIT info for constructors */ JITScriptHandle jitHandleNormal; // extra JIT info for normal scripts JITScriptHandle jitHandleCtor; // extra JIT info for constructors #endif private: Loading @@ -411,7 +452,7 @@ struct JSScript : public js::gc::Cell void *padding_; #endif /* 32-bit fields. */ // 32-bit fields. public: uint32_t length; /* length of code vector */ Loading @@ -424,17 +465,15 @@ struct JSScript : public js::gc::Cell uint32_t natoms; /* length of atoms array */ #ifdef DEBUG /* * Unique identifier within the compartment for this script, used for * printing analysis information. */ // Unique identifier within the compartment for this script, used for // printing analysis information. uint32_t id_; private: uint32_t idpad; public: #endif /* 16-bit fields. */ // 16-bit fields. private: uint16_t version; /* JS version under which script was compiled */ Loading @@ -449,13 +488,11 @@ struct JSScript : public js::gc::Cell uint16_t nslots; /* vars plus maximum stack depth */ uint16_t staticLevel;/* static level for display maintenance */ /* 8-bit fields. */ // 8-bit fields. /* * Offsets to various array structures from the end of this script, or * JSScript::INVALID_OFFSET if the array has length 0. */ public: // Offsets to various array structures from the end of this script, or // JSScript::INVALID_OFFSET if the array has length 0. uint8_t constsOffset; /* offset to the array of constants */ uint8_t objectsOffset; /* offset to the array of nested function, block, scope, xml and one-time regexps Loading @@ -467,7 +504,7 @@ struct JSScript : public js::gc::Cell uint8_t closedArgsOffset; /* offset to the array of closed args */ uint8_t closedVarsOffset; /* offset to the array of closed vars */ /* 1-bit fields. */ // 1-bit fields. public: bool noScriptRval:1; /* no need for result value of last Loading Loading @@ -514,7 +551,9 @@ struct JSScript : public js::gc::Cell bool analyzedArgsUsage_:1; bool needsArgsObj_:1; /* End of fields. Start methods. */ // // End of fields. Start methods. // /* * Two successively less primitive ways to make a new JSScript. The first Loading Loading @@ -601,21 +640,36 @@ struct JSScript : public js::gc::Cell private: bool makeTypes(JSContext *cx); bool makeAnalysis(JSContext *cx); public: #ifdef JS_METHODJIT bool hasJITCode() { return jitNormal || jitCtor; private: // CallCompiler must be a friend because it generates code that directly // accesses jitHandleNormal/jitHandleCtor, via jitHandleOffset(). friend class js::mjit::CallCompiler; static size_t jitHandleOffset(bool constructing) { return constructing ? offsetof(JSScript, jitHandleCtor) : offsetof(JSScript, jitHandleNormal); } // These methods are implemented in MethodJIT.h. inline void **nativeMap(bool constructing); inline void *nativeCodeForPC(bool constructing, jsbytecode *pc); public: bool hasJITCode() { return jitHandleNormal.isValid() || jitHandleCtor.isValid(); } JITScriptHandle *jitHandle(bool constructing) { return constructing ? &jitHandleCtor : &jitHandleNormal; } js::mjit::JITScript *getJIT(bool constructing) { return constructing ? jitCtor : jitNormal; JITScriptHandle *jith = jitHandle(constructing); return jith->isValid() ? jith->getValid() : NULL; } static void ReleaseCode(js::FreeOp *fop, JITScriptHandle *jith); // These methods are implemented in MethodJIT.h. inline void **nativeMap(bool constructing); inline void *nativeCodeForPC(bool constructing, jsbytecode *pc); size_t getUseCount() const { return useCount; } size_t incUseCount() { return ++useCount; } size_t *addressOfUseCount() { return &useCount; } Loading @@ -629,6 +683,7 @@ struct JSScript : public js::gc::Cell size_t sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf); #endif public: js::PCCounts getPCCounts(jsbytecode *pc) { JS_ASSERT(size_t(pc - code) < length); return scriptCounts.pcCountsVector[pc - code]; Loading js/src/methodjit/Compiler.cpp +14 −20 Original line number Diff line number Diff line Loading @@ -143,13 +143,12 @@ mjit::Compiler::compile() { JS_ASSERT(!outerChunkRef().chunk); void **checkAddr = isConstructing ? &outerScript->jitArityCheckCtor : &outerScript->jitArityCheckNormal; CompileStatus status = performCompilation(); if (status != Compile_Okay && status != Compile_Retry) { *checkAddr = JS_UNJITTABLE_SCRIPT; JSScript::JITScriptHandle *jith = outerScript->jitHandle(isConstructing); JSScript::ReleaseCode(cx->runtime->defaultFreeOp(), jith); jith->setUnjittable(); if (outerScript->function()) { outerScript->uninlineable = true; types::MarkTypeObjectFlags(cx, outerScript->function(), Loading Loading @@ -658,15 +657,13 @@ mjit::SetChunkLimit(uint32_t limit) } JITScript * MakeJITScript(JSContext *cx, JSScript *script, bool construct) MakeJITScript(JSContext *cx, JSScript *script) { if (!script->ensureRanAnalysis(cx, NULL)) return NULL; ScriptAnalysis *analysis = script->analysis(); JITScript *&location = construct ? script->jitCtor : script->jitNormal; Vector<ChunkDescriptor> chunks(cx); Vector<CrossChunkEdge> edges(cx); Loading Loading @@ -895,10 +892,8 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct) } } if (edges.empty()) { location = jit; if (edges.empty()) return jit; } jit->nedges = edges.length(); CrossChunkEdge *jitEdges = jit->edges(); Loading Loading @@ -937,7 +932,6 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct) edge.shimLabel = shimCode + (size_t) edge.shimLabel; } location = jit; return jit; } Loading @@ -949,12 +943,10 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc, if (!cx->methodJitEnabled) return Compile_Abort; void *addr = construct ? script->jitArityCheckCtor : script->jitArityCheckNormal; if (addr == JS_UNJITTABLE_SCRIPT) JSScript::JITScriptHandle *jith = script->jitHandle(construct); if (jith->isUnjittable()) return Compile_Abort; JITScript *jit = script->getJIT(construct); if (request == CompileRequest_Interpreter && !cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) && (cx->typeInferenceEnabled() Loading @@ -971,10 +963,14 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc, if (construct && !script->nslots) script->nslots++; if (!jit) { jit = MakeJITScript(cx, script, construct); JITScript *jit; if (jith->isEmpty()) { jit = MakeJITScript(cx, script); if (!jit) return Compile_Error; jith->setValid(jit); } else { jit = jith->getValid(); } unsigned chunkIndex = jit->chunkIndex(pc); ChunkDescriptor &desc = jit->chunkDescriptor(chunkIndex); Loading Loading @@ -1378,8 +1374,6 @@ mjit::Compiler::finishThisUp() jit->arityCheckEntry = stubCode.locationOf(arityLabel).executableAddress(); jit->argsCheckEntry = stubCode.locationOf(argsCheckLabel).executableAddress(); jit->fastEntry = fullCode.locationOf(invokeLabel).executableAddress(); void *&addr = isConstructing ? script->jitArityCheckCtor : script->jitArityCheckNormal; addr = jit->arityCheckEntry; } } Loading js/src/methodjit/MethodJIT.cpp +23 −20 Original line number Diff line number Diff line Loading @@ -1362,13 +1362,8 @@ JITScript::destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses) invokeEntry = NULL; fastEntry = NULL; arityCheckEntry = NULL; argsCheckEntry = NULL; if (script->jitNormal == this) script->jitArityCheckNormal = NULL; else script->jitArityCheckCtor = NULL; arityCheckEntry = NULL; // Fixup any ICs still referring to this chunk. while (!JS_CLIST_IS_EMPTY(&callers)) { Loading @@ -1385,14 +1380,27 @@ JITScript::destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses) } } const js::mjit::JITScript *JSScript::JITScriptHandle::UNJITTABLE = reinterpret_cast<js::mjit::JITScript *>(1); void JSScript::JITScriptHandle::staticAsserts() { // JITScriptHandle's memory layout must match that of JITScript *. JS_STATIC_ASSERT(sizeof(JSScript::JITScriptHandle) == sizeof(js::mjit::JITScript *)); JS_STATIC_ASSERT(JS_ALIGNMENT_OF(JSScript::JITScriptHandle) == JS_ALIGNMENT_OF(js::mjit::JITScript *)); JS_STATIC_ASSERT(offsetof(JSScript::JITScriptHandle, value) == 0); } size_t JSScript::sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf) { size_t n = 0; if (jitNormal) n += jitNormal->sizeOfIncludingThis(mallocSizeOf); if (jitCtor) n += jitCtor->sizeOfIncludingThis(mallocSizeOf); if (jitHandleNormal.isValid()) n += jitHandleNormal.getValid()->sizeOfIncludingThis(mallocSizeOf); if (jitHandleCtor.isValid()) n += jitHandleCtor.getValid()->sizeOfIncludingThis(mallocSizeOf); return n; } Loading Loading @@ -1438,21 +1446,16 @@ mjit::JITChunk::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) } void mjit::ReleaseScriptCode(FreeOp *fop, JSScript *script, bool construct) JSScript::ReleaseCode(FreeOp *fop, JITScriptHandle *jith) { // NB: The recompiler may call ReleaseScriptCode, in which case it // will get called again when the script is destroyed, so we // must protect against calling ReleaseScriptCode twice. JITScript **pjit = construct ? &script->jitCtor : &script->jitNormal; void **parity = construct ? &script->jitArityCheckCtor : &script->jitArityCheckNormal; if (*pjit) { (*pjit)->destroy(fop); fop->free_(*pjit); *pjit = NULL; *parity = NULL; } JITScript *jit = jith->getValid(); jit->destroy(fop); fop->free_(jit); jith->setEmpty(); } #ifdef JS_METHODJIT_PROFILE_STUBS Loading Loading
js/src/jsinfer.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -2205,15 +2205,15 @@ TypeCompartment::addPendingRecompile(JSContext *cx, JSScript *script, jsbytecode RecompileInfo info; info.script = script; if (script->jitNormal) { if (script->jitHandleNormal.isValid()) { info.constructing = false; info.chunkIndex = script->jitNormal->chunkIndex(pc); info.chunkIndex = script->jitHandleNormal.getValid()->chunkIndex(pc); addPendingRecompile(cx, info); } if (script->jitCtor) { if (script->jitHandleCtor.isValid()) { info.constructing = true; info.chunkIndex = script->jitCtor->chunkIndex(pc); info.chunkIndex = script->jitHandleCtor.getValid()->chunkIndex(pc); addPendingRecompile(cx, info); } #endif Loading
js/src/jsscript.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1689,7 +1689,7 @@ void JSScript::recompileForStepMode(FreeOp *fop) { #ifdef JS_METHODJIT if (jitNormal || jitCtor) { if (hasJITCode()) { mjit::Recompiler::clearStackReferences(fop, this); mjit::ReleaseScriptCode(fop, this); } Loading
js/src/jsscript.h +92 −37 Original line number Diff line number Diff line Loading @@ -272,9 +272,13 @@ namespace JSC { class ExecutablePool; } #define JS_UNJITTABLE_SCRIPT (reinterpret_cast<void*>(1)) namespace js { namespace mjit { struct JITScript; class CallCompiler; } } namespace js { namespace mjit { struct JITScript; } } #endif namespace js { Loading Loading @@ -343,18 +347,61 @@ struct JSScript : public js::gc::Cell static const uint32_t stepFlagMask = 0x80000000U; static const uint32_t stepCountMask = 0x7fffffffU; /* * We order fields according to their size in order to avoid wasting space * for alignment. */ public: // This type wraps JITScript. It has three possible states. // - "Empty": no compilation has been attempted and there is no JITScript. // - "Unjittable": compilation failed and there is no JITScript. // - "Valid": compilation succeeded and there is a JITScript. class JITScriptHandle { // CallCompiler must be a friend because it generates code that uses // UNJITTABLE. friend class js::mjit::CallCompiler; // The exact representation: // - NULL means "empty". // - UNJITTABLE means "unjittable". // - Any other value means "valid". // UNJITTABLE = 1 so that we can check that a JITScript is valid // with a single |> 1| test. It's defined outside the class because // non-integral static const fields can't be defined in the class. static const js::mjit::JITScript *UNJITTABLE; // = (JITScript *)1; js::mjit::JITScript *value; /* Larger-than-word-sized fields. */ public: JITScriptHandle() { value = NULL; } bool isEmpty() { return value == NULL; } bool isUnjittable() { return value == UNJITTABLE; } bool isValid() { return value > UNJITTABLE; } js::mjit::JITScript *getValid() { JS_ASSERT(isValid()); return value; } void setEmpty() { value = NULL; } void setUnjittable() { value = const_cast<js::mjit::JITScript *>(UNJITTABLE); } void setValid(js::mjit::JITScript *jit) { value = jit; JS_ASSERT(isValid()); } static void staticAsserts(); }; // // We order fields according to their size in order to avoid wasting space // for alignment. // // Larger-than-word-sized fields. public: js::Bindings bindings; /* names of top-level variables in this script (and arguments if this is a function script) */ /* Word-sized fields. */ // Word-sized fields. public: jsbytecode *code; /* bytecodes and their immediate operands */ Loading Loading @@ -388,16 +435,10 @@ struct JSScript : public js::gc::Cell /* Persistent type information retained across GCs. */ js::types::TypeScript *types; public: #ifdef JS_METHODJIT // Fast-cached pointers to make calls faster. These are also used to // quickly test whether there is JIT code; a NULL value means no // compilation has been attempted. A JS_UNJITTABLE_SCRIPT value means // compilation failed. Any value is the arity-check entry point. void *jitArityCheckNormal; void *jitArityCheckCtor; js::mjit::JITScript *jitNormal; /* Extra JIT info for normal scripts */ js::mjit::JITScript *jitCtor; /* Extra JIT info for constructors */ JITScriptHandle jitHandleNormal; // extra JIT info for normal scripts JITScriptHandle jitHandleCtor; // extra JIT info for constructors #endif private: Loading @@ -411,7 +452,7 @@ struct JSScript : public js::gc::Cell void *padding_; #endif /* 32-bit fields. */ // 32-bit fields. public: uint32_t length; /* length of code vector */ Loading @@ -424,17 +465,15 @@ struct JSScript : public js::gc::Cell uint32_t natoms; /* length of atoms array */ #ifdef DEBUG /* * Unique identifier within the compartment for this script, used for * printing analysis information. */ // Unique identifier within the compartment for this script, used for // printing analysis information. uint32_t id_; private: uint32_t idpad; public: #endif /* 16-bit fields. */ // 16-bit fields. private: uint16_t version; /* JS version under which script was compiled */ Loading @@ -449,13 +488,11 @@ struct JSScript : public js::gc::Cell uint16_t nslots; /* vars plus maximum stack depth */ uint16_t staticLevel;/* static level for display maintenance */ /* 8-bit fields. */ // 8-bit fields. /* * Offsets to various array structures from the end of this script, or * JSScript::INVALID_OFFSET if the array has length 0. */ public: // Offsets to various array structures from the end of this script, or // JSScript::INVALID_OFFSET if the array has length 0. uint8_t constsOffset; /* offset to the array of constants */ uint8_t objectsOffset; /* offset to the array of nested function, block, scope, xml and one-time regexps Loading @@ -467,7 +504,7 @@ struct JSScript : public js::gc::Cell uint8_t closedArgsOffset; /* offset to the array of closed args */ uint8_t closedVarsOffset; /* offset to the array of closed vars */ /* 1-bit fields. */ // 1-bit fields. public: bool noScriptRval:1; /* no need for result value of last Loading Loading @@ -514,7 +551,9 @@ struct JSScript : public js::gc::Cell bool analyzedArgsUsage_:1; bool needsArgsObj_:1; /* End of fields. Start methods. */ // // End of fields. Start methods. // /* * Two successively less primitive ways to make a new JSScript. The first Loading Loading @@ -601,21 +640,36 @@ struct JSScript : public js::gc::Cell private: bool makeTypes(JSContext *cx); bool makeAnalysis(JSContext *cx); public: #ifdef JS_METHODJIT bool hasJITCode() { return jitNormal || jitCtor; private: // CallCompiler must be a friend because it generates code that directly // accesses jitHandleNormal/jitHandleCtor, via jitHandleOffset(). friend class js::mjit::CallCompiler; static size_t jitHandleOffset(bool constructing) { return constructing ? offsetof(JSScript, jitHandleCtor) : offsetof(JSScript, jitHandleNormal); } // These methods are implemented in MethodJIT.h. inline void **nativeMap(bool constructing); inline void *nativeCodeForPC(bool constructing, jsbytecode *pc); public: bool hasJITCode() { return jitHandleNormal.isValid() || jitHandleCtor.isValid(); } JITScriptHandle *jitHandle(bool constructing) { return constructing ? &jitHandleCtor : &jitHandleNormal; } js::mjit::JITScript *getJIT(bool constructing) { return constructing ? jitCtor : jitNormal; JITScriptHandle *jith = jitHandle(constructing); return jith->isValid() ? jith->getValid() : NULL; } static void ReleaseCode(js::FreeOp *fop, JITScriptHandle *jith); // These methods are implemented in MethodJIT.h. inline void **nativeMap(bool constructing); inline void *nativeCodeForPC(bool constructing, jsbytecode *pc); size_t getUseCount() const { return useCount; } size_t incUseCount() { return ++useCount; } size_t *addressOfUseCount() { return &useCount; } Loading @@ -629,6 +683,7 @@ struct JSScript : public js::gc::Cell size_t sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf); #endif public: js::PCCounts getPCCounts(jsbytecode *pc) { JS_ASSERT(size_t(pc - code) < length); return scriptCounts.pcCountsVector[pc - code]; Loading
js/src/methodjit/Compiler.cpp +14 −20 Original line number Diff line number Diff line Loading @@ -143,13 +143,12 @@ mjit::Compiler::compile() { JS_ASSERT(!outerChunkRef().chunk); void **checkAddr = isConstructing ? &outerScript->jitArityCheckCtor : &outerScript->jitArityCheckNormal; CompileStatus status = performCompilation(); if (status != Compile_Okay && status != Compile_Retry) { *checkAddr = JS_UNJITTABLE_SCRIPT; JSScript::JITScriptHandle *jith = outerScript->jitHandle(isConstructing); JSScript::ReleaseCode(cx->runtime->defaultFreeOp(), jith); jith->setUnjittable(); if (outerScript->function()) { outerScript->uninlineable = true; types::MarkTypeObjectFlags(cx, outerScript->function(), Loading Loading @@ -658,15 +657,13 @@ mjit::SetChunkLimit(uint32_t limit) } JITScript * MakeJITScript(JSContext *cx, JSScript *script, bool construct) MakeJITScript(JSContext *cx, JSScript *script) { if (!script->ensureRanAnalysis(cx, NULL)) return NULL; ScriptAnalysis *analysis = script->analysis(); JITScript *&location = construct ? script->jitCtor : script->jitNormal; Vector<ChunkDescriptor> chunks(cx); Vector<CrossChunkEdge> edges(cx); Loading Loading @@ -895,10 +892,8 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct) } } if (edges.empty()) { location = jit; if (edges.empty()) return jit; } jit->nedges = edges.length(); CrossChunkEdge *jitEdges = jit->edges(); Loading Loading @@ -937,7 +932,6 @@ MakeJITScript(JSContext *cx, JSScript *script, bool construct) edge.shimLabel = shimCode + (size_t) edge.shimLabel; } location = jit; return jit; } Loading @@ -949,12 +943,10 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc, if (!cx->methodJitEnabled) return Compile_Abort; void *addr = construct ? script->jitArityCheckCtor : script->jitArityCheckNormal; if (addr == JS_UNJITTABLE_SCRIPT) JSScript::JITScriptHandle *jith = script->jitHandle(construct); if (jith->isUnjittable()) return Compile_Abort; JITScript *jit = script->getJIT(construct); if (request == CompileRequest_Interpreter && !cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) && (cx->typeInferenceEnabled() Loading @@ -971,10 +963,14 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc, if (construct && !script->nslots) script->nslots++; if (!jit) { jit = MakeJITScript(cx, script, construct); JITScript *jit; if (jith->isEmpty()) { jit = MakeJITScript(cx, script); if (!jit) return Compile_Error; jith->setValid(jit); } else { jit = jith->getValid(); } unsigned chunkIndex = jit->chunkIndex(pc); ChunkDescriptor &desc = jit->chunkDescriptor(chunkIndex); Loading Loading @@ -1378,8 +1374,6 @@ mjit::Compiler::finishThisUp() jit->arityCheckEntry = stubCode.locationOf(arityLabel).executableAddress(); jit->argsCheckEntry = stubCode.locationOf(argsCheckLabel).executableAddress(); jit->fastEntry = fullCode.locationOf(invokeLabel).executableAddress(); void *&addr = isConstructing ? script->jitArityCheckCtor : script->jitArityCheckNormal; addr = jit->arityCheckEntry; } } Loading
js/src/methodjit/MethodJIT.cpp +23 −20 Original line number Diff line number Diff line Loading @@ -1362,13 +1362,8 @@ JITScript::destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses) invokeEntry = NULL; fastEntry = NULL; arityCheckEntry = NULL; argsCheckEntry = NULL; if (script->jitNormal == this) script->jitArityCheckNormal = NULL; else script->jitArityCheckCtor = NULL; arityCheckEntry = NULL; // Fixup any ICs still referring to this chunk. while (!JS_CLIST_IS_EMPTY(&callers)) { Loading @@ -1385,14 +1380,27 @@ JITScript::destroyChunk(FreeOp *fop, unsigned chunkIndex, bool resetUses) } } const js::mjit::JITScript *JSScript::JITScriptHandle::UNJITTABLE = reinterpret_cast<js::mjit::JITScript *>(1); void JSScript::JITScriptHandle::staticAsserts() { // JITScriptHandle's memory layout must match that of JITScript *. JS_STATIC_ASSERT(sizeof(JSScript::JITScriptHandle) == sizeof(js::mjit::JITScript *)); JS_STATIC_ASSERT(JS_ALIGNMENT_OF(JSScript::JITScriptHandle) == JS_ALIGNMENT_OF(js::mjit::JITScript *)); JS_STATIC_ASSERT(offsetof(JSScript::JITScriptHandle, value) == 0); } size_t JSScript::sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf) { size_t n = 0; if (jitNormal) n += jitNormal->sizeOfIncludingThis(mallocSizeOf); if (jitCtor) n += jitCtor->sizeOfIncludingThis(mallocSizeOf); if (jitHandleNormal.isValid()) n += jitHandleNormal.getValid()->sizeOfIncludingThis(mallocSizeOf); if (jitHandleCtor.isValid()) n += jitHandleCtor.getValid()->sizeOfIncludingThis(mallocSizeOf); return n; } Loading Loading @@ -1438,21 +1446,16 @@ mjit::JITChunk::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) } void mjit::ReleaseScriptCode(FreeOp *fop, JSScript *script, bool construct) JSScript::ReleaseCode(FreeOp *fop, JITScriptHandle *jith) { // NB: The recompiler may call ReleaseScriptCode, in which case it // will get called again when the script is destroyed, so we // must protect against calling ReleaseScriptCode twice. JITScript **pjit = construct ? &script->jitCtor : &script->jitNormal; void **parity = construct ? &script->jitArityCheckCtor : &script->jitArityCheckNormal; if (*pjit) { (*pjit)->destroy(fop); fop->free_(*pjit); *pjit = NULL; *parity = NULL; } JITScript *jit = jith->getValid(); jit->destroy(fop); fop->free_(jit); jith->setEmpty(); } #ifdef JS_METHODJIT_PROFILE_STUBS Loading