]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGDriver.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / dfg / DFGDriver.cpp
index 09649cc59a4281ac427bae742b97fac666396e7d..30b4f3888e99100b0d236afe610bdff71d72e3a0 100644 (file)
@@ -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
  *
  * 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"
 
 #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 "Options.h"
+#include "SamplingTool.h"
+#include <wtf/Atomics.h>
+
+#if ENABLE(FTL_JIT)
+#include "FTLThunks.h"
+#endif
 
 namespace JSC { namespace DFG {
 
 
 namespace JSC { namespace DFG {
 
@@ -61,8 +53,11 @@ unsigned getNumCompilations()
     return numCompilations;
 }
 
     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)");
     
 {
     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);
     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
 }
 
 } } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-