/*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "JSObject.h"
#include "JSString.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGArgumentsSimplificationPhase.h"
-#include "DFGBackwardsPropagationPhase.h"
-#include "DFGByteCodeParser.h"
-#include "DFGCFAPhase.h"
-#include "DFGCFGSimplificationPhase.h"
-#include "DFGCPSRethreadingPhase.h"
-#include "DFGCSEPhase.h"
-#include "DFGConstantFoldingPhase.h"
-#include "DFGDCEPhase.h"
-#include "DFGFixupPhase.h"
-#include "DFGJITCompiler.h"
-#include "DFGPredictionInjectionPhase.h"
-#include "DFGPredictionPropagationPhase.h"
-#include "DFGTypeCheckHoistingPhase.h"
-#include "DFGUnificationPhase.h"
-#include "DFGValidate.h"
-#include "DFGVirtualRegisterAllocationPhase.h"
-#include "Operations.h"
+#include "CodeBlock.h"
+#include "DFGJITCode.h"
+#include "DFGPlan.h"
+#include "DFGThunks.h"
+#include "DFGWorklist.h"
+#include "JITCode.h"
+#include "JSCInlines.h"
#include "Options.h"
+#include "SamplingTool.h"
+#include <wtf/Atomics.h>
+
+#if ENABLE(FTL_JIT)
+#include "FTLThunks.h"
+#endif
namespace JSC { namespace DFG {
return numCompilations;
}
-enum CompileMode { CompileFunction, CompileOther };
-inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
+#if ENABLE(DFG_JIT)
+static CompilationResult compileImpl(
+ VM& vm, CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationMode mode,
+ unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues,
+ PassRefPtr<DeferredCompilationCallback> callback)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
ASSERT(codeBlock);
ASSERT(codeBlock->alternative());
- ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
+ ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
+ ASSERT(!profiledDFGCodeBlock || profiledDFGCodeBlock->jitType() == JITCode::DFGJIT);
- ASSERT(osrEntryBytecodeIndex != UINT_MAX);
-
- if (!Options::useDFGJIT())
- return false;
-
- if (!Options::bytecodeRangeToDFGCompile().isInRange(codeBlock->instructionCount()))
- return false;
-
- if (logCompilationChanges())
- dataLog("DFG compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
+ if (logCompilationChanges(mode))
+ dataLog("DFG(Driver) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
- // Derive our set of must-handle values. The compilation must be at least conservative
- // enough to allow for OSR entry with these values.
- unsigned numVarsWithValues;
- if (osrEntryBytecodeIndex)
- numVarsWithValues = codeBlock->m_numVars;
- else
- numVarsWithValues = 0;
- Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
- for (size_t i = 0; i < mustHandleValues.size(); ++i) {
- int operand = mustHandleValues.operandForIndex(i);
- if (operandIsArgument(operand)
- && !operandToArgument(operand)
- && compileMode == CompileFunction
- && codeBlock->specializationKind() == CodeForConstruct) {
- // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
- // also never be used. It doesn't matter what we put into the value for this,
- // but it has to be an actual value that can be grokked by subsequent DFG passes,
- // so we sanitize it here by turning it into Undefined.
- mustHandleValues[i] = jsUndefined();
- } else
- mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
+ // Make sure that any stubs that the DFG is going to use are initialized. We want to
+ // make sure that all JIT code generation does finalization on the main thread.
+ vm.getCTIStub(osrExitGenerationThunkGenerator);
+ vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
+ if (mode == DFGMode) {
+ vm.getCTIStub(linkCallThunkGenerator);
+ vm.getCTIStub(linkConstructThunkGenerator);
+ vm.getCTIStub(linkClosureCallThunkGenerator);
+ vm.getCTIStub(virtualCallThunkGenerator);
+ vm.getCTIStub(virtualConstructThunkGenerator);
+ } else {
+ vm.getCTIStub(linkCallThatPreservesRegsThunkGenerator);
+ vm.getCTIStub(linkConstructThatPreservesRegsThunkGenerator);
+ vm.getCTIStub(linkClosureCallThatPreservesRegsThunkGenerator);
+ vm.getCTIStub(virtualCallThatPreservesRegsThunkGenerator);
+ vm.getCTIStub(virtualConstructThatPreservesRegsThunkGenerator);
}
- Graph dfg(exec->vm(), codeBlock, osrEntryBytecodeIndex, mustHandleValues);
- if (!parse(exec, dfg))
- return false;
-
- // By this point the DFG bytecode parser will have potentially mutated various tables
- // in the CodeBlock. This is a good time to perform an early shrink, which is more
- // powerful than a late one. It's safe to do so because we haven't generated any code
- // that references any of the tables directly, yet.
- codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
-
- if (validationEnabled())
- validate(dfg);
-
- performCPSRethreading(dfg);
- performUnification(dfg);
- performPredictionInjection(dfg);
-
- if (validationEnabled())
- validate(dfg);
-
- performBackwardsPropagation(dfg);
- performPredictionPropagation(dfg);
- performFixup(dfg);
- performTypeCheckHoisting(dfg);
+ RefPtr<Plan> plan = adoptRef(
+ new Plan(codeBlock, profiledDFGCodeBlock, mode, osrEntryBytecodeIndex, mustHandleValues));
- dfg.m_fixpointState = FixpointNotConverged;
-
- performCSE(dfg);
- performArgumentsSimplification(dfg);
- performCPSRethreading(dfg); // This should usually be a no-op since CSE rarely dethreads, and arguments simplification rarely does anything.
- performCFA(dfg);
- performConstantFolding(dfg);
- performCFGSimplification(dfg);
-
- dfg.m_fixpointState = FixpointConverged;
-
- performStoreElimination(dfg);
- performCPSRethreading(dfg);
- performDCE(dfg);
- performVirtualRegisterAllocation(dfg);
-
- GraphDumpMode modeForFinalValidate = DumpGraph;
- if (verboseCompilationEnabled()) {
- dataLogF("Graph after optimization:\n");
- dfg.dump();
- modeForFinalValidate = DontDumpGraph;
- }
- if (validationEnabled())
- validate(dfg, modeForFinalValidate);
-
- JITCompiler dataFlowJIT(dfg);
- bool result;
- if (compileMode == CompileFunction) {
- ASSERT(jitCodeWithArityCheck);
-
- result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck);
- } else {
- ASSERT(compileMode == CompileOther);
- ASSERT(!jitCodeWithArityCheck);
-
- result = dataFlowJIT.compile(jitCode);
+ if (Options::enableConcurrentJIT()) {
+ Worklist* worklist = ensureGlobalWorklistFor(mode);
+ plan->callback = callback;
+ if (logCompilationChanges(mode))
+ dataLog("Deferring DFG compilation of ", *codeBlock, " with queue length ", worklist->queueLength(), ".\n");
+ worklist->enqueue(plan);
+ return CompilationDeferred;
}
- return result;
+ plan->compileInThread(*vm.dfgState, 0);
+ return plan->finalizeWithoutNotifyingCallback();
}
-
-bool tryCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, unsigned bytecodeIndex)
+#else // ENABLE(DFG_JIT)
+static CompilationResult compileImpl(
+ VM&, CodeBlock*, CodeBlock*, CompilationMode, unsigned, const Operands<JSValue>&,
+ PassRefPtr<DeferredCompilationCallback>)
{
- return compile(CompileOther, exec, codeBlock, jitCode, 0, bytecodeIndex);
+ return CompilationFailed;
}
+#endif // ENABLE(DFG_JIT)
-bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex)
+CompilationResult compile(
+ VM& vm, CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationMode mode,
+ unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues,
+ PassRefPtr<DeferredCompilationCallback> passedCallback)
{
- return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex);
+ RefPtr<DeferredCompilationCallback> callback = passedCallback;
+ CompilationResult result = compileImpl(
+ vm, codeBlock, profiledDFGCodeBlock, mode, osrEntryBytecodeIndex, mustHandleValues,
+ callback);
+ if (result != CompilationDeferred)
+ callback->compilationDidComplete(codeBlock, result);
+ return result;
}
} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-