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 DFGAliasTracker_h
     27 #define DFGAliasTracker_h
     28 
     29 #if ENABLE(DFG_JIT)
     30 
     31 #include <dfg/DFGGraph.h>
     32 #include <wtf/Vector.h>
     33 
     34 namespace JSC { namespace DFG {
     35 
     36 // === AliasTracker ===
     37 //
     38 // This class id used to detect aliasing property accesses, which we may
     39 // be able to speculatively optimize (for example removing redundant loads
     40 // where we know a getter will not be called, or optimizing puts to arrays
     41 // where we know the value being written to in within length and is not a
     42 // hole value). In time, this should be more than a 1-deep buffer!
     43 class AliasTracker {
     44 public:
     45     AliasTracker(Graph& graph)
     46         : m_graph(graph)
     47         , m_candidateAliasGetByVal(NoNode)
     48     {
     49     }
     50 
     51     NodeIndex lookupGetByVal(NodeIndex base, NodeIndex property)
     52     {
     53         // Try to detect situations where a GetByVal follows another GetByVal to the same
     54         // property; in these cases, we may be able to omit the subsequent get on the
     55         // speculative path, where we know conditions hold to make this safe (for example,
     56         // on the speculative path we will not have allowed getter access).
     57         if (m_candidateAliasGetByVal != NoNode) {
     58             Node& possibleAlias = m_graph[m_candidateAliasGetByVal];
     59             ASSERT(possibleAlias.op == GetByVal);
     60             // This check ensures the accesses alias, provided that the subscript is an
     61             // integer index (this is good enough; the speculative path will only generate
     62             // optimized accesses to handle integer subscripts).
     63             if (possibleAlias.child1 == base && equalIgnoringLaterNumericConversion(possibleAlias.child2, property))
     64                 return m_candidateAliasGetByVal;
     65         }
     66         return NoNode;
     67     }
     68 
     69     void recordGetByVal(NodeIndex getByVal)
     70     {
     71         m_candidateAliasGetByVal = getByVal;
     72     }
     73 
     74     void recordPutByVal(NodeIndex putByVal)
     75     {
     76         ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByVal || m_graph[putByVal].op == PutByValAlias);
     77         m_candidateAliasGetByVal = NoNode;
     78     }
     79 
     80     void recordGetById(NodeIndex getById)
     81     {
     82         ASSERT_UNUSED(getById, m_graph[getById].op == GetById);
     83         m_candidateAliasGetByVal = NoNode;
     84     }
     85 
     86     void recordPutById(NodeIndex putById)
     87     {
     88         ASSERT_UNUSED(putById, m_graph[putById].op == PutById);
     89         m_candidateAliasGetByVal = NoNode;
     90     }
     91 
     92     void recordPutByIdDirect(NodeIndex putByVal)
     93     {
     94         ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByIdDirect);
     95         m_candidateAliasGetByVal = NoNode;
     96     }
     97 
     98 private:
     99     // This method returns true for arguments:
    100     //   - (X, X)
    101     //   - (X, ValueToNumber(X))
    102     //   - (X, ValueToInt32(X))
    103     //   - (X, NumberToInt32(X))
    104     bool equalIgnoringLaterNumericConversion(NodeIndex op1, NodeIndex op2)
    105     {
    106         if (op1 == op2)
    107             return true;
    108         Node& node2 = m_graph[op2];
    109         return (node2.op == ValueToNumber || node2.op == ValueToInt32 || node2.op == NumberToInt32) && op1 == node2.child1;
    110     }
    111 
    112     // The graph, to look up potentially aliasing nodes.
    113     Graph& m_graph;
    114     // Currently a 1-deep buffer!
    115     NodeIndex m_candidateAliasGetByVal;
    116 };
    117 
    118 } } // namespace JSC::DFG
    119 
    120 #endif
    121 #endif
    122