diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
| commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
| tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp | |
| download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz | |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp')
| -rw-r--r-- | Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp new file mode 100644 index 000000000..23d51c68e --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2011-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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGOSRExitCompiler.h" + +#if ENABLE(DFG_JIT) + +#include "CallFrame.h" +#include "DFGCommon.h" +#include "DFGJITCode.h" +#include "DFGOSRExitPreparation.h" +#include "LinkBuffer.h" +#include "OperandsInlines.h" +#include "JSCInlines.h" +#include "RepatchBuffer.h" +#include <wtf/StringPrintStream.h> + +namespace JSC { namespace DFG { + +void OSRExitCompiler::emitRestoreArguments(const Operands<ValueRecovery>& operands) +{ + HashMap<MinifiedID, int> alreadyAllocatedArguments; // Maps phantom arguments node ID to operand. + for (size_t index = 0; index < operands.size(); ++index) { + const ValueRecovery& recovery = operands[index]; + int operand = operands.operandForIndex(index); + + if (recovery.technique() != DirectArgumentsThatWereNotCreated + && recovery.technique() != ClonedArgumentsThatWereNotCreated) + continue; + + MinifiedID id = recovery.nodeID(); + auto iter = alreadyAllocatedArguments.find(id); + if (iter != alreadyAllocatedArguments.end()) { + JSValueRegs regs = JSValueRegs::withTwoAvailableRegs(GPRInfo::regT0, GPRInfo::regT1); + m_jit.loadValue(CCallHelpers::addressFor(iter->value), regs); + m_jit.storeValue(regs, CCallHelpers::addressFor(operand)); + continue; + } + + InlineCallFrame* inlineCallFrame = + m_jit.codeBlock()->jitCode()->dfg()->minifiedDFG.at(id)->inlineCallFrame(); + + int stackOffset; + if (inlineCallFrame) + stackOffset = inlineCallFrame->stackOffset; + else + stackOffset = 0; + + if (!inlineCallFrame || inlineCallFrame->isClosureCall) { + m_jit.loadPtr( + AssemblyHelpers::addressFor(stackOffset + JSStack::Callee), + GPRInfo::regT0); + } else { + m_jit.move( + AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeRecovery.constant().asCell()), + GPRInfo::regT0); + } + + if (!inlineCallFrame || inlineCallFrame->isVarargs()) { + m_jit.load32( + AssemblyHelpers::payloadFor(stackOffset + JSStack::ArgumentCount), + GPRInfo::regT1); + } else { + m_jit.move( + AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), + GPRInfo::regT1); + } + + m_jit.setupArgumentsWithExecState( + AssemblyHelpers::TrustedImmPtr(inlineCallFrame), GPRInfo::regT0, GPRInfo::regT1); + switch (recovery.technique()) { + case DirectArgumentsThatWereNotCreated: + m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(operationCreateDirectArgumentsDuringExit)), GPRInfo::nonArgGPR0); + break; + case ClonedArgumentsThatWereNotCreated: + m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(operationCreateClonedArgumentsDuringExit)), GPRInfo::nonArgGPR0); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); + break; + } + m_jit.call(GPRInfo::nonArgGPR0); + m_jit.storeCell(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(operand)); + + alreadyAllocatedArguments.add(id, operand); + } +} + +extern "C" { + +void compileOSRExit(ExecState* exec) +{ + SamplingRegion samplingRegion("DFG OSR Exit Compilation"); + + CodeBlock* codeBlock = exec->codeBlock(); + + ASSERT(codeBlock); + ASSERT(codeBlock->jitType() == JITCode::DFGJIT); + + VM* vm = &exec->vm(); + + // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't + // really be profitable. + DeferGCForAWhile deferGC(vm->heap); + + uint32_t exitIndex = vm->osrExitIndex; + OSRExit& exit = codeBlock->jitCode()->dfg()->osrExit[exitIndex]; + + prepareCodeOriginForOSRExit(exec, exit.m_codeOrigin); + + // Compute the value recoveries. + Operands<ValueRecovery> operands; + codeBlock->jitCode()->dfg()->variableEventStream.reconstruct(codeBlock, exit.m_codeOrigin, codeBlock->jitCode()->dfg()->minifiedDFG, exit.m_streamIndex, operands); + + SpeculationRecovery* recovery = 0; + if (exit.m_recoveryIndex != UINT_MAX) + recovery = &codeBlock->jitCode()->dfg()->speculationRecovery[exit.m_recoveryIndex]; + + { + CCallHelpers jit(vm, codeBlock); + OSRExitCompiler exitCompiler(jit); + + jit.jitAssertHasValidCallFrame(); + + if (vm->m_perBytecodeProfiler && codeBlock->jitCode()->dfgCommon()->compilation) { + Profiler::Database& database = *vm->m_perBytecodeProfiler; + Profiler::Compilation* compilation = codeBlock->jitCode()->dfgCommon()->compilation.get(); + + Profiler::OSRExit* profilerExit = compilation->addOSRExit( + exitIndex, Profiler::OriginStack(database, codeBlock, exit.m_codeOrigin), + exit.m_kind, exit.m_kind == UncountableInvalidation); + jit.add64(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(profilerExit->counterAddress())); + } + + exitCompiler.compileExit(exit, operands, recovery); + + LinkBuffer patchBuffer(*vm, jit, codeBlock); + exit.m_code = FINALIZE_CODE_IF( + shouldShowDisassembly() || Options::verboseOSR(), + patchBuffer, + ("DFG OSR exit #%u (%s, %s) from %s, with operands = %s", + exitIndex, toCString(exit.m_codeOrigin).data(), + exitKindToString(exit.m_kind), toCString(*codeBlock).data(), + toCString(ignoringContext<DumpContext>(operands)).data())); + } + + { + RepatchBuffer repatchBuffer(codeBlock); + repatchBuffer.relink(exit.codeLocationForRepatch(codeBlock), CodeLocationLabel(exit.m_code.code())); + } + + vm->osrExitJumpDestination = exit.m_code.code().executableAddress(); +} + +} // extern "C" + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) |
