void JS_FASTCALL stubs::ScriptDebugPrologue(VMFrame &f) { Probes::enterJSFun(f.cx, f.fp()->maybeFun(), f.fp()->script()); JSTrapStatus status = js::ScriptDebugPrologue(f.cx, f.fp()); switch (status) { case JSTRAP_CONTINUE: break; case JSTRAP_RETURN: *f.returnAddressLocation() = f.cx->jaegerRuntime().forceReturnFromFastCall(); return; case JSTRAP_ERROR: case JSTRAP_THROW: THROW(); default: JS_NOT_REACHED("bad ScriptDebugPrologue status"); } }
void JS_FASTCALL stubs::CrossChunkShim(VMFrame &f, void *edge_) { DebugOnly<CrossChunkEdge*> edge = (CrossChunkEdge *) edge_; mjit::ExpandInlineFrames(f.cx->compartment); JSScript *script = f.script(); JS_ASSERT(edge->target < script->length); JS_ASSERT(script->code + edge->target == f.pc()); CompileStatus status = CanMethodJIT(f.cx, script, f.pc(), f.fp()->isConstructing(), CompileRequest_Interpreter); if (status == Compile_Error) THROW(); void **addr = f.returnAddressLocation(); *addr = JS_FUNC_TO_DATA_PTR(void *, JaegerInterpoline); f.fp()->setRejoin(StubRejoin(REJOIN_RESUME)); }
/* * The strategy for this goes as follows: * * 1) Scan the stack, looking at all return addresses that could go into JIT * code. * 2) If an address corresponds to a call site registered by |callSite| during * the last compilation, remember it. * 3) Purge the old compiled state and return if there were no active frames of * this script on the stack. * 4) Fix up the stack by replacing all saved addresses with the addresses the * new compiler gives us for the call sites. */ bool Recompiler::recompile() { JS_ASSERT(script->hasJITCode()); Vector<PatchableAddress> normalPatches(cx); Vector<PatchableAddress> ctorPatches(cx); JSStackFrame *firstCtorFrame = NULL; JSStackFrame *firstNormalFrame = NULL; // Find all JIT'd stack frames to account for return addresses that will // need to be patched after recompilation. for (VMFrame *f = script->compartment->jaegerCompartment->activeFrame(); f != NULL; f = f->previous) { // Scan all frames owned by this VMFrame. JSStackFrame *end = f->entryfp->prev(); for (JSStackFrame *fp = f->fp(); fp != end; fp = fp->prev()) { // Remember the latest frame for each type of JIT'd code, so the // compiler will have a frame to re-JIT from. if (!firstCtorFrame && fp->script() == script && fp->isConstructing()) firstCtorFrame = fp; else if (!firstNormalFrame && fp->script() == script && !fp->isConstructing()) firstNormalFrame = fp; void **addr = fp->addressOfNativeReturnAddress(); if (script->jitCtor && script->jitCtor->isValidCode(*addr)) { if (!ctorPatches.append(findPatch(script->jitCtor, addr))) return false; } else if (script->jitNormal && script->jitNormal->isValidCode(*addr)) { if (!normalPatches.append(findPatch(script->jitNormal, addr))) return false; } } void **addr = f->returnAddressLocation(); if (script->jitCtor && script->jitCtor->isValidCode(*addr)) { if (!ctorPatches.append(findPatch(script->jitCtor, addr))) return false; } else if (script->jitNormal && script->jitNormal->isValidCode(*addr)) { if (!normalPatches.append(findPatch(script->jitNormal, addr))) return false; } } Vector<CallSite> normalSites(cx); Vector<CallSite> ctorSites(cx); if (script->jitNormal && !saveTraps(script->jitNormal, &normalSites)) return false; if (script->jitCtor && !saveTraps(script->jitCtor, &ctorSites)) return false; ReleaseScriptCode(cx, script); if (normalPatches.length() && !recompile(firstNormalFrame, normalPatches, normalSites)) { return false; } if (ctorPatches.length() && !recompile(firstCtorFrame, ctorPatches, ctorSites)) { return false; } return true; }