X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/dfg/DFGDriver.cpp?ds=sidebyside diff --git a/dfg/DFGDriver.cpp b/dfg/DFGDriver.cpp index 09649cc..30b4f38 100644 --- a/dfg/DFGDriver.cpp +++ b/dfg/DFGDriver.cpp @@ -1,5 +1,5 @@ /* - * 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 @@ -29,28 +29,20 @@ #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 + +#if ENABLE(FTL_JIT) +#include "FTLThunks.h" +#endif namespace JSC { namespace DFG { @@ -61,8 +53,11 @@ unsigned getNumCompilations() 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& mustHandleValues, + PassRefPtr callback) { SamplingRegion samplingRegion("DFG Compilation (Driver)"); @@ -70,119 +65,66 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo 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 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 = 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&, + PassRefPtr) { - 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& mustHandleValues, + PassRefPtr passedCallback) { - return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex); + RefPtr 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) -