/* * 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); StackFrame *firstCtorFrame = NULL; StackFrame *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. StackFrame *end = f->entryfp->prev(); for (StackFrame *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; }