#include "config.h"
#include "DFGDriver.h"
#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 "Options.h"
namespace JSC { namespace DFG {
static unsigned numCompilations;
unsigned getNumCompilations()
{
return numCompilations;
}
enum CompileMode { CompileFunction, CompileOther };
inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
numCompilations++;
ASSERT(codeBlock);
ASSERT(codeBlock->alternative());
ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
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");
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) {
mustHandleValues[i] = jsUndefined();
} else
mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
}
Graph dfg(exec->vm(), codeBlock, osrEntryBytecodeIndex, mustHandleValues);
if (!parse(exec, dfg))
return false;
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);
dfg.m_fixpointState = FixpointNotConverged;
performCSE(dfg);
performArgumentsSimplification(dfg);
performCPSRethreading(dfg); 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);
}
return result;
}
bool tryCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, unsigned bytecodeIndex)
{
return compile(CompileOther, exec, codeBlock, jitCode, 0, bytecodeIndex);
}
bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex)
{
return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex);
}
} }
#endif // ENABLE(DFG_JIT)