summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGCommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCommon.h')
-rw-r--r--Source/JavaScriptCore/dfg/DFGCommon.h173
1 files changed, 121 insertions, 52 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h
index 7b4b1db5f..4104eb324 100644
--- a/Source/JavaScriptCore/dfg/DFGCommon.h
+++ b/Source/JavaScriptCore/dfg/DFGCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,14 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DFGCommon_h
-#define DFGCommon_h
+#pragma once
-#include <wtf/Platform.h>
+#include "DFGCompilationMode.h"
#if ENABLE(DFG_JIT)
-#include "CodeOrigin.h"
#include "Options.h"
#include "VirtualRegister.h"
@@ -41,11 +39,6 @@ struct Node;
typedef uint32_t BlockIndex;
static const BlockIndex NoBlock = UINT_MAX;
-struct NodePointerTraits {
- static Node* defaultValue() { return 0; }
- static bool isEmptyForDump(Node* value) { return !value; }
-};
-
// Use RefChildren if the child ref counts haven't already been adjusted using
// other means and either of the following is true:
// - The node you're creating is MustGenerate.
@@ -63,19 +56,28 @@ enum RefNodeMode {
DontRefNode
};
-inline bool verboseCompilationEnabled()
+enum SwitchKind {
+ SwitchImm,
+ SwitchChar,
+ SwitchString,
+ SwitchCell
+};
+
+inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
{
- return Options::verboseCompilation() || Options::dumpGraphAtEachPhase();
+ return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) && Options::verboseFTLCompilation());
}
-inline bool logCompilationChanges()
+inline bool logCompilationChanges(CompilationMode mode = DFGMode)
{
- return verboseCompilationEnabled() || Options::logCompilationChanges();
+ return verboseCompilationEnabled(mode) || Options::logCompilationChanges();
}
-inline bool shouldDumpGraphAtEachPhase()
+inline bool shouldDumpGraphAtEachPhase(CompilationMode mode)
{
- return Options::dumpGraphAtEachPhase();
+ if (isFTL(mode))
+ return Options::dumpGraphAtEachPhase() || Options::dumpDFGFTLGraphAtEachPhase();
+ return Options::dumpGraphAtEachPhase() || Options::dumpDFGGraphAtEachPhase();
}
inline bool validationEnabled()
@@ -87,15 +89,6 @@ inline bool validationEnabled()
#endif
}
-inline bool enableConcurrentJIT()
-{
-#if ENABLE(CONCURRENT_JIT)
- return Options::enableConcurrentJIT() && Options::numberOfCompilerThreads();
-#else
- return false;
-#endif
-}
-
inline bool enableInt52()
{
#if USE(JSVALUE64)
@@ -105,9 +98,57 @@ inline bool enableInt52()
#endif
}
-enum SpillRegistersMode { NeedToSpill, DontSpill };
+// The prediction propagator effectively does four passes, with the last pass
+// being done by the separate FixuPhase.
+enum PredictionPass {
+ // We're converging in a straight-forward forward flow fixpoint. This is the
+ // most conventional part of the propagator - it makes only monotonic decisions
+ // based on value profiles and rare case profiles. It ignores baseline JIT rare
+ // case profiles. The goal here is to develop a good guess of which variables
+ // are likely to be purely numerical, which generally doesn't require knowing
+ // the rare case profiles.
+ PrimaryPass,
+
+ // At this point we know what is numerical and what isn't. Non-numerical inputs
+ // to arithmetic operations will not have useful information in the Baseline JIT
+ // rare case profiles because Baseline may take slow path on non-numerical
+ // inputs even if the DFG could handle the input on the fast path. Boolean
+ // inputs are the most obvious example. This pass of prediction propagation will
+ // use Baseline rare case profiles for purely numerical operations and it will
+ // ignore them for everything else. The point of this pass is to develop a good
+ // guess of which variables are likely to be doubles.
+ //
+ // This pass is intentionally weird and goes against what is considered good
+ // form when writing a static analysis: a new data flow of booleans will cause
+ // us to ignore rare case profiles except that by then, we will have already
+ // propagated double types based on our prior assumption that we shouldn't
+ // ignore rare cases. This probably won't happen because the PrimaryPass is
+ // almost certainly going to establish what is and isn't numerical. But it's
+ // conceivable that during this pass we will discover a new boolean data flow.
+ // This ends up being sound because the prediction propagator could literally
+ // make any guesses it wants and still be sound (worst case, we OSR exit more
+ // often or use too general of types are run a bit slower). This will converge
+ // because we force monotonicity on the types of nodes and variables. So, the
+ // worst thing that can happen is that we violate basic laws of theoretical
+ // decency.
+ RareCasePass,
+
+ // At this point we know what is numerical and what isn't, and we also know what
+ // is a double and what isn't. So, we start forcing variables to be double.
+ // Doing so may have a cascading effect so this is a fixpoint. It's monotonic
+ // in the sense that once a variable is forced double, it cannot be forced in
+ // the other direction.
+ DoubleVotingPass,
+
+ // This pass occurs once we have converged. At this point we are just installing
+ // type checks based on the conclusions we have already reached. It's important
+ // for this pass to reach the same conclusions that DoubleVotingPass reached.
+ FixupPass
+};
+
+enum StructureRegistrationState { HaveNotStartedRegistering, AllStructuresAreRegistered };
-enum NoResultTag { NoResult };
+enum StructureRegistrationResult { StructureRegisteredNormally, StructureRegisteredAndWatched };
enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
@@ -145,12 +186,10 @@ enum GraphForm {
// expect to be live at the head, and which locals they make available at the
// tail. ThreadedCPS form also implies that:
//
- // - GetLocals and SetLocals to uncaptured variables are not redundant within
- // a basic block.
+ // - GetLocals and SetLocals are not redundant within a basic block.
//
// - All GetLocals and Flushes are linked directly to the last access point
- // of the variable, which must not be another GetLocal if the variable is
- // uncaptured.
+ // of the variable, which must not be another GetLocal.
//
// - Phantom(Phi) is not legal, but PhantomLocal is.
//
@@ -208,14 +247,44 @@ inline KillStatus killStatusForDoesKill(bool doesKill)
return doesKill ? DoesKill : DoesNotKill;
}
-template<typename T, typename U>
-bool checkAndSet(T& left, U right)
-{
- if (left == right)
- return false;
- left = right;
- return true;
-}
+enum class PlanStage {
+ Initial,
+ AfterFixup
+};
+
+// If possible, this will acquire a lock to make sure that if multiple threads
+// start crashing at the same time, you get coherent dump output. Use this only
+// when you're forcing a crash with diagnostics.
+void startCrashing();
+
+JS_EXPORT_PRIVATE bool isCrashing();
+
+struct NodeAndIndex {
+ NodeAndIndex()
+ : node(nullptr)
+ , index(UINT_MAX)
+ {
+ }
+
+ NodeAndIndex(Node* node, unsigned index)
+ : node(node)
+ , index(index)
+ {
+ ASSERT(!node == (index == UINT_MAX));
+ }
+
+ bool operator!() const
+ {
+ return !node;
+ }
+
+ Node* node;
+ unsigned index;
+};
+
+// A less-than operator for strings that is useful for generating string switches. Sorts by <
+// relation on characters. Ensures that if a is a prefix of b, then a < b.
+bool stringLessThan(StringImpl& a, StringImpl& b);
} } // namespace JSC::DFG
@@ -235,7 +304,12 @@ namespace JSC { namespace DFG {
// Put things here that must be defined even if ENABLE(DFG_JIT) is false.
-enum CapabilityLevel { CannotCompile, CanInline, CanCompile, CanCompileAndInline, CapabilityLevelNotSet };
+enum CapabilityLevel {
+ CannotCompile,
+ CanCompile,
+ CanCompileAndInline,
+ CapabilityLevelNotSet
+};
inline bool canCompile(CapabilityLevel level)
{
@@ -251,7 +325,6 @@ inline bool canCompile(CapabilityLevel level)
inline bool canInline(CapabilityLevel level)
{
switch (level) {
- case CanInline:
case CanCompileAndInline:
return true;
default:
@@ -264,14 +337,6 @@ inline CapabilityLevel leastUpperBound(CapabilityLevel a, CapabilityLevel b)
switch (a) {
case CannotCompile:
return CannotCompile;
- case CanInline:
- switch (b) {
- case CanInline:
- case CanCompileAndInline:
- return CanInline;
- default:
- return CannotCompile;
- }
case CanCompile:
switch (b) {
case CanCompile:
@@ -291,16 +356,20 @@ inline CapabilityLevel leastUpperBound(CapabilityLevel a, CapabilityLevel b)
}
// Unconditionally disable DFG disassembly support if the DFG is not compiled in.
-inline bool shouldShowDisassembly()
+inline bool shouldDumpDisassembly(CompilationMode mode = DFGMode)
{
#if ENABLE(DFG_JIT)
- return Options::showDisassembly() || Options::showDFGDisassembly();
+ return Options::dumpDisassembly() || Options::dumpDFGDisassembly() || (isFTL(mode) && Options::dumpFTLDisassembly());
#else
+ UNUSED_PARAM(mode);
return false;
#endif
}
} } // namespace JSC::DFG
-#endif // DFGCommon_h
+namespace WTF {
+void printInternal(PrintStream&, JSC::DFG::CapabilityLevel);
+
+} // namespace WTF