Home | History | Annotate | Download | only in dfg
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef DFGNode_h
     27 #define DFGNode_h
     28 
     29 // Emit various logging information for debugging, including dumping the dataflow graphs.
     30 #define DFG_DEBUG_VERBOSE 0
     31 // Enable generation of dynamic checks into the instruction stream.
     32 #define DFG_JIT_ASSERT 0
     33 // Consistency check contents compiler data structures.
     34 #define DFG_CONSISTENCY_CHECK 0
     35 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
     36 #define DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
     37 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
     38 #define DFG_JIT_BREAK_ON_EVERY_BLOCK 0
     39 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
     40 #define DFG_JIT_BREAK_ON_EVERY_NODE 0
     41 // Disable the DFG JIT without having to touch Platform.h!
     42 #define DFG_DEBUG_LOCAL_DISBALE 0
     43 // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
     44 #define DFG_SUCCESS_STATS 0
     45 
     46 
     47 #if ENABLE(DFG_JIT)
     48 
     49 #include <wtf/Vector.h>
     50 
     51 namespace JSC { namespace DFG {
     52 
     53 // Type for a virtual register number (spill location).
     54 // Using an enum to make this type-checked at compile time, to avert programmer errors.
     55 enum VirtualRegister { InvalidVirtualRegister = -1 };
     56 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
     57 
     58 // Type for a reference to another node in the graph.
     59 typedef uint32_t NodeIndex;
     60 static const NodeIndex NoNode = UINT_MAX;
     61 
     62 // Information used to map back from an exception to any handler/source information.
     63 // (Presently implemented as a bytecode index).
     64 typedef uint32_t ExceptionInfo;
     65 
     66 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
     67 // and some additional informative flags (must generate, is constant, etc).
     68 #define NodeIdMask          0xFFF
     69 #define NodeResultMask     0xF000
     70 #define NodeMustGenerate  0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
     71 #define NodeIsConstant    0x20000
     72 #define NodeIsJump        0x40000
     73 #define NodeIsBranch      0x80000
     74 
     75 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
     76 #define NodeResultJS      0x1000
     77 #define NodeResultDouble  0x2000
     78 #define NodeResultInt32   0x3000
     79 
     80 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
     81 #define FOR_EACH_DFG_OP(macro) \
     82     /* Nodes for constants. */\
     83     macro(JSConstant, NodeResultJS | NodeIsConstant) \
     84     macro(Int32Constant, NodeResultJS | NodeIsConstant) \
     85     macro(DoubleConstant, NodeResultJS | NodeIsConstant) \
     86     macro(ConvertThis, NodeResultJS) \
     87     \
     88     /* Nodes for local variable access. */\
     89     macro(GetLocal, NodeResultJS) \
     90     macro(SetLocal, NodeMustGenerate) \
     91     \
     92     /* Nodes for bitwise operations. */\
     93     macro(BitAnd, NodeResultInt32) \
     94     macro(BitOr, NodeResultInt32) \
     95     macro(BitXor, NodeResultInt32) \
     96     macro(BitLShift, NodeResultInt32) \
     97     macro(BitRShift, NodeResultInt32) \
     98     macro(BitURShift, NodeResultInt32) \
     99     /* Bitwise operators call ToInt32 on their operands. */\
    100     macro(NumberToInt32, NodeResultInt32) \
    101     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
    102     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
    103     macro(UInt32ToNumber, NodeResultDouble) \
    104     \
    105     /* Nodes for arithmetic operations. */\
    106     macro(ArithAdd, NodeResultDouble) \
    107     macro(ArithSub, NodeResultDouble) \
    108     macro(ArithMul, NodeResultDouble) \
    109     macro(ArithDiv, NodeResultDouble) \
    110     macro(ArithMod, NodeResultDouble) \
    111     /* Arithmetic operators call ToNumber on their operands. */\
    112     macro(Int32ToNumber, NodeResultDouble) \
    113     macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \
    114     \
    115     /* Add of values may either be arithmetic, or result in string concatenation. */\
    116     macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
    117     \
    118     /* Property access. */\
    119     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
    120     /* Since a put to 'length' may invalidate optimizations here, */\
    121     /* this must be the directly subsequent property put. */\
    122     macro(GetByVal, NodeResultJS | NodeMustGenerate) \
    123     macro(PutByVal, NodeMustGenerate) \
    124     macro(PutByValAlias, NodeMustGenerate) \
    125     macro(GetById, NodeResultJS | NodeMustGenerate) \
    126     macro(PutById, NodeMustGenerate) \
    127     macro(PutByIdDirect, NodeMustGenerate) \
    128     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
    129     macro(PutGlobalVar, NodeMustGenerate) \
    130     \
    131     /* Nodes for comparison operations. */\
    132     macro(CompareLess, NodeResultJS | NodeMustGenerate) \
    133     macro(CompareLessEq, NodeResultJS | NodeMustGenerate) \
    134     macro(CompareEq, NodeResultJS | NodeMustGenerate) \
    135     macro(CompareStrictEq, NodeResultJS) \
    136     \
    137     /* Nodes for misc operations. */\
    138     macro(LogicalNot, NodeResultJS) \
    139     \
    140     /* Block terminals. */\
    141     macro(Jump, NodeMustGenerate | NodeIsJump) \
    142     macro(Branch, NodeMustGenerate | NodeIsBranch) \
    143     macro(Return, NodeMustGenerate)
    144 
    145 // This enum generates a monotonically increasing id for all Node types,
    146 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
    147 enum NodeId {
    148 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
    149     FOR_EACH_DFG_OP(DFG_OP_ENUM)
    150 #undef DFG_OP_ENUM
    151 };
    152 
    153 // Entries in this enum describe all Node types.
    154 // The enum value contains a monotonically increasing id, a result type, and additional flags.
    155 enum NodeType {
    156 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
    157     FOR_EACH_DFG_OP(DFG_OP_ENUM)
    158 #undef DFG_OP_ENUM
    159 };
    160 
    161 // This type used in passing an immediate argument to Node constructor;
    162 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
    163 // a constant index, argument, or identifier) from a NodeIndex.
    164 struct OpInfo {
    165     explicit OpInfo(unsigned value) : m_value(value) {}
    166     unsigned m_value;
    167 };
    168 
    169 // === Node ===
    170 //
    171 // Node represents a single operation in the data flow graph.
    172 struct Node {
    173     // Construct a node with up to 3 children, no immediate value.
    174     Node(NodeType op, ExceptionInfo exceptionInfo, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
    175         : op(op)
    176         , exceptionInfo(exceptionInfo)
    177         , child1(child1)
    178         , child2(child2)
    179         , child3(child3)
    180         , virtualRegister(InvalidVirtualRegister)
    181         , refCount(0)
    182     {
    183     }
    184 
    185     // Construct a node with up to 3 children and an immediate value.
    186     Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
    187         : op(op)
    188         , exceptionInfo(exceptionInfo)
    189         , child1(child1)
    190         , child2(child2)
    191         , child3(child3)
    192         , virtualRegister(InvalidVirtualRegister)
    193         , refCount(0)
    194         , m_opInfo(imm.m_value)
    195     {
    196     }
    197 
    198     // Construct a node with up to 3 children and two immediate values.
    199     Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
    200         : op(op)
    201         , exceptionInfo(exceptionInfo)
    202         , child1(child1)
    203         , child2(child2)
    204         , child3(child3)
    205         , virtualRegister(InvalidVirtualRegister)
    206         , refCount(0)
    207         , m_opInfo(imm1.m_value)
    208     {
    209         m_constantValue.opInfo2 = imm2.m_value;
    210     }
    211 
    212     bool mustGenerate()
    213     {
    214         return op & NodeMustGenerate;
    215     }
    216 
    217     bool isConstant()
    218     {
    219         return op & NodeIsConstant;
    220     }
    221 
    222     unsigned constantNumber()
    223     {
    224         ASSERT(isConstant());
    225         return m_opInfo;
    226     }
    227 
    228     bool hasLocal()
    229     {
    230         return op == GetLocal || op == SetLocal;
    231     }
    232 
    233     VirtualRegister local()
    234     {
    235         ASSERT(hasLocal());
    236         return (VirtualRegister)m_opInfo;
    237     }
    238 
    239     bool hasIdentifier()
    240     {
    241         return op == GetById || op == PutById || op == PutByIdDirect;
    242     }
    243 
    244     unsigned identifierNumber()
    245     {
    246         ASSERT(hasIdentifier());
    247         return m_opInfo;
    248     }
    249 
    250     bool hasVarNumber()
    251     {
    252         return op == GetGlobalVar || op == PutGlobalVar;
    253     }
    254 
    255     unsigned varNumber()
    256     {
    257         ASSERT(hasVarNumber());
    258         return m_opInfo;
    259     }
    260 
    261     bool hasInt32Result()
    262     {
    263         return (op & NodeResultMask) == NodeResultInt32;
    264     }
    265 
    266     bool hasDoubleResult()
    267     {
    268         return (op & NodeResultMask) == NodeResultDouble;
    269     }
    270 
    271     bool hasJSResult()
    272     {
    273         return (op & NodeResultMask) == NodeResultJS;
    274     }
    275 
    276     // Check for integers or doubles.
    277     bool hasNumericResult()
    278     {
    279         // This check will need updating if more result types are added.
    280         ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult());
    281         return !hasJSResult();
    282     }
    283 
    284     int32_t int32Constant()
    285     {
    286         ASSERT(op == Int32Constant);
    287         return m_constantValue.asInt32;
    288     }
    289 
    290     void setInt32Constant(int32_t value)
    291     {
    292         ASSERT(op == Int32Constant);
    293         m_constantValue.asInt32 = value;
    294     }
    295 
    296     double numericConstant()
    297     {
    298         ASSERT(op == DoubleConstant);
    299         return m_constantValue.asDouble;
    300     }
    301 
    302     void setDoubleConstant(double value)
    303     {
    304         ASSERT(op == DoubleConstant);
    305         m_constantValue.asDouble = value;
    306     }
    307 
    308     bool isJump()
    309     {
    310         return op & NodeIsJump;
    311     }
    312 
    313     bool isBranch()
    314     {
    315         return op & NodeIsBranch;
    316     }
    317 
    318     unsigned takenBytecodeOffset()
    319     {
    320         ASSERT(isBranch() || isJump());
    321         return m_opInfo;
    322     }
    323 
    324     unsigned notTakenBytecodeOffset()
    325     {
    326         ASSERT(isBranch());
    327         return m_constantValue.opInfo2;
    328     }
    329 
    330     // This enum value describes the type of the node.
    331     NodeType op;
    332     // Used to look up exception handling information (currently implemented as a bytecode index).
    333     ExceptionInfo exceptionInfo;
    334     // References to up to 3 children (0 for no child).
    335     NodeIndex child1, child2, child3;
    336     // The virtual register number (spill location) associated with this .
    337     VirtualRegister virtualRegister;
    338     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
    339     unsigned refCount;
    340 
    341 private:
    342     // An immediate value, accesses type-checked via accessors above.
    343     unsigned m_opInfo;
    344     // The value of an int32/double constant.
    345     union {
    346         int32_t asInt32;
    347         double asDouble;
    348         unsigned opInfo2;
    349     } m_constantValue;
    350 };
    351 
    352 } } // namespace JSC::DFG
    353 
    354 #endif
    355 #endif
    356