author | Sean Stangl <sstangl@mozilla.com> |
Wed, 14 Jul 2010 22:56:06 -0700 | |
changeset 53119 | d83e40b415682d6d233a02be09751b54ef01f6e4 |
parent 53118 | eff02554170ae71c7a9144e557f678b330c4cc83 |
child 53120 | a998833b71780025fcea3f2bcc50bb51634f505a |
push id | 15660 |
push user | rsayre@mozilla.com |
push date | Sat, 11 Sep 2010 19:16:24 +0000 |
treeherder | mozilla-central@f1bd314e64ac [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 578896 |
milestone | 2.0b2pre |
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/configure.in +++ b/js/src/configure.in @@ -2575,16 +2575,18 @@ fi dnl Configure JIT support case "$target" in i?86-*) ENABLE_TRACEJIT=1 NANOJIT_ARCH=i386 ENABLE_METHODJIT=1 + ENABLE_MONOIC=1 + ENABLE_POLYIC=1 AC_DEFINE(JS_CPU_X86) AC_DEFINE(JS_32BIT) ;; x86_64*-*) ENABLE_TRACEJIT=1 NANOJIT_ARCH=X64 AC_DEFINE(JS_CPU_X64) ;; @@ -2601,16 +2603,24 @@ sparc*-*) AC_DEFINE(JS_CPU_SPARC) ;; esac MOZ_ARG_DISABLE_BOOL(methodjit, [ --disable-methodjit Disable method JIT support], ENABLE_METHODJIT= ) +MOZ_ARG_DISABLE_BOOL(monoic, +[ --disable-monoic Disable use of MICs by JIT compiler], + ENABLE_MONOIC= ) + +MOZ_ARG_DISABLE_BOOL(polyic, +[ --disable-polyic Disable use of PICs by JIT compiler], + ENABLE_POLYIC= ) + MOZ_ARG_DISABLE_BOOL(tracejit, [ --disable-tracejit Disable tracing JIT support], ENABLE_TRACEJIT=) MOZ_ARG_ENABLE_BOOL(methodjit-spew, [ --enable-methodjit-spew Enable method JIT spew support], ENABLE_METHODJIT_SPEW=1, ENABLE_METHODJIT_SPEW= ) @@ -2618,16 +2628,24 @@ MOZ_ARG_ENABLE_BOOL(methodjit-spew, AC_SUBST(ENABLE_METHODJIT) if test "$ENABLE_METHODJIT"; then AC_DEFINE(JS_METHODJIT) else ENABLE_TRACEJIT= fi +if test "$ENABLE_MONOIC"; then + AC_DEFINE(JS_MONOIC) +fi + +if test "$ENABLE_POLYIC"; then + AC_DEFINE(JS_POLYIC) +fi + if test "$ENABLE_METHODJIT_SPEW"; then AC_DEFINE(JS_METHODJIT_SPEW) fi if test "$ENABLE_TRACEJIT"; then AC_DEFINE(FEATURE_NANOJIT) AC_DEFINE(JS_TRACER)
--- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -157,18 +157,22 @@ struct GlobalSlotArray { #ifdef JS_METHODJIT namespace JSC { class ExecutablePool; } namespace js { namespace mjit { namespace ic { +# if defined JS_POLYIC struct PICInfo; +# endif +# if defined JS_MONOIC struct MICInfo; +# endif } } } #endif struct JSScript { jsbytecode *code; /* bytecodes and their immediate operands */ uint32 length; /* length of code vector */ @@ -211,30 +215,36 @@ struct JSScript { JSThread *owner; /* for thread-safe life-cycle assertions */ #endif #ifdef JS_METHODJIT // Note: the other pointers in this group may be non-NULL only if // |execPool| is non-NULL. void *ncode; /* native code compiled by the method JIT */ void **nmap; /* maps PCs to native code */ JSC::ExecutablePool *execPool; /* pool that contains |ncode|; script owns the pool */ +# if defined JS_POLYIC js::mjit::ic::PICInfo *pics; /* PICs in this script */ +# endif +# if defined JS_MONOIC js::mjit::ic::MICInfo *mics; /* MICs in this script. */ +# endif # ifdef DEBUG uint32 jitLength; /* length of JIT'd code */ inline bool isValidJitCode(void *jcode) { return (char*)jcode >= (char*)ncode && (char*)jcode < (char*)ncode + jitLength; } # endif +# if defined JS_POLYIC inline uint32 numPICs() { return pics ? *(uint32*)((uint8 *)pics - sizeof(uint32)) : 0; } +# endif #endif #if 0 /* def JS_TRACER */ js::TraceTreeCache *trees; /* trace tree info. */ uint32 tmGen; /* generation number from the TraceMonitor */ #endif uint32 tracePoints; /* number of trace points in the script */ /* Script notes are allocated right after the code. */
--- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -74,18 +74,24 @@ static const JSC::MacroAssembler::Regist #elif defined(JS_CPU_ARM) static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::ARMRegisters::r2; static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::ARMRegisters::r1; #endif mjit::Compiler::Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain) : cx(cx), script(script), scopeChain(scopeChain), globalObj(scopeChain->getGlobal()), fun(fun), analysis(cx, script), jumpMap(NULL), frame(cx, script, masm), - branchPatches(ContextAllocPolicy(cx)), mics(ContextAllocPolicy(cx)), - pics(ContextAllocPolicy(cx)), stubcc(cx, *this, frame, script) + branchPatches(ContextAllocPolicy(cx)), +#if defined JS_MONOIC + mics(ContextAllocPolicy(cx)), +#endif +#if defined JS_POLYIC + pics(ContextAllocPolicy(cx)), +#endif + stubcc(cx, *this, frame, script) { #ifdef DEBUG masm.setSpewPath(false); #endif } #define CHECK_STATUS(expr) \ JS_BEGIN_MACRO \ @@ -257,38 +263,43 @@ mjit::Compiler::finishThisUp() for (size_t i = 0; i < script->length; i++) { Label L = jumpMap[i]; if (analysis[i].safePoint) { JS_ASSERT(L.isValid()); nmap[i] = (uint8 *)(result + masm.distanceOf(L)); } } +#if defined JS_MONOIC if (mics.length()) { script->mics = (ic::MICInfo *)cx->calloc(sizeof(ic::MICInfo) * mics.length()); if (!script->mics) { execPool->release(); return Compile_Error; } } +#endif JSC::LinkBuffer fullCode(result, masm.size() + stubcc.size()); JSC::LinkBuffer stubCode(result + masm.size(), stubcc.size()); +#if defined JS_MONOIC for (size_t i = 0; i < mics.length(); i++) { script->mics[i].entry = fullCode.locationOf(mics[i].entry); script->mics[i].load = fullCode.locationOf(mics[i].load); script->mics[i].shape = fullCode.locationOf(mics[i].shapeVal); script->mics[i].stubCall = stubCode.locationOf(mics[i].call); script->mics[i].stubEntry = stubCode.locationOf(mics[i].stubEntry); script->mics[i].kind = mics[i].kind; script->mics[i].typeConst = mics[i].typeConst; script->mics[i].dataConst = mics[i].dataConst; script->mics[i].dataWrite = mics[i].dataWrite; } - +#endif /* JS_MONOIC */ + +#if defined JS_POLYIC if (pics.length()) { uint8 *cursor = (uint8 *)cx->calloc(sizeof(ic::PICInfo) * pics.length() + sizeof(uint32)); if (!cursor) { execPool->release(); return Compile_Error; } *(uint32*)cursor = pics.length(); cursor += sizeof(uint32); @@ -319,16 +330,17 @@ mjit::Compiler::finishThisUp() script->pics[i].u.get.typeCheckOffset = uint16(-distance); JS_ASSERT(script->pics[i].u.get.typeCheckOffset == -distance); } script->pics[i].u.get.hasTypeCheck = pics[i].hasTypeCheck; script->pics[i].u.get.objRemat = pics[i].objRemat.offset; } new (&script->pics[i].execPools) ic::PICInfo::ExecPoolVector(SystemAllocPolicy()); } +#endif /* JS_POLYIC */ /* Link fast and slow paths together. */ stubcc.fixCrossJumps(result, masm.size(), masm.size() + stubcc.size()); /* Patch all outgoing calls. */ masm.finalize(result); stubcc.finalize(result + masm.size()); @@ -1837,27 +1849,27 @@ mjit::Compiler::jsop_length() RegisterID str = frame.ownRegForData(top); masm.loadPtr(Address(str, offsetof(JSString, mLength)), str); frame.pop(); frame.pushTypedPayload(JSVAL_TYPE_INT32, str); } return; } -#if ENABLE_PIC +#if defined JS_POLYIC jsop_getprop(cx->runtime->atomState.lengthAtom); #else prepareStubCall(Uses(1)); stubCall(stubs::Length); frame.pop(); frame.pushSynced(); #endif } -#if ENABLE_PIC +#if defined JS_POLYIC void mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck) { FrameEntry *top = frame.peek(-1); /* If the incoming type will never PIC, take slow path. */ if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) { JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom, @@ -2342,36 +2354,36 @@ mjit::Compiler::jsop_bindname(uint32 ind frame.pushTypedPayload(JSVAL_TYPE_OBJECT, pic.objReg); frame.freeReg(pic.shapeReg); stubcc.rejoin(Changes(1)); pics.append(pic); } -#else /* ENABLE_PIC */ +#else /* JS_POLYIC */ void mjit::Compiler::jsop_name(JSAtom *atom) { prepareStubCall(Uses(0)); stubCall(stubs::Name); frame.pushSynced(); } void mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck) { jsop_getprop_slow(); } -void +bool mjit::Compiler::jsop_callprop(JSAtom *atom) { - jsop_callprop_slow(atom); + return jsop_callprop_slow(atom); } void mjit::Compiler::jsop_setprop(JSAtom *atom) { jsop_setprop_slow(atom); } @@ -2438,21 +2450,21 @@ mjit::Compiler::jsop_gnameinc(JSOp op, V stubCall(stub); frame.pushSynced(); } void mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index) { JSAtom *atom = script->getAtom(index); +#if defined JS_POLYIC jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH]; bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; int amt = (op == JSOP_NAMEINC || op == JSOP_INCNAME) ? -1 : 1; -#if ENABLE_PIC if (pop || (op == JSOP_INCNAME || op == JSOP_DECNAME)) { /* These cases are easy, the original value is not observed. */ jsop_name(atom); // V frame.push(Int32Value(amt)); // V 1 @@ -2509,38 +2521,39 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo // N OBJ N+1 jsop_setprop(atom); // N N+1 frame.pop(); // N } + + if (pop) + PC += JSOP_POP_LENGTH; #else prepareStubCall(Uses(1)); masm.move(ImmPtr(atom), Registers::ArgReg1); stubCall(stub); frame.pop(); frame.pushSynced(); #endif PC += JSOP_NAMEINC_LENGTH; - if (pop) - PC += JSOP_POP_LENGTH; } void mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index) { JSAtom *atom = script->getAtom(index); +#if defined JS_POLYIC jsbytecode *next = &PC[JSOP_PROPINC_LENGTH]; bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; int amt = (op == JSOP_PROPINC || op == JSOP_INCPROP) ? -1 : 1; -#if ENABLE_PIC if (pop || (op == JSOP_INCPROP || op == JSOP_DECPROP)) { /* These cases are easy, the original value is not observed. */ frame.dup(); // OBJ OBJ jsop_getprop(atom); // OBJ V @@ -2588,27 +2601,27 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo // OBJ N N+1 N+1 frame.popn(2); // OBJ N frame.shimmy(1); // N } + if (pop) + PC += JSOP_POP_LENGTH; #else prepareStubCall(Uses(1)); masm.move(ImmPtr(atom), Registers::ArgReg1); stubCall(stub); frame.pop(); frame.pushSynced(); #endif PC += JSOP_PROPINC_LENGTH; - if (pop) - PC += JSOP_POP_LENGTH; } /* * This big nasty function emits a fast-path for native iterators, producing * a temporary value on the stack for FORLOCAL,ARG,GLOBAL,etc ops to use. */ void mjit::Compiler::iterNext() @@ -2744,17 +2757,17 @@ mjit::Compiler::jsop_bindgname() stubCall(stubs::BindGlobalName); frame.takeReg(Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg); } void mjit::Compiler::jsop_getgname(uint32 index) { -#if ENABLE_MIC +#if defined JS_MONOIC jsop_bindgname(); FrameEntry *fe = frame.peek(-1); JS_ASSERT(fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_OBJECT); MICGenInfo mic(ic::MICInfo::GET); RegisterID objReg; Jump shapeGuard; @@ -2821,17 +2834,17 @@ mjit::Compiler::jsop_setgname_slow(uint3 stubCall(stubs::SetGlobalName); frame.popn(2); frame.pushSynced(); } void mjit::Compiler::jsop_setgname(uint32 index) { -#if ENABLE_MIC +#if defined JS_MONOIC FrameEntry *objFe = frame.peek(-2); JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT); MICGenInfo mic(ic::MICInfo::SET); RegisterID objReg; Jump shapeGuard; mic.entry = masm.label();
--- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -69,30 +69,33 @@ class Compiler BranchPatch(const Jump &j, jsbytecode *pc) : jump(j), pc(pc) { } Jump jump; jsbytecode *pc; }; +#if defined JS_MONOIC struct MICGenInfo { MICGenInfo(ic::MICInfo::Kind kind) : kind(kind) { } Label entry; Label stubEntry; DataLabelPtr shapeVal; Label load; Call call; ic::MICInfo::Kind kind; bool typeConst; bool dataConst; bool dataWrite; }; +#endif +#if defined JS_POLYIC struct PICGenInfo { PICGenInfo(ic::PICInfo::Kind kind) : kind(kind) { } ic::PICInfo::Kind kind; Label hotPathBegin; Label storeBack; Label typeCheck; Label slowPathStart; @@ -101,16 +104,17 @@ class Compiler RegisterID typeReg; Label shapeGuard; JSAtom *atom; StateRemat objRemat; Call callReturn; bool hasTypeCheck; ValueRemat vr; }; +#endif struct Defs { Defs(uint32 ndefs) : ndefs(ndefs) { } uint32 ndefs; }; @@ -150,18 +154,22 @@ class Compiler JSObject *globalObj; JSFunction *fun; BytecodeAnalyzer analysis; Label *jumpMap; jsbytecode *PC; Assembler masm; FrameState frame; js::Vector<BranchPatch, 64> branchPatches; +#if defined JS_MONOIC js::Vector<MICGenInfo, 64> mics; +#endif +#if defined JS_POLYIC js::Vector<PICGenInfo, 64> pics; +#endif StubCompiler stubcc; Label invokeLabel; public: // Special atom index used to indicate that the atom is 'length'. This // follows interpreter usage in JSOP_LENGTH. enum { LengthAtomIndex = uint32(-2) };
--- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -574,18 +574,22 @@ ThreadData::removeScript(JSScript *scrip void ThreadData::purge(JSContext *cx) { if (!cx->runtime->gcRegenShapes) return; for (ThreadData::ScriptSet::Enum e(picScripts); !e.empty(); e.popFront()) { JSScript *script = e.front(); +#if defined JS_POLYIC ic::PurgePICs(cx, script); +#endif +#if defined JS_MONOIC //PurgeMICs(cs, script); +#endif } picScripts.clear(); } extern "C" JSBool JaegerTrampoline(JSContext *cx, JSStackFrame *fp, void *code, uintptr_t inlineCallCount); @@ -660,37 +664,39 @@ mjit::ReleaseScriptCode(JSContext *cx, J script->execPool->release(); script->execPool = NULL; // Releasing the execPool takes care of releasing the code. script->ncode = NULL; #ifdef DEBUG script->jitLength = 0; #endif -#if ENABLE_PIC +#if defined JS_POLYIC if (script->pics) { uint32 npics = script->numPICs(); for (uint32 i = 0; i < npics; i++) { script->pics[i].releasePools(); Destroy(script->pics[i].execPools); } JS_METHODJIT_DATA(cx).removeScript(script); cx->free((uint8*)script->pics - sizeof(uint32)); } #endif } if (script->nmap) { cx->free(script->nmap - 1); script->nmap = NULL; } +#if defined JS_MONOIC if (script->mics) { cx->free(script->mics); script->mics = NULL; } +#endif # if 0 /* def JS_TRACER */ if (script->trees) { cx->free(script->trees); script->trees = NULL; } # endif }
--- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -44,16 +44,18 @@ #include "assembler/assembler/RepatchBuffer.h" #include "jsscopeinlines.h" using namespace js; using namespace js::mjit; using namespace js::mjit::ic; +#if defined JS_MONOIC + static void PatchGetFallback(VMFrame &f, ic::MICInfo &mic) { JSC::RepatchBuffer repatch(mic.stubEntry.executableAddress(), 64); JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stubs::GetGlobalName)); repatch.relink(mic.stubCall, fptr); } @@ -165,8 +167,9 @@ ic::SetGlobalName(VMFrame &f, uint32 ind dataOffset = MICInfo::SET_DATA_TYPE_OFFSET; if (mic.dataWrite) stores.repatch(mic.load.dataLabel32AtOffset(dataOffset), slot); /* Do load anyway... this time. */ stubs::SetGlobalName(f, atom); } +#endif /* JS_MONOIC */
--- a/js/src/methodjit/MonoIC.h +++ b/js/src/methodjit/MonoIC.h @@ -33,24 +33,22 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#if !defined jsjaeger_mono_ic_h__ && defined JS_METHODJIT +#if !defined jsjaeger_mono_ic_h__ && defined JS_METHODJIT && defined JS_MONOIC #define jsjaeger_mono_ic_h__ #include "assembler/assembler/CodeLocation.h" #include "methodjit/MethodJIT.h" -#define ENABLE_MIC 1 - namespace js { namespace mjit { namespace ic { struct MICInfo { #ifdef JS_CPU_X86 static const uint32 GET_DATA_OFFSET = 9; static const uint32 GET_TYPE_OFFSET = 15;
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -47,17 +47,17 @@ #include "jsscopeinlines.h" #include "jspropertycache.h" #include "jspropertycacheinlines.h" #include "jsautooplen.h" using namespace js; using namespace js::mjit; -#if ENABLE_PIC +#if defined JS_POLYIC /* Rough over-estimate of how much memory we need to unprotect. */ static const uint32 INLINE_PATH_LENGTH = 64; /* Maximum number of stubs for a given callsite. */ static const uint32 MAX_STUBS = 16; typedef JSC::FunctionPtr FunctionPtr; @@ -1590,10 +1590,11 @@ ic::PurgePICs(JSContext *cx, JSScript *s break; default: GetPropCompiler::reset(pic); break; } pic.reset(); } } -#endif +#endif /* JS_POLYIC */ +
--- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -32,29 +32,27 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT +#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT && defined JS_POLYIC #define jsjaeger_poly_ic_h__ #include "jscntxt.h" #include "jstl.h" #include "jsvector.h" #include "assembler/assembler/MacroAssembler.h" #include "assembler/assembler/CodeLocation.h" #include "methodjit/MethodJIT.h" #include "RematInfo.h" -#define ENABLE_PIC 1 - namespace js { namespace mjit { namespace ic { static const uint32 MAX_PIC_STUBS = 16; void PurgePICs(JSContext *cx);