diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/ftl/FTLLink.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLLink.cpp')
-rw-r--r-- | Source/JavaScriptCore/ftl/FTLLink.cpp | 216 |
1 files changed, 91 insertions, 125 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLLink.cpp b/Source/JavaScriptCore/ftl/FTLLink.cpp index 188afe5f0..85050d151 100644 --- a/Source/JavaScriptCore/ftl/FTLLink.cpp +++ b/Source/JavaScriptCore/ftl/FTLLink.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013 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,8 +28,8 @@ #if ENABLE(FTL_JIT) -#include "ArityCheckFailReturnThunks.h" #include "CCallHelpers.h" +#include "CallFrameInlines.h" #include "CodeBlockWithJITType.h" #include "DFGCommon.h" #include "FTLJITCode.h" @@ -37,156 +37,121 @@ #include "JITStubs.h" #include "LLVMAPI.h" #include "LinkBuffer.h" -#include "JSCInlines.h" -#include "ProfilerCompilation.h" #include "VirtualRegister.h" namespace JSC { namespace FTL { using namespace DFG; +static void compileEntry(CCallHelpers& jit) +{ + jit.preserveReturnAddressAfterCall(GPRInfo::regT2); + jit.emitPutReturnPCToCallFrameHeader(GPRInfo::regT2); + jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock); +} + void link(State& state) { - Graph& graph = state.graph; - CodeBlock* codeBlock = graph.m_codeBlock; - VM& vm = graph.m_vm; + CodeBlock* codeBlock = state.graph.m_codeBlock; // LLVM will create its own jump tables as needed. codeBlock->clearSwitchJumpTables(); - // FIXME: Need to know the real frame register count. - // https://bugs.webkit.org/show_bug.cgi?id=125727 - state.jitCode->common.frameRegisterCount = 1000; - - state.jitCode->common.requiredRegisterCountForExit = graph.requiredRegisterCountForExit(); + state.jitCode->common.frameRegisterCount = state.graph.frameRegisterCount(); + state.jitCode->common.requiredRegisterCountForExit = state.graph.requiredRegisterCountForExit(); - if (!graph.m_plan.inlineCallFrames->isEmpty()) - state.jitCode->common.inlineCallFrames = graph.m_plan.inlineCallFrames; + if (!state.graph.m_inlineCallFrames->isEmpty()) + state.jitCode->common.inlineCallFrames = std::move(state.graph.m_inlineCallFrames); - graph.registerFrozenValues(); - // Create the entrypoint. Note that we use this entrypoint totally differently // depending on whether we're doing OSR entry or not. - CCallHelpers jit(&vm, codeBlock); + // FIXME: Except for OSR entry, this is a total kludge - LLVM should just use our + // calling convention. + // https://bugs.webkit.org/show_bug.cgi?id=113621 + CCallHelpers jit(&state.graph.m_vm, codeBlock); - std::unique_ptr<LinkBuffer> linkBuffer; - - CCallHelpers::Address frame = CCallHelpers::Address( - CCallHelpers::stackPointerRegister, -static_cast<int32_t>(AssemblyHelpers::prologueStackPointerDelta())); + OwnPtr<LinkBuffer> linkBuffer; + CCallHelpers::Label arityCheck; + switch (state.graph.m_plan.mode) { + case FTLMode: { + compileEntry(jit); - if (Profiler::Compilation* compilation = graph.compilation()) { - compilation->addDescription( - Profiler::OriginStack(), - toCString("Generated FTL JIT code for ", CodeBlockWithJITType(codeBlock, JITCode::FTLJIT), ", instruction count = ", graph.m_codeBlock->instructionCount(), ":\n")); + // This part is only necessary for functions. We currently only compile functions. - graph.m_dominators.computeIfNecessary(graph); - graph.m_naturalLoops.computeIfNecessary(graph); + CCallHelpers::Label fromArityCheck = jit.label(); - const char* prefix = " "; - - DumpContext dumpContext; - StringPrintStream out; - Node* lastNode = 0; - for (size_t blockIndex = 0; blockIndex < graph.numBlocks(); ++blockIndex) { - BasicBlock* block = graph.block(blockIndex); - if (!block) - continue; - - graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &dumpContext); - compilation->addDescription(Profiler::OriginStack(), out.toCString()); - out.reset(); - - for (size_t nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { - Node* node = block->at(nodeIndex); - - Profiler::OriginStack stack; - - if (node->origin.semantic.isSet()) { - stack = Profiler::OriginStack( - *vm.m_perBytecodeProfiler, codeBlock, node->origin.semantic); - } - - if (graph.dumpCodeOrigin(out, prefix, lastNode, node, &dumpContext)) { - compilation->addDescription(stack, out.toCString()); - out.reset(); - } - - graph.dump(out, prefix, node, &dumpContext); - compilation->addDescription(stack, out.toCString()); - out.reset(); - - if (node->origin.semantic.isSet()) - lastNode = node; - } - } + // Plant a check that sufficient space is available in the JSStack. + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 + jit.addPtr( + CCallHelpers::TrustedImm32(virtualRegisterForLocal(state.jitCode->common.requiredRegisterCountForExit).offset() * sizeof(Register)), + GPRInfo::callFrameRegister, GPRInfo::regT1); + CCallHelpers::Jump stackCheck = jit.branchPtr( + CCallHelpers::Above, + CCallHelpers::AbsoluteAddress(state.graph.m_vm.addressOfJSStackLimit()), + GPRInfo::regT1); + CCallHelpers::Label fromStackCheck = jit.label(); - dumpContext.dump(out, prefix); - compilation->addDescription(Profiler::OriginStack(), out.toCString()); - out.reset(); + jit.setupArgumentsExecState(); + jit.move( + CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)), + GPRInfo::nonArgGPR0); + jit.call(GPRInfo::nonArgGPR0); + jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT1); + jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister); + jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1); + jit.ret(); - out.print(" Disassembly:\n"); - for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) { - if (state.codeSectionNames[i] != SECTION_NAME("text")) - continue; - - ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get(); - disassemble( - MacroAssemblerCodePtr(handle->start()), handle->sizeInBytes(), - " ", out, LLVMSubset); - } - compilation->addDescription(Profiler::OriginStack(), out.toCString()); - out.reset(); + stackCheck.link(&jit); + jit.move(CCallHelpers::TrustedImmPtr(codeBlock), GPRInfo::argumentGPR1); + jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + jit.store32( + CCallHelpers::TrustedImm32(CallFrame::Location::encodeAsBytecodeOffset(0)), + CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount))); + jit.storePtr(GPRInfo::callFrameRegister, &state.graph.m_vm.topCallFrame); + CCallHelpers::Call callStackCheck = jit.call(); +#if !ASSERT_DISABLED + // FIXME: need to make this call register with exception handling somehow. This is + // part of a bigger problem: FTL should be able to handle exceptions. + // https://bugs.webkit.org/show_bug.cgi?id=113622 + // Until then, use a JIT ASSERT. + jit.load64(state.graph.m_vm.addressOfException(), GPRInfo::regT0); + jit.jitAssertIsNull(GPRInfo::regT0); +#endif + jit.jump(fromStackCheck); - state.jitCode->common.compilation = compilation; - } - - switch (graph.m_plan.mode) { - case FTLMode: { - CCallHelpers::JumpList mainPathJumps; - + arityCheck = jit.label(); + compileEntry(jit); jit.load32( - frame.withOffset(sizeof(Register) * JSStack::ArgumentCount), + CCallHelpers::payloadFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)), GPRInfo::regT1); - mainPathJumps.append(jit.branch32( + jit.branch32( CCallHelpers::AboveOrEqual, GPRInfo::regT1, - CCallHelpers::TrustedImm32(codeBlock->numParameters()))); - jit.emitFunctionPrologue(); + CCallHelpers::TrustedImm32(codeBlock->numParameters())) + .linkTo(fromArityCheck, &jit); jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); jit.store32( CCallHelpers::TrustedImm32(CallFrame::Location::encodeAsBytecodeOffset(0)), - CCallHelpers::tagFor(JSStack::ArgumentCount)); - jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); + CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount))); + jit.storePtr(GPRInfo::callFrameRegister, &state.graph.m_vm.topCallFrame); CCallHelpers::Call callArityCheck = jit.call(); #if !ASSERT_DISABLED // FIXME: need to make this call register with exception handling somehow. This is // part of a bigger problem: FTL should be able to handle exceptions. // https://bugs.webkit.org/show_bug.cgi?id=113622 // Until then, use a JIT ASSERT. - jit.load64(vm.addressOfException(), GPRInfo::regT1); + jit.load64(state.graph.m_vm.addressOfException(), GPRInfo::regT1); jit.jitAssertIsNull(GPRInfo::regT1); #endif - jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); - jit.emitFunctionEpilogue(); - mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0)); - jit.emitFunctionPrologue(); - CodeLocationLabel* arityThunkLabels = - vm.arityCheckFailReturnThunks->returnPCsFor(vm, codeBlock->numParameters()); - jit.move(CCallHelpers::TrustedImmPtr(arityThunkLabels), GPRInfo::regT7); - jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::regT7, GPRInfo::regT0, CCallHelpers::timesPtr()), GPRInfo::regT7); + if (GPRInfo::returnValueGPR != GPRInfo::regT0) + jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); + jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0).linkTo(fromArityCheck, &jit); CCallHelpers::Call callArityFixup = jit.call(); - jit.emitFunctionEpilogue(); - mainPathJumps.append(jit.jump()); - - linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationCanFail); - if (linkBuffer->didFailToAllocate()) { - state.allocationFailed = true; - return; - } + jit.jump(fromArityCheck); + + linkBuffer = adoptPtr(new LinkBuffer(state.graph.m_vm, &jit, codeBlock, JITCompilationMustSucceed)); + linkBuffer->link(callStackCheck, operationStackCheck); linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck); - linkBuffer->link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress())); - linkBuffer->link(mainPathJumps, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); - - state.jitCode->initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast<void*>(state.generatedFunction))); + linkBuffer->link(callArityFixup, FunctionPtr((state.graph.m_vm.getCTIStub(arityFixup)).code().executableAddress())); break; } @@ -195,18 +160,18 @@ void link(State& state) // values into the scratch buffer. Everything should be good to go - at this // point we've even done the stack check. Basically we just have to make the // call to the LLVM-generated code. - CCallHelpers::Label start = jit.label(); - jit.emitFunctionEpilogue(); - CCallHelpers::Jump mainPathJump = jit.jump(); + jit.setupArgumentsExecState(); + jit.move( + CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)), + GPRInfo::nonArgGPR0); + jit.call(GPRInfo::nonArgGPR0); + jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT1); + jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister); + jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1); + jit.ret(); - linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationCanFail); - if (linkBuffer->didFailToAllocate()) { - state.allocationFailed = true; - return; - } - linkBuffer->link(mainPathJump, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); - - state.jitCode->initializeAddressForCall(linkBuffer->locationOf(start)); + linkBuffer = adoptPtr(new LinkBuffer( + state.graph.m_vm, &jit, codeBlock, JITCompilationMustSucceed)); break; } @@ -215,8 +180,9 @@ void link(State& state) break; } - state.finalizer->entrypointLinkBuffer = WTF::move(linkBuffer); + state.finalizer->entrypointLinkBuffer = linkBuffer.release(); state.finalizer->function = state.generatedFunction; + state.finalizer->arityCheck = arityCheck; state.finalizer->jitCode = state.jitCode; } |