summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/ftl/FTLLink.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/ftl/FTLLink.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLLink.cpp')
-rw-r--r--Source/JavaScriptCore/ftl/FTLLink.cpp209
1 files changed, 97 insertions, 112 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLLink.cpp b/Source/JavaScriptCore/ftl/FTLLink.cpp
index 5b2bb67c7..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
@@ -29,145 +29,129 @@
#if ENABLE(FTL_JIT)
#include "CCallHelpers.h"
+#include "CallFrameInlines.h"
#include "CodeBlockWithJITType.h"
#include "DFGCommon.h"
#include "FTLJITCode.h"
#include "JITOperations.h"
+#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;
- // B3 will create its own jump tables as needed.
+ // LLVM will create its own jump tables as needed.
codeBlock->clearSwitchJumpTables();
-
- state.jitCode->common.requiredRegisterCountForExit = graph.requiredRegisterCountForExit();
- if (!graph.m_plan.inlineCallFrames->isEmpty())
- state.jitCode->common.inlineCallFrames = graph.m_plan.inlineCallFrames;
+ state.jitCode->common.frameRegisterCount = state.graph.frameRegisterCount();
+ state.jitCode->common.requiredRegisterCountForExit = state.graph.requiredRegisterCountForExit();
+
+ 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.ensureDominators();
- graph.ensureNaturalLoops();
+ CCallHelpers::Label fromArityCheck = jit.label();
- const char* prefix = " ";
+ // 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 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;
- }
- }
+ 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();
- dumpContext.dump(out, prefix);
- compilation->addDescription(Profiler::OriginStack(), out.toCString());
- out.reset();
-
- out.print(" Disassembly:\n");
- out.print(" <not implemented yet>\n");
- 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(CallSiteIndex(0).bits()),
- CCallHelpers::tagFor(JSStack::ArgumentCount));
- jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame);
+ CCallHelpers::TrustedImm32(CallFrame::Location::encodeAsBytecodeOffset(0)),
+ 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::argumentGPR0);
- jit.emitFunctionEpilogue();
- mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0));
- jit.emitFunctionPrologue();
+ 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;
}
@@ -175,19 +159,19 @@ void link(State& state)
// We jump to here straight from DFG code, after having boxed up all of the
// 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 B3-generated code.
- CCallHelpers::Label start = jit.label();
- jit.emitFunctionEpilogue();
- CCallHelpers::Jump mainPathJump = jit.jump();
+ // call to the LLVM-generated code.
+ 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;
}
@@ -196,8 +180,9 @@ void link(State& state)
break;
}
- state.finalizer->entrypointLinkBuffer = WTFMove(linkBuffer);
+ state.finalizer->entrypointLinkBuffer = linkBuffer.release();
state.finalizer->function = state.generatedFunction;
+ state.finalizer->arityCheck = arityCheck;
state.finalizer->jitCode = state.jitCode;
}