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 #include "config.h"
     27 #include "DFGGraph.h"
     28 
     29 #include "CodeBlock.h"
     30 
     31 #if ENABLE(DFG_JIT)
     32 
     33 namespace JSC { namespace DFG {
     34 
     35 #ifndef NDEBUG
     36 
     37 // Creates an array of stringized names.
     38 static const char* dfgOpNames[] = {
     39 #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
     40     FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM)
     41 #undef STRINGIZE_DFG_OP_ENUM
     42 };
     43 
     44 void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
     45 {
     46     Node& node = at(nodeIndex);
     47     NodeType op = node.op;
     48 
     49     unsigned refCount = node.refCount;
     50     if (!refCount)
     51         return;
     52     bool mustGenerate = node.mustGenerate();
     53     if (mustGenerate)
     54         --refCount;
     55 
     56     // Example/explanation of dataflow dump output
     57     //
     58     //   14:   <!2:7>  GetByVal(@3, @13)
     59     //   ^1     ^2 ^3     ^4       ^5
     60     //
     61     // (1) The nodeIndex of this operation.
     62     // (2) The reference count. The number printed is the 'real' count,
     63     //     not including the 'mustGenerate' ref. If the node is
     64     //     'mustGenerate' then the count it prefixed with '!'.
     65     // (3) The virtual register slot assigned to this node.
     66     // (4) The name of the operation.
     67     // (5) The arguments to the operation. The may be of the form:
     68     //         @#   - a NodeIndex referencing a prior node in the graph.
     69     //         arg# - an argument number.
     70     //         $#   - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }.
     71     //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
     72     //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
     73     printf("% 4d:\t<%c%u:%u>\t%s(", (int)nodeIndex, mustGenerate ? '!' : ' ', refCount, node.virtualRegister, dfgOpNames[op & NodeIdMask]);
     74     if (node.child1 != NoNode)
     75         printf("@%u", node.child1);
     76     if (node.child2 != NoNode)
     77         printf(", @%u", node.child2);
     78     if (node.child3 != NoNode)
     79         printf(", @%u", node.child3);
     80     bool hasPrinted = node.child1 != NoNode;
     81 
     82     if (node.hasVarNumber()) {
     83         printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
     84         hasPrinted = true;
     85     }
     86     if (node.hasIdentifier()) {
     87         if (codeBlock)
     88             printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
     89         else
     90             printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber());
     91         hasPrinted = true;
     92     }
     93     if (node.hasLocal()) {
     94         int local = node.local();
     95         if (local < 0)
     96             printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister());
     97         else
     98             printf("%sr%u", hasPrinted ? ", " : "", local);
     99         hasPrinted = true;
    100     }
    101     if (op == Int32Constant) {
    102         printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant());
    103         hasPrinted = true;
    104     }
    105     if (op == DoubleConstant) {
    106         printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant());
    107         hasPrinted = true;
    108     }
    109     if (op == JSConstant) {
    110         printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
    111         hasPrinted = true;
    112     }
    113     if  (node.isBranch() || node.isJump()) {
    114         printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
    115         hasPrinted = true;
    116     }
    117     if  (node.isBranch()) {
    118         printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
    119         hasPrinted = true;
    120     }
    121 
    122     printf(")\n");
    123 }
    124 
    125 void Graph::dump(CodeBlock* codeBlock)
    126 {
    127     for (size_t b = 0; b < m_blocks.size(); ++b) {
    128         printf("Block #%u:\n", (int)b);
    129         BasicBlock& block = m_blocks[b];
    130         for (size_t i = block.begin; i < block.end; ++i)
    131             dump(i, codeBlock);
    132     }
    133 }
    134 
    135 #endif
    136 
    137 // FIXME: Convert these methods to be iterative, not recursive.
    138 void Graph::refChildren(NodeIndex op)
    139 {
    140     Node& node = at(op);
    141 
    142     if (node.child1 == NoNode) {
    143         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
    144         return;
    145     }
    146     ref(node.child1);
    147 
    148     if (node.child2 == NoNode) {
    149         ASSERT(node.child3 == NoNode);
    150         return;
    151     }
    152     ref(node.child2);
    153 
    154     if (node.child3 == NoNode)
    155         return;
    156     ref(node.child3);
    157 }
    158 void Graph::derefChildren(NodeIndex op)
    159 {
    160     Node& node = at(op);
    161 
    162     if (node.child1 == NoNode) {
    163         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
    164         return;
    165     }
    166     deref(node.child1);
    167 
    168     if (node.child2 == NoNode) {
    169         ASSERT(node.child3 == NoNode);
    170         return;
    171     }
    172     deref(node.child2);
    173 
    174     if (node.child3 == NoNode)
    175         return;
    176     deref(node.child3);
    177 }
    178 
    179 } } // namespace JSC::DFG
    180 
    181 #endif
    182