diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCommon.h')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGCommon.h | 193 |
1 files changed, 151 insertions, 42 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h index 14c47cefc..7aef749b0 100644 --- a/Source/JavaScriptCore/dfg/DFGCommon.h +++ b/Source/JavaScriptCore/dfg/DFGCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ #include "VirtualRegister.h" /* DFG_ENABLE() - turn on a specific features in the DFG JIT */ -#define DFG_ENABLE(DFG_FEATURE) (defined DFG_ENABLE_##DFG_FEATURE && DFG_ENABLE_##DFG_FEATURE) +#define DFG_ENABLE(DFG_FEATURE) (defined DFG_ENABLE_##DFG_FEATURE && DFG_ENABLE_##DFG_FEATURE) // Emit various logging information for debugging, including dumping the dataflow graphs. #define DFG_ENABLE_DEBUG_VERBOSE 0 @@ -50,14 +50,6 @@ #else #define DFG_ENABLE_JIT_ASSERT 0 #endif -// Enable validation of the graph. -#if !ASSERT_DISABLED -#define DFG_ENABLE_VALIDATION 1 -#else -#define DFG_ENABLE_VALIDATION 0 -#endif -// Enable validation on completion of each phase. -#define DFG_ENABLE_PER_PHASE_VALIDATION 0 // Consistency check contents compiler data structures. #define DFG_ENABLE_CONSISTENCY_CHECK 0 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB. @@ -70,8 +62,6 @@ #define DFG_ENABLE_XOR_DEBUG_AID 0 // Emit a breakpoint into the speculation failure code. #define DFG_ENABLE_JIT_BREAK_ON_SPECULATION_FAILURE 0 -// Log every speculation failure. -#define DFG_ENABLE_VERBOSE_SPECULATION_FAILURE 0 // Disable the DFG JIT without having to touch Platform.h #define DFG_DEBUG_LOCAL_DISBALE 0 // Enable OSR entry from baseline JIT. @@ -83,49 +73,66 @@ namespace JSC { namespace DFG { -// Type for a reference to another node in the graph. -typedef uint32_t NodeIndex; -static const NodeIndex NoNode = UINT_MAX; +struct Node; typedef uint32_t BlockIndex; static const BlockIndex NoBlock = UINT_MAX; -struct NodeIndexTraits { - static NodeIndex defaultValue() { return NoNode; } - static void dump(NodeIndex value, PrintStream& out) - { - if (value == NoNode) - out.printf("-"); - else - out.printf("@%u", value); - } +struct NodePointerTraits { + static Node* defaultValue() { return 0; } + static void dump(Node* value, PrintStream& out); }; -enum UseKind { - UntypedUse, - DoubleUse, - LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements. +// 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. +// - The place where you're inserting a reference to the node you're creating +// will not also do RefChildren. +enum RefChildrenMode { + RefChildren, + DontRefChildren }; -inline const char* useKindToString(UseKind useKind) +// Use RefNode if you know that the node will be used from another node, and you +// will not already be ref'ing the node to account for that use. +enum RefNodeMode { + RefNode, + DontRefNode +}; + +inline bool verboseCompilationEnabled() { - switch (useKind) { - case UntypedUse: - return ""; - case DoubleUse: - return "d"; - default: - ASSERT_NOT_REACHED(); - return 0; - } +#if DFG_ENABLE(DEBUG_VERBOSE) + return true; +#else + return Options::verboseCompilation() || Options::dumpGraphAtEachPhase(); +#endif } -inline bool isX86() +inline bool logCompilationChanges() { -#if CPU(X86_64) || CPU(X86) +#if DFG_ENABLE(DEBUG_VERBOSE) return true; #else - return false; + return verboseCompilationEnabled() || Options::logCompilationChanges(); +#endif +} + +inline bool shouldDumpGraphAtEachPhase() +{ +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + return true; +#else + return Options::dumpGraphAtEachPhase(); +#endif +} + +inline bool validationEnabled() +{ +#if !ASSERT_DISABLED + return true; +#else + return Options::validateGraph() || Options::validateGraphAtEachPhase(); #endif } @@ -135,15 +142,117 @@ enum NoResultTag { NoResult }; enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged }; +// Describes the form you can expect the entire graph to be in. +enum GraphForm { + // LoadStore form means that basic blocks may freely use GetLocal, SetLocal, + // GetLocalUnlinked, and Flush for accessing local variables and indicating + // where their live ranges ought to be. Data flow between local accesses is + // implicit. Liveness is only explicit at block heads (variablesAtHead). + // This is only used by the DFG simplifier and is only preserved by same. + // + // For example, LoadStore form gives no easy way to determine which SetLocal's + // flow into a GetLocal. As well, LoadStore form implies no restrictions on + // redundancy: you can freely emit multiple GetLocals, or multiple SetLocals + // (or any combination thereof) to the same local in the same block. LoadStore + // form does not require basic blocks to declare how they affect or use locals, + // other than implicitly by using the local ops and by preserving + // variablesAtHead. Finally, LoadStore allows flexibility in how liveness of + // locals is extended; for example you can replace a GetLocal with a Phantom + // and so long as the Phantom retains the GetLocal's children (i.e. the Phi + // most likely) then it implies that the local is still live but that it need + // not be stored to the stack necessarily. This implies that Phantom can + // reference nodes that have no result, as long as those nodes are valid + // GetLocal children (i.e. Phi, SetLocal, SetArgument). + // + // LoadStore form also implies that Phis need not have children. By default, + // they end up having no children if you enter LoadStore using the canonical + // way (call Graph::dethread). + // + // LoadStore form is suitable for CFG transformations, as well as strength + // reduction, folding, and CSE. + LoadStore, + + // ThreadedCPS form means that basic blocks list up-front which locals they + // 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. + // + // - 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. + // + // - Phantom(Phi) is not legal, but PhantomLocal is. + // + // ThreadedCPS form is suitable for data flow analysis (CFA, prediction + // propagation), register allocation, and code generation. + ThreadedCPS +}; + +// Describes the state of the UnionFind structure of VariableAccessData's. +enum UnificationState { + // BasicBlock-local accesses to variables are appropriately unified with each other. + LocallyUnified, + + // Unification has been performed globally. + GloballyUnified +}; + +// Describes how reference counts in the graph behave. +enum RefCountState { + // Everything has refCount() == 1. + EverythingIsLive, + + // Set after DCE has run. + ExactRefCount +}; + +enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation }; + +enum SpeculationDirection { ForwardSpeculation, BackwardSpeculation }; + +enum ProofStatus { NeedsCheck, IsProved }; + +inline bool isProved(ProofStatus proofStatus) +{ + ASSERT(proofStatus == IsProved || proofStatus == NeedsCheck); + return proofStatus == IsProved; +} + +inline ProofStatus proofStatusForIsProved(bool isProved) +{ + return isProved ? IsProved : NeedsCheck; +} + +template<typename T, typename U> +bool checkAndSet(T& left, U right) +{ + if (left == right) + return false; + left = right; + return true; +} + } } // namespace JSC::DFG +namespace WTF { + +void printInternal(PrintStream&, JSC::DFG::OptimizationFixpointState); +void printInternal(PrintStream&, JSC::DFG::GraphForm); +void printInternal(PrintStream&, JSC::DFG::UnificationState); +void printInternal(PrintStream&, JSC::DFG::RefCountState); +void printInternal(PrintStream&, JSC::DFG::ProofStatus); + +} // namespace WTF + #endif // ENABLE(DFG_JIT) namespace JSC { namespace DFG { // Put things here that must be defined even if ENABLE(DFG_JIT) is false. -enum CapabilityLevel { CannotCompile, ShouldProfile, CanCompile, CapabilityLevelNotSet }; +enum CapabilityLevel { CannotCompile, MayInline, CanCompile, CapabilityLevelNotSet }; // Unconditionally disable DFG disassembly support if the DFG is not compiled in. inline bool shouldShowDisassembly() |