diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp | 276 |
1 files changed, 207 insertions, 69 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp index 9f84a2968..c63f53f60 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,16 +28,21 @@ #if ENABLE(DFG_JIT) -#include "Arguments.h" +#include "DFGJITCode.h" #include "DFGOperations.h" +#include "JIT.h" #include "JSCJSValueInlines.h" -#include "Operations.h" +#include "JSCInlines.h" +#include "StructureStubInfo.h" namespace JSC { namespace DFG { void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit) { jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); + + if (!exitKindMayJettison(exit.m_kind)) + return; jit.move(AssemblyHelpers::TrustedImmPtr(jit.codeBlock()), GPRInfo::regT0); @@ -52,20 +57,55 @@ void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit) AssemblyHelpers::GreaterThanOrEqual, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()), AssemblyHelpers::TrustedImm32(0)); + + // We want to figure out if there's a possibility that we're in a loop. For the outermost + // code block in the inline stack, we handle this appropriately by having the loop OSR trigger + // check the exit count of the replacement of the CodeBlock from which we are OSRing. The + // problem is the inlined functions, which might also have loops, but whose baseline versions + // don't know where to look for the exit count. Figure out if those loops are severe enough + // that we had tried to OSR enter. If so, then we should use the loop reoptimization trigger. + // Otherwise, we should use the normal reoptimization trigger. + + AssemblyHelpers::JumpList loopThreshold; + + for (InlineCallFrame* inlineCallFrame = exit.m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) { + loopThreshold.append( + jit.branchTest8( + AssemblyHelpers::NonZero, + AssemblyHelpers::AbsoluteAddress( + inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->addressOfDidTryToEnterInLoop()))); + } + + jit.move( + AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization()), + GPRInfo::regT1); + + if (!loopThreshold.empty()) { + AssemblyHelpers::Jump done = jit.jump(); + + loopThreshold.link(&jit); + jit.move( + AssemblyHelpers::TrustedImm32( + jit.codeBlock()->exitCountThresholdForReoptimizationFromLoop()), + GPRInfo::regT1); - tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization())); + done.link(&jit); + } + + tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); reoptimizeNow.link(&jit); // Reoptimize as soon as possible. #if !NUMBER_OF_ARGUMENT_REGISTERS jit.poke(GPRInfo::regT0); + jit.poke(AssemblyHelpers::TrustedImmPtr(&exit), 1); #else jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0); - ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1); + jit.move(AssemblyHelpers::TrustedImmPtr(&exit), GPRInfo::argumentGPR1); #endif - jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::regT1); - jit.call(GPRInfo::regT1); + jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::nonArgGPR0); + jit.call(GPRInfo::nonArgGPR0); AssemblyHelpers::Jump doneAdjusting = jit.jump(); tooFewFails.link(&jit); @@ -74,105 +114,203 @@ void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit) int32_t activeThreshold = jit.baselineCodeBlock()->adjustedCounterValue( Options::thresholdForOptimizeAfterLongWarmUp()); - int32_t targetValue = ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( + int32_t targetValue = applyMemoryUsageHeuristicsAndConvertToInt( activeThreshold, jit.baselineCodeBlock()); - int32_t clippedValue = - ExecutionCounter::clippedThreshold(jit.codeBlock()->globalObject(), targetValue); + int32_t clippedValue; + switch (jit.codeBlock()->jitType()) { + case JITCode::DFGJIT: + clippedValue = BaselineExecutionCounter::clippedThreshold(jit.codeBlock()->globalObject(), targetValue); + break; + case JITCode::FTLJIT: + clippedValue = UpperTierExecutionCounter::clippedThreshold(jit.codeBlock()->globalObject(), targetValue); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); +#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE) + clippedValue = 0; // Make some compilers, and mhahnenberg, happy. +#endif + break; + } jit.store32(AssemblyHelpers::TrustedImm32(-clippedValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); jit.store32(AssemblyHelpers::TrustedImm32(activeThreshold), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); - jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(clippedValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); + jit.store32(AssemblyHelpers::TrustedImm32(formattedTotalExecutionCount(clippedValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); doneAdjusting.link(&jit); } void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit) { + // FIXME: We shouldn't leave holes on the stack when performing an OSR exit + // in presence of inlined tail calls. + // https://bugs.webkit.org/show_bug.cgi?id=147511 ASSERT(jit.baselineCodeBlock()->jitType() == JITCode::BaselineJIT); - jit.storePtr(AssemblyHelpers::TrustedImmPtr(jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)JSStack::CodeBlock)); - - CodeOrigin codeOrigin; - for (codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) { - InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; - CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(codeOrigin); - CodeBlock* baselineCodeBlockForCaller = jit.baselineCodeBlockFor(inlineCallFrame->caller); - unsigned callBytecodeIndex = inlineCallFrame->caller.bytecodeIndex; - CallLinkInfo& callLinkInfo = baselineCodeBlockForCaller->getCallLinkInfo(callBytecodeIndex); - - void* jumpTarget = callLinkInfo.callReturnLocation.executableAddress(); + jit.storePtr(AssemblyHelpers::TrustedImmPtr(jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)CallFrameSlot::codeBlock)); - GPRReg callerFrameGPR; - if (inlineCallFrame->caller.inlineCallFrame) { - jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3); + const CodeOrigin* codeOrigin; + for (codeOrigin = &exit.m_codeOrigin; codeOrigin && codeOrigin->inlineCallFrame; codeOrigin = codeOrigin->inlineCallFrame->getCallerSkippingTailCalls()) { + InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame; + CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(*codeOrigin); + InlineCallFrame::Kind trueCallerCallKind; + CodeOrigin* trueCaller = inlineCallFrame->getCallerSkippingTailCalls(&trueCallerCallKind); + GPRReg callerFrameGPR = GPRInfo::callFrameRegister; + + if (!trueCaller) { + ASSERT(inlineCallFrame->isTail()); + jit.loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT3); + jit.storePtr(GPRInfo::regT3, AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset())); + jit.loadPtr(AssemblyHelpers::Address(GPRInfo::callFrameRegister, CallFrame::callerFrameOffset()), GPRInfo::regT3); callerFrameGPR = GPRInfo::regT3; - } else - callerFrameGPR = GPRInfo::callFrameRegister; - + } else { + CodeBlock* baselineCodeBlockForCaller = jit.baselineCodeBlockFor(*trueCaller); + unsigned callBytecodeIndex = trueCaller->bytecodeIndex; + void* jumpTarget = nullptr; + + switch (trueCallerCallKind) { + case InlineCallFrame::Call: + case InlineCallFrame::Construct: + case InlineCallFrame::CallVarargs: + case InlineCallFrame::ConstructVarargs: + case InlineCallFrame::TailCall: + case InlineCallFrame::TailCallVarargs: { + CallLinkInfo* callLinkInfo = + baselineCodeBlockForCaller->getCallLinkInfoForBytecodeIndex(callBytecodeIndex); + RELEASE_ASSERT(callLinkInfo); + + jumpTarget = callLinkInfo->callReturnLocation().executableAddress(); + break; + } + + case InlineCallFrame::GetterCall: + case InlineCallFrame::SetterCall: { + StructureStubInfo* stubInfo = + baselineCodeBlockForCaller->findStubInfo(CodeOrigin(callBytecodeIndex)); + RELEASE_ASSERT(stubInfo); + + jumpTarget = stubInfo->doneLocation().executableAddress(); + break; + } + + default: + RELEASE_ASSERT_NOT_REACHED(); + } + + if (trueCaller->inlineCallFrame) { + jit.addPtr( + AssemblyHelpers::TrustedImm32(trueCaller->inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), + GPRInfo::callFrameRegister, + GPRInfo::regT3); + callerFrameGPR = GPRInfo::regT3; + } + + jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset())); + } + + jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::codeBlock))); + + // Restore the inline call frame's callee save registers. + // If this inlined frame is a tail call that will return back to the original caller, we need to + // copy the prior contents of the tag registers already saved for the outer frame to this frame. + jit.emitSaveOrCopyCalleeSavesFor( + baselineCodeBlock, + static_cast<VirtualRegister>(inlineCallFrame->stackOffset), + trueCaller ? AssemblyHelpers::UseExistingTagRegisterContents : AssemblyHelpers::CopyBaselineCalleeSavedRegistersFromBaseFrame, + GPRInfo::regT2); + + if (!inlineCallFrame->isVarargs()) + jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::argumentCount))); #if USE(JSVALUE64) - jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CodeBlock))); - if (!inlineCallFrame->isClosureCall) - jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame->calleeConstant()->scope()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain))); jit.store64(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame->callerFrameOffset())); - jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset())); - uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(codeOrigin.bytecodeIndex); - jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount))); - jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount))); + uint32_t locationBits = CallSiteIndex(codeOrigin->bytecodeIndex).bits(); + jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::argumentCount))); if (!inlineCallFrame->isClosureCall) - jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame->calleeConstant()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee))); - - // Leave the captured arguments in regT3. - if (baselineCodeBlock->usesArguments()) - jit.loadPtr(AssemblyHelpers::addressFor(VirtualRegister(inlineCallFrame->stackOffset + unmodifiedArgumentsRegister(baselineCodeBlock->argumentsRegister()).offset())), GPRInfo::regT3); + jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame->calleeConstant()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::callee))); #else // USE(JSVALUE64) // so this is the 32-bit part - jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CodeBlock))); - jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain))); - if (!inlineCallFrame->isClosureCall) - jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeConstant()->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain))); jit.storePtr(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame->callerFrameOffset())); - jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset())); - Instruction* instruction = baselineCodeBlock->instructions().begin() + codeOrigin.bytecodeIndex; - uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction); - jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount))); - jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount))); - jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee))); + Instruction* instruction = baselineCodeBlock->instructions().begin() + codeOrigin->bytecodeIndex; + uint32_t locationBits = CallSiteIndex(instruction).bits(); + jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::argumentCount))); + jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::callee))); if (!inlineCallFrame->isClosureCall) - jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeConstant()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee))); - - // Leave the captured arguments in regT3. - if (baselineCodeBlock->usesArguments()) - jit.loadPtr(AssemblyHelpers::payloadFor(VirtualRegister(inlineCallFrame->stackOffset + unmodifiedArgumentsRegister(baselineCodeBlock->argumentsRegister()).offset())), GPRInfo::regT3); + jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeConstant()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + CallFrameSlot::callee))); #endif // USE(JSVALUE64) // ending the #else part, so directly above is the 32-bit part - - if (baselineCodeBlock->usesArguments()) { - AssemblyHelpers::Jump noArguments = jit.branchTestPtr(AssemblyHelpers::Zero, GPRInfo::regT3); - jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT0); - jit.storePtr(GPRInfo::regT0, AssemblyHelpers::Address(GPRInfo::regT3, Arguments::offsetOfRegisters())); - noArguments.link(&jit); - } } + // Don't need to set the toplevel code origin if we only did inline tail calls + if (codeOrigin) { #if USE(JSVALUE64) - uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(codeOrigin.bytecodeIndex); + uint32_t locationBits = CallSiteIndex(codeOrigin->bytecodeIndex).bits(); #else - Instruction* instruction = jit.baselineCodeBlock()->instructions().begin() + codeOrigin.bytecodeIndex; - uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction); + Instruction* instruction = jit.baselineCodeBlock()->instructions().begin() + codeOrigin->bytecodeIndex; + uint32_t locationBits = CallSiteIndex(instruction).bits(); +#endif + jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(CallFrameSlot::argumentCount))); + } +} + +static void osrWriteBarrier(CCallHelpers& jit, GPRReg owner, GPRReg scratch) +{ + AssemblyHelpers::Jump ownerIsRememberedOrInEden = jit.barrierBranchWithoutFence(owner); + + // We need these extra slots because setupArgumentsWithExecState will use poke on x86. +#if CPU(X86) + jit.subPtr(MacroAssembler::TrustedImm32(sizeof(void*) * 3), MacroAssembler::stackPointerRegister); +#endif + + jit.setupArgumentsWithExecState(owner); + jit.move(MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(operationOSRWriteBarrier)), scratch); + jit.call(scratch); + +#if CPU(X86) + jit.addPtr(MacroAssembler::TrustedImm32(sizeof(void*) * 3), MacroAssembler::stackPointerRegister); #endif - jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(JSStack::ArgumentCount))); + + ownerIsRememberedOrInEden.link(&jit); } void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit) { + jit.memoryFence(); + + jit.move( + AssemblyHelpers::TrustedImmPtr( + jit.codeBlock()->baselineAlternative()), GPRInfo::argumentGPR1); + osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0); + + // We barrier all inlined frames -- and not just the current inline stack -- + // because we don't know which inlined function owns the value profile that + // we'll update when we exit. In the case of "f() { a(); b(); }", if both + // a and b are inlined, we might exit inside b due to a bad value loaded + // from a. + // FIXME: MethodOfGettingAValueProfile should remember which CodeBlock owns + // the value profile. + InlineCallFrameSet* inlineCallFrames = jit.codeBlock()->jitCode()->dfgCommon()->inlineCallFrames.get(); + if (inlineCallFrames) { + for (InlineCallFrame* inlineCallFrame : *inlineCallFrames) { + jit.move( + AssemblyHelpers::TrustedImmPtr( + inlineCallFrame->baselineCodeBlock.get()), GPRInfo::argumentGPR1); + osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0); + } + } + if (exit.m_codeOrigin.inlineCallFrame) jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister); - CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin); - Vector<BytecodeAndMachineOffset>& decodedCodeMap = jit.decodedCodeMapFor(baselineCodeBlock); + CodeBlock* codeBlockForExit = jit.baselineCodeBlockFor(exit.m_codeOrigin); + Vector<BytecodeAndMachineOffset>& decodedCodeMap = jit.decodedCodeMapFor(codeBlockForExit); BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned>(decodedCodeMap, decodedCodeMap.size(), exit.m_codeOrigin.bytecodeIndex, BytecodeAndMachineOffset::getBytecodeIndex); ASSERT(mapping); ASSERT(mapping->m_bytecodeIndex == exit.m_codeOrigin.bytecodeIndex); - void* jumpTarget = baselineCodeBlock->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset); + void* jumpTarget = codeBlockForExit->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset); + + jit.addPtr(AssemblyHelpers::TrustedImm32(JIT::stackPointerOffsetFor(codeBlockForExit) * sizeof(Register)), GPRInfo::callFrameRegister, AssemblyHelpers::stackPointerRegister); + if (exit.isExceptionHandler()) { + // Since we're jumping to op_catch, we need to set callFrameForCatch. + jit.storePtr(GPRInfo::callFrameRegister, jit.vm()->addressOfCallFrameForCatch()); + } jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget), GPRInfo::regT2); jit.jump(GPRInfo::regT2); |