1/*
2 * Copyright (C) 2014-2019 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#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "DFGGraph.h"
31#include "DFGNode.h"
32
33namespace JSC { namespace DFG {
34
35class PureValue {
36public:
37 PureValue()
38 : m_op(LastNodeType)
39 , m_info(0)
40 {
41 }
42
43 PureValue(NodeType op, const AdjacencyList& children, uintptr_t info)
44 : m_op(op)
45 , m_children(children.sanitized())
46 , m_info(info)
47 {
48 ASSERT(!(defaultFlags(op) & NodeHasVarArgs));
49 }
50
51 PureValue(NodeType op, const AdjacencyList& children, const void* ptr)
52 : PureValue(op, children, bitwise_cast<uintptr_t>(ptr))
53 {
54 }
55
56 PureValue(NodeType op, const AdjacencyList& children)
57 : PureValue(op, children, static_cast<uintptr_t>(0))
58 {
59 }
60
61 PureValue(Node* node, uintptr_t info)
62 : PureValue(node->op(), node->children, info)
63 {
64 }
65
66 PureValue(Node* node, const void* ptr)
67 : PureValue(node->op(), node->children, ptr)
68 {
69 }
70
71 PureValue(Node* node)
72 : PureValue(node->op(), node->children)
73 {
74 }
75
76 PureValue(Graph& graph, Node* node, uintptr_t info)
77 : m_op(node->op())
78 , m_children(node->children)
79 , m_info(info)
80 , m_graph(&graph)
81 {
82 ASSERT(node->flags() & NodeHasVarArgs);
83 ASSERT(isVarargs());
84 }
85
86 PureValue(Graph& graph, Node* node)
87 : PureValue(graph, node, static_cast<uintptr_t>(0))
88 {
89 }
90
91 PureValue(WTF::HashTableDeletedValueType)
92 : m_op(LastNodeType)
93 , m_info(1)
94 {
95 }
96
97 bool operator!() const { return m_op == LastNodeType && !m_info; }
98
99 NodeType op() const { return m_op; }
100 uintptr_t info() const { return m_info; }
101
102 unsigned hash() const
103 {
104 unsigned hash = WTF::IntHash<int>::hash(static_cast<int>(m_op)) + m_info;
105 if (!isVarargs())
106 return hash ^ m_children.hash();
107 for (unsigned i = 0; i < m_children.numChildren(); ++i)
108 hash ^= m_graph->m_varArgChildren[m_children.firstChild() + i].sanitized().hash();
109 return hash;
110 }
111
112 bool operator==(const PureValue& other) const
113 {
114 if (isVarargs() != other.isVarargs() || m_op != other.m_op || m_info != other.m_info)
115 return false;
116 if (!isVarargs())
117 return m_children == other.m_children;
118 if (m_children.numChildren() != other.m_children.numChildren())
119 return false;
120 for (unsigned i = 0; i < m_children.numChildren(); ++i) {
121 Edge a = m_graph->m_varArgChildren[m_children.firstChild() + i].sanitized();
122 Edge b = m_graph->m_varArgChildren[other.m_children.firstChild() + i].sanitized();
123 if (a != b)
124 return false;
125 }
126 return true;
127 }
128
129 bool isHashTableDeletedValue() const
130 {
131 return m_op == LastNodeType && m_info;
132 }
133
134 void dump(PrintStream& out) const;
135
136private:
137 bool isVarargs() const { return !!m_graph; }
138
139 NodeType m_op;
140 AdjacencyList m_children;
141 uintptr_t m_info;
142 Graph* m_graph { nullptr };
143};
144
145struct PureValueHash {
146 static unsigned hash(const PureValue& key) { return key.hash(); }
147 static bool equal(const PureValue& a, const PureValue& b) { return a == b; }
148 static constexpr bool safeToCompareToEmptyOrDeleted = true;
149};
150
151} } // namespace JSC::DFG
152
153namespace WTF {
154
155template<typename T> struct DefaultHash;
156template<> struct DefaultHash<JSC::DFG::PureValue> {
157 typedef JSC::DFG::PureValueHash Hash;
158};
159
160template<typename T> struct HashTraits;
161template<> struct HashTraits<JSC::DFG::PureValue> : SimpleClassHashTraits<JSC::DFG::PureValue> {
162 static constexpr bool emptyValueIsZero = false;
163};
164
165} // namespace WTF
166
167namespace JSC { namespace DFG {
168
169typedef HashMap<PureValue, Node*> PureMap;
170typedef HashMap<PureValue, Vector<Node*>> PureMultiMap;
171
172} } // namespace JSC::DFG
173
174#endif // ENABLE(DFG_JIT)
175