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