Commit 634a76a2 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime...

fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime are not being called during compilation
https://bugs.webkit.org/show_bug.cgi?id=115297

Source/JavaScriptCore:

Reviewed by Geoffrey Garen.

Put in assertions that we're not doing bad things in compilation threads. Also
factored compilation into compile+link so that even though we don't yet have
concurrent compilation, we can be explicit about which parts of DFG work are
meant to be concurrent, and which aren't.

Also fix a handful of bugs found by these assertions.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/ResolveGlobalStatus.cpp:
(JSC::computeForStructure):
* bytecode/Watchpoint.cpp:
(JSC::WatchpointSet::add):
(JSC::InlineWatchpointSet::inflateSlow):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::~JITCompiler):
(DFG):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::linkFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.h:
(FTL):
* ftl/FTLLink.cpp: Added.
(FTL):
(JSC::FTL::compileEntry):
(JSC::FTL::link):
* ftl/FTLLink.h: Added.
(FTL):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
(FTL):
(State):
* runtime/Structure.cpp:
(JSC::Structure::get):
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:
(JSC::Structure::materializePropertyMapIfNecessary):
* runtime/StructureInlines.h:
(JSC::Structure::get):

Source/WTF:

Reviewed by Geoffrey Garen.

Taught WTF the notion of compilation threads. This allows all parts of our stack
to assert that we're not being called from a JSC compilation thread. This is in
WTF because it will probably end up being used in StringImpl and WTFString.

* WTF.xcodeproj/project.pbxproj:
* wtf/CompilationThread.cpp: Added.
(WTF):
(WTF::initializeCompilationThreadsOnce):
(WTF::initializeCompilationThreads):
(WTF::isCompilationThread):
(WTF::exchangeIsCompilationThread):
* wtf/CompilationThread.h: Added.
(WTF):
(CompilationScope):
(WTF::CompilationScope::CompilationScope):
(WTF::CompilationScope::~CompilationScope):
(WTF::CompilationScope::leaveEarly):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153134 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 32295c1a
2013-07-16 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r149301
2013-04-28 Filip Pizlo <fpizlo@apple.com>
fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime are not being called during compilation
https://bugs.webkit.org/show_bug.cgi?id=115297
Reviewed by Geoffrey Garen.
Put in assertions that we're not doing bad things in compilation threads. Also
factored compilation into compile+link so that even though we don't yet have
concurrent compilation, we can be explicit about which parts of DFG work are
meant to be concurrent, and which aren't.
Also fix a handful of bugs found by these assertions.
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/ResolveGlobalStatus.cpp:
(JSC::computeForStructure):
* bytecode/Watchpoint.cpp:
(JSC::WatchpointSet::add):
(JSC::InlineWatchpointSet::inflateSlow):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::~JITCompiler):
(DFG):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::linkFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.h:
(FTL):
* ftl/FTLLink.cpp: Added.
(FTL):
(JSC::FTL::compileEntry):
(JSC::FTL::link):
* ftl/FTLLink.h: Added.
(FTL):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
(FTL):
(State):
* runtime/Structure.cpp:
(JSC::Structure::get):
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:
(JSC::Structure::materializePropertyMapIfNecessary):
* runtime/StructureInlines.h:
(JSC::Structure::get):
2013-04-27 Filip Pizlo <fpizlo@apple.com>
FTL should support double variables
......
......@@ -218,6 +218,8 @@
0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F8364B7164B0C110053329A /* DFGBranchDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */; };
0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B94172E049E007DBDA5 /* FTLLink.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F943A1667631100D61971 /* CodeSpecializationKind.cpp */; };
0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F943D1667632D00D61971 /* CodeBlockHash.cpp */; };
0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F943E1667632D00D61971 /* CodeBlockHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1192,6 +1194,8 @@
0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };
0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; };
0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariadicFunction.h; path = dfg/DFGVariadicFunction.h; sourceTree = "<group>"; };
0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLink.cpp; path = ftl/FTLLink.cpp; sourceTree = "<group>"; };
0F8F2B94172E049E007DBDA5 /* FTLLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLLink.h; path = ftl/FTLLink.h; sourceTree = "<group>"; };
0F8F943A1667631100D61971 /* CodeSpecializationKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeSpecializationKind.cpp; sourceTree = "<group>"; };
0F8F943D1667632D00D61971 /* CodeBlockHash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockHash.cpp; sourceTree = "<group>"; };
0F8F943E1667632D00D61971 /* CodeBlockHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockHash.h; sourceTree = "<group>"; };
......@@ -2136,6 +2140,8 @@
0FEA0A221709606900BB722C /* FTLIntrinsicRepository.h */,
0FEA0A02170513DB00BB722C /* FTLJITCode.cpp */,
0FEA0A03170513DB00BB722C /* FTLJITCode.h */,
0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */,
0F8F2B94172E049E007DBDA5 /* FTLLink.h */,
0FEA0A131706363600BB722C /* FTLLLVMHeaders.h */,
0FEA0A04170513DB00BB722C /* FTLLowerDFGToLLVM.cpp */,
0FEA0A05170513DB00BB722C /* FTLLowerDFGToLLVM.h */,
......@@ -3444,6 +3450,7 @@
BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */,
BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */,
0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */,
A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */,
BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
......@@ -4306,6 +4313,7 @@
14469DE7107EC7E700650446 /* PropertyNameArray.cpp in Sources */,
14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
......
......@@ -37,7 +37,7 @@ static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure*
{
unsigned attributesIgnored;
JSCell* specificValue;
PropertyOffset offset = structure->get(*codeBlock->vm(), identifier, attributesIgnored, specificValue);
PropertyOffset offset = structure->getConcurrently(*codeBlock->vm(), identifier, attributesIgnored, specificValue);
if (structure->isDictionary())
specificValue = 0;
if (!isValidOffset(offset))
......
......@@ -27,6 +27,7 @@
#include "Watchpoint.h"
#include "LinkBuffer.h"
#include <wtf/CompilationThread.h>
#include <wtf/PassRefPtr.h>
namespace JSC {
......@@ -53,6 +54,7 @@ WatchpointSet::~WatchpointSet()
void WatchpointSet::add(Watchpoint* watchpoint)
{
ASSERT(!isCompilationThread());
if (!watchpoint)
return;
m_set.push(watchpoint);
......@@ -83,6 +85,7 @@ void InlineWatchpointSet::add(Watchpoint* watchpoint)
WatchpointSet* InlineWatchpointSet::inflateSlow()
{
ASSERT(isThin());
ASSERT(!isCompilationThread());
WatchpointSet* fat = adoptRef(new WatchpointSet(InitializedBlind)).leakRef();
if (m_data & IsInvalidatedFlag)
fat->m_isInvalidated = true;
......
......@@ -51,10 +51,12 @@
#include "DFGVirtualRegisterAllocationPhase.h"
#include "FTLCapabilities.h"
#include "FTLCompile.h"
#include "FTLLink.h"
#include "FTLLowerDFGToLLVM.h"
#include "FTLState.h"
#include "Operations.h"
#include "Options.h"
#include <wtf/CompilationThread.h>
namespace JSC { namespace DFG {
......@@ -81,6 +83,7 @@ enum CompileMode { CompileFunction, CompileOther };
static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
CompilationScope compilationScope;
numCompilations++;
......@@ -174,7 +177,9 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
FTL::State state(dfg);
FTL::lowerDFGToLLVM(state);
return FTL::compile(state, jitCode, *jitCodeWithArityCheck);
FTL::compile(state);
compilationScope.leaveEarly();
return FTL::link(state, jitCode, *jitCodeWithArityCheck);
}
#endif // ENABLE(FTL_JIT)
......@@ -186,12 +191,18 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
if (compileMode == CompileFunction) {
ASSERT(jitCodeWithArityCheck);
result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck);
if (!dataFlowJIT.compileFunction())
return false;
compilationScope.leaveEarly();
result = dataFlowJIT.linkFunction(jitCode, *jitCodeWithArityCheck);
} else {
ASSERT(compileMode == CompileOther);
ASSERT(!jitCodeWithArityCheck);
result = dataFlowJIT.compile(jitCode);
if (!dataFlowJIT.compile())
return false;
compilationScope.leaveEarly();
result = dataFlowJIT.link(jitCode);
}
return result;
......
......@@ -52,6 +52,10 @@ JITCompiler::JITCompiler(Graph& dfg)
m_disassembler = adoptPtr(new Disassembler(dfg));
}
JITCompiler::~JITCompiler()
{
}
void JITCompiler::linkOSRExits()
{
ASSERT(m_jitCode->osrExit.size() == m_exitCompilationInfo.size());
......@@ -97,7 +101,7 @@ void JITCompiler::compileEntry()
emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
}
void JITCompiler::compileBody(SpeculativeJIT& speculative)
void JITCompiler::compileBody()
{
// We generate the speculative code path, followed by OSR exit code to return
// to the old JIT code if speculations fail.
......@@ -107,7 +111,7 @@ void JITCompiler::compileBody(SpeculativeJIT& speculative)
breakpoint();
#endif
bool compiledSpeculative = speculative.compile();
bool compiledSpeculative = m_speculative->compile();
ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
}
......@@ -242,26 +246,31 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
m_graph.m_watchpoints.reallyAdd();
}
bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
bool JITCompiler::compile()
{
SamplingRegion samplingRegion("DFG Backend");
setStartOfCode();
compileEntry();
SpeculativeJIT speculative(*this);
compileBody(speculative);
m_speculative = adoptPtr(new SpeculativeJIT(*this));
compileBody();
setEndOfMainPath();
// Generate slow path code.
speculative.runSlowPathGenerators();
m_speculative->runSlowPathGenerators();
compileExceptionHandlers();
linkOSRExits();
// Create OSR entry trampolines if necessary.
speculative.createOSREntries();
m_speculative->createOSREntries();
setEndOfCode();
return true;
}
bool JITCompiler::link(RefPtr<JSC::JITCode>& entry)
{
if (!m_graph.m_watchpoints.areStillValid())
return false;
......@@ -269,7 +278,7 @@ bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
if (linkBuffer.didFailToAllocate())
return false;
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
m_speculative->linkOSREntries(linkBuffer);
m_jitCode->shrinkToFit();
codeBlock()->shrinkToFit(CodeBlock::LateShrink);
......@@ -284,7 +293,7 @@ bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
return true;
}
bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck)
bool JITCompiler::compileFunction()
{
SamplingRegion samplingRegion("DFG Backend");
......@@ -305,8 +314,8 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
// === Function body code generation ===
SpeculativeJIT speculative(*this);
compileBody(speculative);
m_speculative = adoptPtr(new SpeculativeJIT(*this));
compileBody();
setEndOfMainPath();
// === Function footer code generation ===
......@@ -323,8 +332,8 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
CallBeginToken token;
beginCall(CodeOrigin(0), token);
Call callStackCheck = call();
notifyCall(callStackCheck, CodeOrigin(0), token);
m_callStackCheck = call();
notifyCall(m_callStackCheck, CodeOrigin(0), token);
jump(fromStackCheck);
// The fast entry point into a function does not check the correct number of arguments
......@@ -332,7 +341,7 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
// determine the correct number of arguments have been passed, or have already checked).
// In cases where an arity check is necessary, we enter here.
// FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
Label arityCheck = label();
m_arityCheck = label();
compileEntry();
load32(AssemblyHelpers::payloadFor((VirtualRegister)JSStack::ArgumentCount), GPRInfo::regT1);
......@@ -340,21 +349,26 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
beginCall(CodeOrigin(0), token);
Call callArityCheck = call();
notifyCall(callArityCheck, CodeOrigin(0), token);
m_callArityCheck = call();
notifyCall(m_callArityCheck, CodeOrigin(0), token);
move(GPRInfo::regT0, GPRInfo::callFrameRegister);
jump(fromArityCheck);
// Generate slow path code.
speculative.runSlowPathGenerators();
m_speculative->runSlowPathGenerators();
compileExceptionHandlers();
linkOSRExits();
// Create OSR entry trampolines if necessary.
speculative.createOSREntries();
m_speculative->createOSREntries();
setEndOfCode();
return true;
}
bool JITCompiler::linkFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck)
{
if (!m_graph.m_watchpoints.areStillValid())
return false;
......@@ -363,21 +377,21 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
if (linkBuffer.didFailToAllocate())
return false;
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
m_speculative->linkOSREntries(linkBuffer);
m_jitCode->shrinkToFit();
codeBlock()->shrinkToFit(CodeBlock::LateShrink);
// FIXME: switch the stack check & arity check over to DFGOpertaion style calls, not JIT stubs.
linkBuffer.link(callStackCheck, cti_stack_check);
linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
linkBuffer.link(m_callStackCheck, cti_stack_check);
linkBuffer.link(m_callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
if (shouldShowDisassembly())
m_disassembler->dump(linkBuffer);
if (m_graph.m_compilation)
m_disassembler->reportToProfiler(m_graph.m_compilation.get(), linkBuffer);
entryWithArityCheck = linkBuffer.locationOf(arityCheck);
entryWithArityCheck = linkBuffer.locationOf(m_arityCheck);
m_jitCode->initializeCodeRef(linkBuffer.finalizeCodeWithoutDisassembly());
entry = m_jitCode;
return true;
......
......@@ -245,9 +245,13 @@ struct PropertyAccessRecord {
class JITCompiler : public CCallHelpers {
public:
JITCompiler(Graph& dfg);
~JITCompiler();
bool compile(RefPtr<JSC::JITCode>& entry);
bool compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck);
bool compile();
bool compileFunction();
bool link(RefPtr<JSC::JITCode>& entry);
bool linkFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck);
// Accessors for properties.
Graph& graph() { return m_graph; }
......@@ -435,7 +439,7 @@ private:
// Internal implementation to compile.
void compileEntry();
void compileBody(SpeculativeJIT&);
void compileBody();
void link(LinkBuffer&);
void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
......@@ -478,6 +482,11 @@ private:
Vector<OSRExitCompilationInfo> m_exitCompilationInfo;
Vector<Vector<Label> > m_exitSiteLabels;
unsigned m_currentCodeOriginIndex;
Call m_callStackCheck;
Call m_callArityCheck;
Label m_arityCheck;
OwnPtr<SpeculativeJIT> m_speculative;
};
} } // namespace JSC::DFG
......
......@@ -31,7 +31,6 @@
#include "CodeBlockWithJITType.h"
#include "DFGCCallHelpers.h"
#include "DFGCommon.h"
#include "FTLJITCode.h"
#include "FTLLLVMHeaders.h"
#include "JITStubs.h"
#include "LinkBuffer.h"
......@@ -40,18 +39,8 @@ namespace JSC { namespace FTL {
using namespace DFG;
typedef EncodedJSValue (*GeneratedFunction)(ExecState*);
static void compileEntry(CCallHelpers& jit)
{
jit.preserveReturnAddressAfterCall(GPRInfo::regT2);
jit.emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
}
bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
void compile(State& state)
{
LLVMExecutionEngineRef engine;
char* error = 0;
LLVMMCJITCompilerOptions options;
......@@ -60,13 +49,13 @@ bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
options.NoFramePointerElim = true;
options.CodeModel = LLVMCodeModelSmall;
if (LLVMCreateMCJITCompilerForModule(&engine, state.module, &options, sizeof(options), &error)) {
if (LLVMCreateMCJITCompilerForModule(&state.engine, state.module, &options, sizeof(options), &error)) {
dataLog("FATAL: Could not create LLVM execution engine: ", error, "\n");
CRASH();
}
LLVMPassManagerRef pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(state.engine), pass);
LLVMAddConstantPropagationPass(pass);
LLVMAddInstructionCombiningPass(pass);
LLVMAddPromoteMemoryToRegisterPass(pass);
......@@ -83,97 +72,8 @@ bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
// https://bugs.webkit.org/show_bug.cgi?id=113619
// FIXME: Need to add support for the case where JIT memory allocation failed.
// https://bugs.webkit.org/show_bug.cgi?id=113620
GeneratedFunction function = reinterpret_cast<GeneratedFunction>(LLVMGetPointerToGlobal(engine, state.function));
state.generatedFunction = reinterpret_cast<GeneratedFunction>(LLVMGetPointerToGlobal(state.engine, state.function));
LLVMDisposePassManager(pass);
if (!state.graph.m_watchpoints.areStillValid()) {
LLVMDisposeExecutionEngine(engine);
return false;
}
state.graph.m_watchpoints.reallyAdd();
// Create the entrypoint.
// FIXME: 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, state.graph.m_codeBlock);
compileEntry(jit);
// This part is only necessary for functions. We currently only compile functions.
CCallHelpers::Label fromArityCheck = jit.label();
// 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(state.graph.m_codeBlock->m_numCalleeRegisters * sizeof(Register)),
GPRInfo::callFrameRegister, GPRInfo::regT1);
CCallHelpers::Jump stackCheck = jit.branchPtr(
CCallHelpers::Below,
CCallHelpers::AbsoluteAddress(state.graph.m_vm.interpreter->stack().addressOfEnd()),
GPRInfo::regT1);
CCallHelpers::Label fromStackCheck = jit.label();
jit.setupArgumentsExecState();
jit.move(CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::nonArgGPR0);
jit.call(GPRInfo::nonArgGPR0);
jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
jit.ret();
stackCheck.link(&jit);
jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
jit.poke(
GPRInfo::callFrameRegister,
OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
jit.store32(
CCallHelpers::TrustedImm32(0),
CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
CCallHelpers::Call callStackCheck = jit.call();
// 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
jit.jump(fromStackCheck);
CCallHelpers::Label arityCheck = jit.label();
compileEntry(jit);
jit.load32(
CCallHelpers::payloadFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)),
GPRInfo::regT1);
jit.branch32(
CCallHelpers::AboveOrEqual, GPRInfo::regT1,
CCallHelpers::TrustedImm32(state.graph.m_codeBlock->numParameters()))
.linkTo(fromArityCheck, &jit);
jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
jit.poke(
GPRInfo::callFrameRegister,
OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
jit.store32(
CCallHelpers::TrustedImm32(0),
CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
CCallHelpers::Call callArityCheck = jit.call();
// 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
jit.move(GPRInfo::regT0, GPRInfo::callFrameRegister);
jit.jump(fromArityCheck);
LinkBuffer linkBuffer(state.graph.m_vm, &jit, state.graph.m_codeBlock, JITCompilationMustSucceed);
linkBuffer.link(callStackCheck, cti_stack_check);
linkBuffer.link(callArityCheck, state.graph.m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
jitCodeWithArityCheck = linkBuffer.locationOf(arityCheck);
state.jitCode->initializeCode(
engine,
FINALIZE_DFG_CODE(
linkBuffer,
("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT)).data(), function)));
jitCode = state.jitCode;
return true;
}
} } // namespace JSC::FTL
......
......@@ -34,7 +34,7 @@
namespace JSC { namespace FTL {
bool compile(State&, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
void compile(State&);
} } // namespace JSC::FTL
......
/*
* 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
* 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 "FTLLink.h"
#if ENABLE(FTL_JIT)
#include "CodeBlockWithJITType.h"
#include "DFGCCallHelpers.h"
#include "DFGCommon.h"
#include "FTLJITCode.h"
#include "FTLLLVMHeaders.h"
#include "JITStubs.h"
#include "LinkBuffer.h"
namespace JSC { namespace FTL {
using namespace DFG;
static void compileEntry(CCallHelpers& jit)
{
jit.preserveReturnAddressAfterCall(GPRInfo::regT2);
jit.emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
}
bool link(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
{
if (!state.graph.m_watchpoints.areStillValid()) {
LLVMDisposeExecutionEngine(state.engine);
return false;
}
state.graph.m_watchpoints.reallyAdd();
// Create the entrypoint.
// FIXME: 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, state.graph.m_codeBlock);
compileEntry(jit);
// This part is only necessary for functions. We currently only compile functions.
CCallHelpers::Label fromArityCheck = jit.label();
// 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(state.graph.m_codeBlock->m_numCalleeRegisters * sizeof(Register)),
GPRInfo::callFrameRegister, GPRInfo::regT1);
CCallHelpers::Jump stackCheck = jit.branchPtr(
CCallHelpers::Below,
CCallHelpers::AbsoluteAddress(state.graph.m_vm.interpreter->stack().addressOfEnd()),
GPRInfo::regT1);
CCallHelpers::Label fromStackCheck = jit.label();
jit.setupArgumentsExecState();
jit.move(CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)), GPRInfo::nonArgGPR0);
jit.call(GPRInfo::nonArgGPR0);
jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
jit.ret();
stackCheck.link(&jit);
jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
jit.poke(
GPRInfo::callFrameRegister,
OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
jit.store32(
CCallHelpers::TrustedImm32(0),
CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
CCallHelpers::Call callStackCheck = jit.call();
// 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
jit.jump(fromStackCheck);
CCallHelpers::Label arityCheck = jit.label();
compileEntry(jit);
jit.load32(
CCallHelpers::payloadFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)),