blob: d4be12a27349ad48a77b15ddf5b6905a35afc890 [file] [log] [blame]
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001/*
fpizlo@apple.come799b862016-03-01 21:18:42 +00002 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003 *
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
ryanhaddad@apple.com22104f52016-09-28 17:08:17 +000026#pragma once
oliver@apple.com55d32d92013-07-25 04:05:03 +000027
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000028#if ENABLE(DFG_JIT)
29
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000030#include "ArrayConstructor.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000031#include "DFGAbstractInterpreter.h"
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000032#include "DOMJITGetterSetter.h"
utatane.tea@gmail.com0d74c7c2016-11-03 03:20:53 +000033#include "DOMJITSignature.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000034#include "GetByIdStatus.h"
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000035#include "GetterSetter.h"
sbarati@apple.coma528ff02016-09-12 21:04:25 +000036#include "HashMapImpl.h"
benjamin@webkit.org903025b2015-02-14 04:20:21 +000037#include "JITOperations.h"
benjamin@webkit.org28b4f2d2015-02-18 08:01:01 +000038#include "MathCommon.h"
oliver@apple.come722ad02013-01-09 02:37:29 +000039#include "Operations.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000040#include "PutByIdStatus.h"
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +000041#include "StringObject.h"
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000042
43namespace JSC { namespace DFG {
44
oliver@apple.com55d32d92013-07-25 04:05:03 +000045template<typename AbstractStateType>
46AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000047 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000048 , m_graph(graph)
oliver@apple.com55d32d92013-07-25 04:05:03 +000049 , m_state(state)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000050{
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000051 if (m_graph.m_form == SSA)
52 m_phiChildren = std::make_unique<PhiChildren>(m_graph);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000053}
54
oliver@apple.com55d32d92013-07-25 04:05:03 +000055template<typename AbstractStateType>
56AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000057{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000058}
59
oliver@apple.com55d32d92013-07-25 04:05:03 +000060template<typename AbstractStateType>
61typename AbstractInterpreter<AbstractStateType>::BooleanResult
62AbstractInterpreter<AbstractStateType>::booleanResult(
63 Node* node, AbstractValue& value)
fpizlo@apple.com367a1102012-11-10 23:33:29 +000064{
65 JSValue childConst = value.value();
66 if (childConst) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +000067 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
fpizlo@apple.com367a1102012-11-10 23:33:29 +000068 return DefinitelyTrue;
69 return DefinitelyFalse;
70 }
71
72 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000073 if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
74 bool allTrue = true;
75 for (unsigned i = value.m_structure.size(); i--;) {
76 Structure* structure = value.m_structure[i];
77 if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
78 || structure->typeInfo().type() == StringType) {
79 allTrue = false;
80 break;
81 }
82 }
83 if (allTrue)
fpizlo@apple.com367a1102012-11-10 23:33:29 +000084 return DefinitelyTrue;
85 }
86
87 return UnknownBooleanResult;
88}
89
oliver@apple.com55d32d92013-07-25 04:05:03 +000090template<typename AbstractStateType>
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000091void AbstractInterpreter<AbstractStateType>::startExecuting()
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000092{
oliver@apple.com55d32d92013-07-25 04:05:03 +000093 ASSERT(m_state.block());
94 ASSERT(m_state.isValid());
fpizlo@apple.comb75911b2012-06-13 20:53:52 +000095
oliver@apple.com55d32d92013-07-25 04:05:03 +000096 m_state.setDidClobber(false);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000097}
98
oliver@apple.com55d32d92013-07-25 04:05:03 +000099template<typename AbstractStateType>
100void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000101{
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000102 m_graph.doToChildren(
103 node,
104 [&] (Edge& edge) {
105 filterEdgeByUse(edge);
106 });
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000107}
108
oliver@apple.com55d32d92013-07-25 04:05:03 +0000109template<typename AbstractStateType>
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000110void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000111{
fpizlo@apple.com96679c02015-09-01 18:27:13 +0000112 // Some use kinds are required to not have checks, because we know somehow that the incoming
113 // value will already have the type we want. In those cases, AI may not be smart enough to
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000114 // prove that this is indeed the case. But the existance of the edge is enough to prove that
115 // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
116 // and FTL backends may emit checks in a node that lacks a valid exit origin.
117 m_graph.doToChildren(
118 node,
119 [&] (Edge& edge) {
120 if (mayHaveTypeCheck(edge.useKind()))
121 return;
122
123 filterEdgeByUse(edge);
124 });
125}
126
127template<typename AbstractStateType>
128void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
129{
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000130 if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
131 return;
132
fpizlo@apple.com97812a32014-10-04 17:18:25 +0000133 DFG_CRASH(m_graph, node, toCString("Edge verification error: ", node, "->", edge, " was expected to have type ", SpeculationDump(typeFilterFor(edge.useKind())), " but has type ", SpeculationDump(forNode(edge).m_type), " (", forNode(edge).m_type, ")").data());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000134}
135
oliver@apple.com55d32d92013-07-25 04:05:03 +0000136template<typename AbstractStateType>
137void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000138{
139 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
140}
141
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +0000142inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
143{
144 // We look at the type first since that will cover most cases and does not require iterating all the structures.
145 if (isStrictMode) {
146 if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
147 return true;
148 } else {
149 if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
150 return true;
151 }
152
153 if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
154 bool overridesToThis = false;
155 valueForNode.m_structure.forEach([&](Structure* structure) {
156 TypeInfo type = structure->typeInfo();
157 ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
158 if (!isStrictMode)
159 ASSERT(type.isObject());
160 // We don't need to worry about strings/symbols here since either:
161 // 1) We are in strict mode and strings/symbols are not wrapped
162 // 2) The AI has proven that the type of this is a subtype of object
163 if (type.isObject() && type.overridesToThis())
164 overridesToThis = true;
165 });
sbarati@apple.com1fcf9882016-07-07 22:15:04 +0000166 return !overridesToThis;
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +0000167 }
168
169 return false;
170}
171
oliver@apple.com55d32d92013-07-25 04:05:03 +0000172template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +0000173bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000174{
175 if (!ASSERT_DISABLED)
176 verifyEdges(node);
177
oliver@apple.com02e7a972013-07-25 04:05:04 +0000178 m_state.createValueForNode(node);
179
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000180 switch (node->op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000181 case JSConstant:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000182 case DoubleConstant:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000183 case Int52Constant: {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000184 setBuiltInConstant(node, *node->constant());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000185 break;
186 }
fpizlo@apple.com024424c2016-03-09 05:16:47 +0000187
188 case LazyJSConstant: {
189 LazyJSValue value = node->lazyJSValue();
190 switch (value.kind()) {
191 case LazyJSValue::KnownValue:
192 setConstant(node, value.value()->value());
193 break;
194 case LazyJSValue::SingleCharacterString:
195 case LazyJSValue::KnownStringImpl:
196 case LazyJSValue::NewStringImpl:
197 forNode(node).setType(m_graph, SpecString);
198 break;
199 }
200 break;
201 }
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000202
203 case Identity: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000204 forNode(node) = forNode(node->child1());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000205 if (forNode(node).value())
206 m_state.setFoundConstants(true);
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000207 break;
208 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000209
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000210 case ExtractOSREntryLocal: {
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000211 forNode(node).makeBytecodeTop();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000212 break;
213 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000214
215 case GetLocal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000216 VariableAccessData* variableAccessData = node->variableAccessData();
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000217 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000218 // The value in the local should already be checked.
219 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000220 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000221 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000222 forNode(node) = value;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000223 break;
224 }
225
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000226 case GetStack: {
227 StackAccessData* data = node->stackAccessData();
228 AbstractValue value = m_state.variables().operand(data->local);
229 // The value in the local should already be checked.
230 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
231 if (value.value())
232 m_state.setFoundConstants(true);
233 forNode(node) = value;
234 break;
235 }
236
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000237 case GetLocalUnlinked: {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000238 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000239 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000240 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000241 forNode(node) = value;
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000242 break;
243 }
244
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000245 case SetLocal: {
246 m_state.variables().operand(node->local()) = forNode(node->child1());
247 break;
248 }
249
250 case PutStack: {
251 m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000252 break;
253 }
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000254
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000255 case MovHint: {
256 // Don't need to do anything. A MovHint only informs us about what would have happened
257 // in bytecode, but this code is just concerned with what is actually happening during
258 // DFG execution.
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000259 break;
260 }
261
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000262 case KillStack: {
fpizlo@apple.com832490a2014-10-01 20:12:11 +0000263 // This is just a hint telling us that the OSR state of the local is no longer inside the
264 // flushed data.
265 break;
266 }
267
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000268 case SetArgument:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000269 // Assert that the state of arguments has been set. SetArgument means that someone set
270 // the argument values out-of-band, and currently this always means setting to a
271 // non-clear value.
272 ASSERT(!m_state.variables().operand(node->local()).isClear());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000273 break;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000274
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000275 case LoadVarargs:
276 case ForwardVarargs: {
277 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
278 // itself into a straight-line sequence of GetStack/PutStack.
279 // https://bugs.webkit.org/show_bug.cgi?id=143071
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000280 clobberWorld(node->origin.semantic, clobberLimit);
281 LoadVarargsData* data = node->loadVarargsData();
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000282 m_state.variables().operand(data->count).setType(SpecInt32Only);
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000283 for (unsigned i = data->limit - 1; i--;)
284 m_state.variables().operand(data->start.offset() + i).makeHeapTop();
285 break;
286 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000287
288 case BitAnd:
289 case BitOr:
290 case BitXor:
291 case BitRShift:
292 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000293 case BitURShift: {
mark.lam@apple.comc0008652015-12-15 21:19:31 +0000294 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
295 clobberWorld(node->origin.semantic, clobberLimit);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000296 forNode(node).setType(m_graph, SpecInt32Only);
mark.lam@apple.comc0008652015-12-15 21:19:31 +0000297 break;
298 }
299
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000300 JSValue left = forNode(node->child1()).value();
301 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000302 if (left && right && left.isInt32() && right.isInt32()) {
303 int32_t a = left.asInt32();
304 int32_t b = right.asInt32();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000305 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000306 case BitAnd:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000307 setConstant(node, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000308 break;
309 case BitOr:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000310 setConstant(node, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000311 break;
312 case BitXor:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000313 setConstant(node, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000314 break;
315 case BitRShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000316 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000317 break;
318 case BitLShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000319 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000320 break;
321 case BitURShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000322 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000323 break;
324 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000325 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000326 break;
327 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000328 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000329 }
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000330
331 if (node->op() == BitAnd
332 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
333 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
334 forNode(node).setType(SpecBoolInt32);
335 break;
336 }
337
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000338 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000339 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000340 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000341
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000342 case UInt32ToNumber: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000343 JSValue child = forNode(node->child1()).value();
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000344 if (doesOverflow(node->arithMode())) {
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000345 if (enableInt52()) {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000346 if (child && child.isAnyInt()) {
commit-queue@webkit.org1f3678b2016-04-26 04:08:22 +0000347 int64_t machineInt = child.asAnyInt();
348 setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000349 break;
350 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000351 forNode(node).setType(SpecAnyInt);
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000352 break;
353 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000354 if (child && child.isInt32()) {
355 uint32_t value = child.asInt32();
356 setConstant(node, jsNumber(value));
357 break;
358 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000359 forNode(node).setType(SpecAnyIntAsDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000360 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000361 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000362 if (child && child.isInt32()) {
363 int32_t value = child.asInt32();
364 if (value >= 0) {
365 setConstant(node, jsNumber(value));
366 break;
367 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000368 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000369 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000370 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000371 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000372
373 case BooleanToNumber: {
374 JSValue concreteValue = forNode(node->child1()).value();
375 if (concreteValue) {
376 if (concreteValue.isBoolean())
377 setConstant(node, jsNumber(concreteValue.asBoolean()));
378 else
fpizlo@apple.comf8cb6182015-02-23 18:03:49 +0000379 setConstant(node, *m_graph.freeze(concreteValue));
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000380 break;
381 }
382 AbstractValue& value = forNode(node);
383 value = forNode(node->child1());
384 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
385 m_state.setFoundConstants(true);
386 if (value.m_type & SpecBoolean) {
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000387 value.merge(SpecBoolInt32);
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000388 value.filter(~SpecBoolean);
389 }
390 break;
391 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000392
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000393 case DoubleAsInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000394 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000395 if (child && child.isNumber()) {
396 double asDouble = child.asNumber();
397 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000398 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
399 setConstant(node, JSValue(asInt));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000400 break;
401 }
402 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000403 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000404 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000405 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000406
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000407 case ValueToInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000408 JSValue child = forNode(node->child1()).value();
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000409 if (child) {
410 if (child.isNumber()) {
411 if (child.isInt32())
412 setConstant(node, child);
413 else
414 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
415 break;
416 }
417 if (child.isBoolean()) {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000418 setConstant(node, jsNumber(child.asBoolean()));
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000419 break;
420 }
fpizlo@apple.com29594fe2014-03-21 00:32:37 +0000421 if (child.isUndefinedOrNull()) {
422 setConstant(node, jsNumber(0));
423 break;
424 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000425 }
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000426
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000427 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
428 forNode(node).setType(SpecBoolInt32);
429 break;
430 }
431
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000432 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000433 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000434 }
oliver@apple.com500b53a2013-07-25 04:05:25 +0000435
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000436 case DoubleRep: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000437 JSValue child = forNode(node->child1()).value();
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000438 if (std::optional<double> number = child.toNumberFromPrimitive()) {
commit-queue@webkit.org7936e482016-08-25 23:02:52 +0000439 setConstant(node, jsDoubleNumber(*number));
440 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000441 }
benjamin@webkit.orgbf928092015-05-28 01:30:58 +0000442
443 SpeculatedType type = forNode(node->child1()).m_type;
444 switch (node->child1().useKind()) {
445 case NotCellUse: {
446 if (type & SpecOther) {
447 type &= ~SpecOther;
448 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
449 }
450 if (type & SpecBoolean) {
451 type &= ~SpecBoolean;
452 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
453 }
454 type &= SpecBytecodeNumber;
455 break;
456 }
457
458 case Int52RepUse:
459 case NumberUse:
fpizlo@apple.com318af072015-06-05 04:59:28 +0000460 case RealNumberUse:
benjamin@webkit.orgbf928092015-05-28 01:30:58 +0000461 break;
462
463 default:
464 RELEASE_ASSERT_NOT_REACHED();
465 }
466 forNode(node).setType(type);
fpizlo@apple.com12381022015-05-13 23:57:17 +0000467 forNode(node).fixTypeForRepresentation(m_graph, node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000468 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000469 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000470
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000471 case Int52Rep: {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000472 JSValue child = forNode(node->child1()).value();
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000473 if (child && child.isAnyInt()) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000474 setConstant(node, child);
475 break;
476 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000477
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000478 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000479 break;
480 }
481
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000482 case ValueRep: {
483 JSValue value = forNode(node->child1()).value();
484 if (value) {
485 setConstant(node, value);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000486 break;
487 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000488
fpizlo@apple.combaac2b92015-04-29 15:55:54 +0000489 forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
fpizlo@apple.com12381022015-05-13 23:57:17 +0000490 forNode(node).fixTypeForRepresentation(m_graph, node);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000491 break;
492 }
493
fpizlo@apple.com97756552014-01-02 20:15:25 +0000494 case ValueAdd: {
fpizlo@apple.com97756552014-01-02 20:15:25 +0000495 ASSERT(node->binaryUseKind() == UntypedUse);
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000496 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.combaac2b92015-04-29 15:55:54 +0000497 forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
fpizlo@apple.com97756552014-01-02 20:15:25 +0000498 break;
499 }
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +0000500
501 case StrCat: {
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +0000502 forNode(node).setType(m_graph, SpecString);
503 break;
504 }
fpizlo@apple.com97756552014-01-02 20:15:25 +0000505
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000506 case ArithAdd: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000507 JSValue left = forNode(node->child1()).value();
508 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000509 switch (node->binaryUseKind()) {
510 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000511 if (left && right && left.isInt32() && right.isInt32()) {
512 if (!shouldCheckOverflow(node->arithMode())) {
513 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
514 break;
515 }
516 JSValue result = jsNumber(left.asNumber() + right.asNumber());
517 if (result.isInt32()) {
518 setConstant(node, result);
519 break;
520 }
521 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000522 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000523 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000524 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000525 if (left && right && left.isAnyInt() && right.isAnyInt()) {
526 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
527 if (result.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000528 setConstant(node, result);
529 break;
530 }
531 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000532 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000533 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000534 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000535 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000536 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000537 break;
538 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000539 forNode(node).setType(
540 typeOfDoubleSum(
541 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000542 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000543 default:
fpizlo@apple.com97756552014-01-02 20:15:25 +0000544 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000545 break;
546 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000547 break;
548 }
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000549
550 case ArithClz32: {
551 JSValue operand = forNode(node->child1()).value();
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000552 if (std::optional<double> number = operand.toNumberFromPrimitive()) {
commit-queue@webkit.org95f28be2016-09-06 21:54:11 +0000553 uint32_t value = toUInt32(*number);
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000554 setConstant(node, jsNumber(clz32(value)));
555 break;
556 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000557 forNode(node).setType(SpecInt32Only);
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000558 break;
559 }
560
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000561 case MakeRope: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000562 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000563 break;
564 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000565
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000566 case ArithSub: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000567 JSValue left = forNode(node->child1()).value();
568 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000569 switch (node->binaryUseKind()) {
570 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000571 if (left && right && left.isInt32() && right.isInt32()) {
572 if (!shouldCheckOverflow(node->arithMode())) {
573 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
574 break;
575 }
576 JSValue result = jsNumber(left.asNumber() - right.asNumber());
577 if (result.isInt32()) {
578 setConstant(node, result);
579 break;
580 }
581 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000582 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000583 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000584 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000585 if (left && right && left.isAnyInt() && right.isAnyInt()) {
586 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
587 if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000588 setConstant(node, result);
589 break;
590 }
591 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000592 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000593 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000594 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000595 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000596 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000597 break;
598 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000599 forNode(node).setType(
600 typeOfDoubleDifference(
601 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000602 break;
mark.lam@apple.com75249092015-10-16 23:26:14 +0000603 case UntypedUse:
mark.lam@apple.com39515722015-12-02 19:15:33 +0000604 clobberWorld(node->origin.semantic, clobberLimit);
605 forNode(node).setType(m_graph, SpecBytecodeNumber);
mark.lam@apple.com75249092015-10-16 23:26:14 +0000606 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000607 default:
608 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000609 break;
610 }
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000611 break;
612 }
613
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000614 case ArithNegate: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000615 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000616 switch (node->child1().useKind()) {
617 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000618 if (child && child.isInt32()) {
619 if (!shouldCheckOverflow(node->arithMode())) {
620 setConstant(node, jsNumber(-child.asInt32()));
621 break;
622 }
623 double doubleResult;
624 if (shouldCheckNegativeZero(node->arithMode()))
625 doubleResult = -child.asNumber();
626 else
627 doubleResult = 0 - child.asNumber();
628 JSValue valueResult = jsNumber(doubleResult);
629 if (valueResult.isInt32()) {
630 setConstant(node, valueResult);
631 break;
632 }
633 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000634 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000635 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000636 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000637 if (child && child.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000638 double doubleResult;
639 if (shouldCheckNegativeZero(node->arithMode()))
640 doubleResult = -child.asNumber();
641 else
642 doubleResult = 0 - child.asNumber();
643 JSValue valueResult = jsNumber(doubleResult);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000644 if (valueResult.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000645 setConstant(node, valueResult);
646 break;
647 }
648 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000649 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000650 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000651 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000652 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000653 setConstant(node, jsDoubleNumber(-child.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000654 break;
655 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000656 forNode(node).setType(
657 typeOfDoubleNegation(
658 forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000659 break;
660 default:
commit-queue@webkit.orgf59f0ed2016-10-15 02:19:16 +0000661 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
662 forNode(node).setType(SpecBytecodeNumber);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000663 break;
664 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000665 break;
666 }
667
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000668 case ArithMul: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000669 JSValue left = forNode(node->child1()).value();
670 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000671 switch (node->binaryUseKind()) {
672 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000673 if (left && right && left.isInt32() && right.isInt32()) {
674 if (!shouldCheckOverflow(node->arithMode())) {
675 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
676 break;
677 }
678 double doubleResult = left.asNumber() * right.asNumber();
679 if (!shouldCheckNegativeZero(node->arithMode()))
680 doubleResult += 0; // Sanitizes zero.
681 JSValue valueResult = jsNumber(doubleResult);
682 if (valueResult.isInt32()) {
683 setConstant(node, valueResult);
684 break;
685 }
686 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000687 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000688 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000689 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000690 if (left && right && left.isAnyInt() && right.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000691 double doubleResult = left.asNumber() * right.asNumber();
692 if (!shouldCheckNegativeZero(node->arithMode()))
693 doubleResult += 0;
694 JSValue valueResult = jsNumber(doubleResult);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000695 if (valueResult.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000696 setConstant(node, valueResult);
697 break;
698 }
699 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000700 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000701 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000702 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000703 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000704 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000705 break;
706 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000707 forNode(node).setType(
708 typeOfDoubleProduct(
709 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000710 break;
mark.lam@apple.com1d936142015-12-03 05:42:56 +0000711 case UntypedUse:
712 clobberWorld(node->origin.semantic, clobberLimit);
713 forNode(node).setType(m_graph, SpecBytecodeNumber);
714 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000715 default:
716 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000717 break;
718 }
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000719 break;
720 }
721
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000722 case ArithDiv: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000723 JSValue left = forNode(node->child1()).value();
724 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000725 switch (node->binaryUseKind()) {
726 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000727 if (left && right && left.isInt32() && right.isInt32()) {
728 double doubleResult = left.asNumber() / right.asNumber();
729 if (!shouldCheckOverflow(node->arithMode()))
730 doubleResult = toInt32(doubleResult);
731 else if (!shouldCheckNegativeZero(node->arithMode()))
732 doubleResult += 0; // Sanitizes zero.
733 JSValue valueResult = jsNumber(doubleResult);
734 if (valueResult.isInt32()) {
735 setConstant(node, valueResult);
736 break;
737 }
738 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000739 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000740 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000741 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000742 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000743 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000744 break;
745 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000746 forNode(node).setType(
747 typeOfDoubleQuotient(
748 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000749 break;
mark.lam@apple.com224ce4d2015-12-08 21:44:12 +0000750 case UntypedUse:
751 clobberWorld(node->origin.semantic, clobberLimit);
752 forNode(node).setType(m_graph, SpecBytecodeNumber);
753 break;
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000754 default:
755 RELEASE_ASSERT_NOT_REACHED();
756 break;
757 }
758 break;
759 }
760
761 case ArithMod: {
762 JSValue left = forNode(node->child1()).value();
763 JSValue right = forNode(node->child2()).value();
764 switch (node->binaryUseKind()) {
765 case Int32Use:
766 if (left && right && left.isInt32() && right.isInt32()) {
767 double doubleResult = fmod(left.asNumber(), right.asNumber());
768 if (!shouldCheckOverflow(node->arithMode()))
769 doubleResult = toInt32(doubleResult);
770 else if (!shouldCheckNegativeZero(node->arithMode()))
771 doubleResult += 0; // Sanitizes zero.
772 JSValue valueResult = jsNumber(doubleResult);
773 if (valueResult.isInt32()) {
774 setConstant(node, valueResult);
775 break;
776 }
777 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000778 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000779 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000780 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000781 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000782 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000783 break;
784 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000785 forNode(node).setType(
786 typeOfDoubleBinaryOp(
787 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000788 break;
789 default:
790 RELEASE_ASSERT_NOT_REACHED();
791 break;
792 }
793 break;
794 }
795
796 case ArithMin: {
797 JSValue left = forNode(node->child1()).value();
798 JSValue right = forNode(node->child2()).value();
799 switch (node->binaryUseKind()) {
800 case Int32Use:
801 if (left && right && left.isInt32() && right.isInt32()) {
802 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
803 break;
804 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000805 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000806 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000807 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000808 if (left && right && left.isNumber() && right.isNumber()) {
809 double a = left.asNumber();
810 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000811 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000812 break;
813 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000814 forNode(node).setType(
815 typeOfDoubleMinMax(
816 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000817 break;
818 default:
819 RELEASE_ASSERT_NOT_REACHED();
820 break;
821 }
822 break;
823 }
824
825 case ArithMax: {
826 JSValue left = forNode(node->child1()).value();
827 JSValue right = forNode(node->child2()).value();
828 switch (node->binaryUseKind()) {
829 case Int32Use:
830 if (left && right && left.isInt32() && right.isInt32()) {
831 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
832 break;
833 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000834 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000835 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000836 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000837 if (left && right && left.isNumber() && right.isNumber()) {
838 double a = left.asNumber();
839 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000840 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000841 break;
842 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000843 forNode(node).setType(
844 typeOfDoubleMinMax(
845 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000846 break;
847 default:
848 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000849 break;
850 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000851 break;
852 }
853
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000854 case ArithAbs: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000855 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000856 switch (node->child1().useKind()) {
857 case Int32Use:
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000858 if (std::optional<double> number = child.toNumberFromPrimitive()) {
commit-queue@webkit.org0ec71072016-08-29 07:21:04 +0000859 JSValue result = jsNumber(fabs(*number));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000860 if (result.isInt32()) {
861 setConstant(node, result);
862 break;
863 }
864 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000865 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000866 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000867 case DoubleRepUse:
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000868 if (std::optional<double> number = child.toNumberFromPrimitive()) {
commit-queue@webkit.org0ec71072016-08-29 07:21:04 +0000869 setConstant(node, jsDoubleNumber(fabs(*number)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000870 break;
871 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000872 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000873 break;
874 default:
commit-queue@webkit.org0ec71072016-08-29 07:21:04 +0000875 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
876 forNode(node).setType(SpecFullNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000877 break;
878 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000879 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000880 }
benjamin@webkit.org903025b2015-02-14 04:20:21 +0000881
882 case ArithPow: {
883 JSValue childY = forNode(node->child2()).value();
884 if (childY && childY.isNumber()) {
885 if (!childY.asNumber()) {
886 setConstant(node, jsDoubleNumber(1));
887 break;
888 }
889
890 JSValue childX = forNode(node->child1()).value();
891 if (childX && childX.isNumber()) {
892 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
893 break;
894 }
895 }
896 forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
897 break;
898 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000899
utatane.tea@gmail.comd2fca0a2015-12-15 03:51:42 +0000900 case ArithRandom: {
901 forNode(node).setType(m_graph, SpecDoubleReal);
902 break;
903 }
904
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000905 case ArithRound:
906 case ArithFloor:
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000907 case ArithCeil:
908 case ArithTrunc: {
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000909 JSValue operand = forNode(node->child1()).value();
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000910 if (std::optional<double> number = operand.toNumberFromPrimitive()) {
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000911 double roundedValue = 0;
912 if (node->op() == ArithRound)
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000913 roundedValue = jsRound(*number);
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000914 else if (node->op() == ArithFloor)
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000915 roundedValue = floor(*number);
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000916 else if (node->op() == ArithCeil)
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000917 roundedValue = ceil(*number);
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000918 else {
919 ASSERT(node->op() == ArithTrunc);
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000920 roundedValue = trunc(*number);
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000921 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000922
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000923 if (node->child1().useKind() == UntypedUse) {
924 setConstant(node, jsNumber(roundedValue));
925 break;
926 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000927 if (producesInteger(node->arithRoundingMode())) {
928 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
929 if (roundedValueAsInt32 == roundedValue) {
930 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
931 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
932 setConstant(node, jsNumber(roundedValueAsInt32));
933 break;
934 }
935 } else {
936 setConstant(node, jsNumber(roundedValueAsInt32));
937 break;
938 }
939 }
940 } else {
941 setConstant(node, jsDoubleNumber(roundedValue));
942 break;
943 }
944 }
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +0000945 if (node->child1().useKind() == DoubleRepUse) {
946 if (producesInteger(node->arithRoundingMode()))
947 forNode(node).setType(SpecInt32Only);
948 else if (node->child1().useKind() == DoubleRepUse)
949 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
950 } else {
951 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
952 forNode(node).setType(SpecFullNumber);
953 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000954 break;
955 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000956
commit-queue@webkit.org7936e482016-08-25 23:02:52 +0000957 case ArithSqrt:
958 executeDoubleUnaryOpEffects(node, sqrt);
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000959 break;
benjamin@webkit.org2b5682d2015-03-04 22:39:28 +0000960
commit-queue@webkit.org7936e482016-08-25 23:02:52 +0000961 case ArithFRound:
962 executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
benjamin@webkit.org2b5682d2015-03-04 22:39:28 +0000963 break;
commit-queue@webkit.org7936e482016-08-25 23:02:52 +0000964
965 case ArithSin:
966 executeDoubleUnaryOpEffects(node, sin);
967 break;
968
969 case ArithCos:
970 executeDoubleUnaryOpEffects(node, cos);
971 break;
972
utatane.tea@gmail.com9917d6a2016-09-12 22:01:13 +0000973 case ArithTan:
974 executeDoubleUnaryOpEffects(node, tan);
975 break;
976
commit-queue@webkit.org7936e482016-08-25 23:02:52 +0000977 case ArithLog:
978 executeDoubleUnaryOpEffects(node, log);
979 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000980
981 case LogicalNot: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000982 switch (booleanResult(node, forNode(node->child1()))) {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000983 case DefinitelyTrue:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000984 setConstant(node, jsBoolean(false));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000985 break;
986 case DefinitelyFalse:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000987 setConstant(node, jsBoolean(true));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000988 break;
989 default:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000990 forNode(node).setType(SpecBoolean);
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000991 break;
992 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000993 break;
994 }
keith_miller@apple.com32fbcb72016-04-13 00:37:52 +0000995
sbarati@apple.coma528ff02016-09-12 21:04:25 +0000996 case MapHash: {
997 if (JSValue key = forNode(node->child1()).value()) {
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000998 if (std::optional<uint32_t> hash = concurrentJSMapHash(key)) {
sbarati@apple.coma528ff02016-09-12 21:04:25 +0000999 // Although C++ code uses uint32_t for the hash, the closest type in DFG IR is Int32
1000 // and that's what MapHash returns. So, we have to cast to int32_t to avoid large
1001 // unsigned values becoming doubles. This casting between signed and unsigned
1002 // happens in the assembly code we emit when we don't constant fold this node.
1003 setConstant(node, jsNumber(static_cast<int32_t>(*hash)));
1004 break;
1005 }
1006 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00001007 forNode(node).setType(SpecInt32Only);
1008 break;
sbarati@apple.coma528ff02016-09-12 21:04:25 +00001009 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00001010
sbarati@apple.com527ebc22016-10-05 06:16:15 +00001011 case ToLowerCase: {
1012 forNode(node).setType(m_graph, SpecString);
1013 break;
1014 }
1015
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00001016 case LoadFromJSMapBucket:
1017 forNode(node).makeHeapTop();
1018 break;
1019
1020 case GetMapBucket:
1021 forNode(node).setType(m_graph, SpecCellOther);
1022 break;
1023
1024 case IsNonEmptyMapBucket:
1025 forNode(node).setType(SpecBoolean);
1026 break;
1027
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001028 case IsEmpty:
fpizlo@apple.com1d216892012-04-12 00:55:44 +00001029 case IsUndefined:
1030 case IsBoolean:
1031 case IsNumber:
fpizlo@apple.com1d216892012-04-12 00:55:44 +00001032 case IsObject:
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00001033 case IsObjectOrNull:
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001034 case IsFunction:
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001035 case IsCellWithType:
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001036 case IsTypedArrayView: {
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001037 AbstractValue child = forNode(node->child1());
1038 if (child.value()) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001039 bool constantWasSet = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001040 switch (node->op()) {
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001041 case IsCellWithType:
1042 setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001043 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001044 case IsUndefined:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001045 setConstant(node, jsBoolean(
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001046 child.value().isCell()
1047 ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1048 : child.value().isUndefined()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001049 break;
1050 case IsBoolean:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001051 setConstant(node, jsBoolean(child.value().isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001052 break;
1053 case IsNumber:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001054 setConstant(node, jsBoolean(child.value().isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001055 break;
oliver@apple.come722ad02013-01-09 02:37:29 +00001056 case IsObject:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001057 setConstant(node, jsBoolean(child.value().isObject()));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00001058 break;
1059 case IsObjectOrNull:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001060 if (child.value().isObject()) {
1061 JSObject* object = asObject(child.value());
1062 if (object->type() == JSFunctionType)
1063 setConstant(node, jsBoolean(false));
1064 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1065 setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1066 else {
1067 // FIXME: This could just call getCallData.
1068 // https://bugs.webkit.org/show_bug.cgi?id=144457
1069 constantWasSet = false;
1070 }
1071 } else
1072 setConstant(node, jsBoolean(child.value().isNull()));
1073 break;
1074 case IsFunction:
1075 if (child.value().isObject()) {
1076 JSObject* object = asObject(child.value());
1077 if (object->type() == JSFunctionType)
1078 setConstant(node, jsBoolean(true));
1079 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1080 setConstant(node, jsBoolean(false));
1081 else {
1082 // FIXME: This could just call getCallData.
1083 // https://bugs.webkit.org/show_bug.cgi?id=144457
1084 constantWasSet = false;
1085 }
1086 } else
1087 setConstant(node, jsBoolean(false));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001088 break;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001089 case IsEmpty:
1090 setConstant(node, jsBoolean(child.value().isEmpty()));
1091 break;
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001092 case IsTypedArrayView:
1093 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo()->typedArrayStorageType)));
1094 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001095 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +00001096 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001097 break;
1098 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001099 if (constantWasSet)
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001100 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001101 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001102
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001103 // FIXME: This code should really use AbstractValue::isType() and
1104 // AbstractValue::couldBeType().
1105 // https://bugs.webkit.org/show_bug.cgi?id=146870
1106
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001107 bool constantWasSet = false;
1108 switch (node->op()) {
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001109 case IsEmpty: {
1110 if (child.m_type && !(child.m_type & SpecEmpty)) {
1111 setConstant(node, jsBoolean(false));
1112 constantWasSet = true;
1113 break;
1114 }
1115
1116 if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1117 setConstant(node, jsBoolean(true));
1118 constantWasSet = true;
1119 break;
1120 }
1121
1122 break;
1123 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001124 case IsUndefined:
1125 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1126 // https://bugs.webkit.org/show_bug.cgi?id=144456
1127
1128 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1129 setConstant(node, jsBoolean(false));
1130 constantWasSet = true;
1131 break;
1132 }
1133
1134 break;
1135 case IsBoolean:
1136 if (!(child.m_type & ~SpecBoolean)) {
1137 setConstant(node, jsBoolean(true));
1138 constantWasSet = true;
1139 break;
1140 }
1141
1142 if (!(child.m_type & SpecBoolean)) {
1143 setConstant(node, jsBoolean(false));
1144 constantWasSet = true;
1145 break;
1146 }
1147
1148 break;
1149 case IsNumber:
1150 if (!(child.m_type & ~SpecFullNumber)) {
1151 setConstant(node, jsBoolean(true));
1152 constantWasSet = true;
1153 break;
1154 }
1155
1156 if (!(child.m_type & SpecFullNumber)) {
1157 setConstant(node, jsBoolean(false));
1158 constantWasSet = true;
1159 break;
1160 }
1161
1162 break;
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001163 case IsObject:
1164 if (!(child.m_type & ~SpecObject)) {
1165 setConstant(node, jsBoolean(true));
1166 constantWasSet = true;
1167 break;
1168 }
1169
1170 if (!(child.m_type & SpecObject)) {
1171 setConstant(node, jsBoolean(false));
1172 constantWasSet = true;
1173 break;
1174 }
1175
1176 break;
1177 case IsObjectOrNull:
1178 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1179 // https://bugs.webkit.org/show_bug.cgi?id=144456
1180
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001181 // These expressions are complicated to parse. A helpful way to parse this is that
1182 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1183 // disjoint set from S". Things like "T - S" means that, provided that S is a
1184 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1185 // mean the "union of T and S".
1186
1187 // Is the child's type an object that isn't an other-object (i.e. object that could
1188 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1189 // this to true.
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001190 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1191 setConstant(node, jsBoolean(true));
1192 constantWasSet = true;
1193 break;
1194 }
1195
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001196 // Is the child's type definitely not either of: an object that isn't a function,
1197 // or either undefined or null? Then: we should fold this to false. This means
1198 // for example that if it's any non-function object, including those that have
1199 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1200 // if it's undefined-or-null, since the type bits don't distinguish between
1201 // undefined (which should fold to false) and null (which should fold to true).
1202 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001203 setConstant(node, jsBoolean(false));
1204 constantWasSet = true;
1205 break;
1206 }
1207
1208 break;
1209 case IsFunction:
1210 if (!(child.m_type & ~SpecFunction)) {
1211 setConstant(node, jsBoolean(true));
1212 constantWasSet = true;
1213 break;
1214 }
1215
1216 if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
1217 setConstant(node, jsBoolean(false));
1218 constantWasSet = true;
1219 break;
1220 }
1221 break;
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001222
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001223 case IsCellWithType:
1224 if (!(child.m_type & ~node->speculatedTypeForQuery())) {
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001225 setConstant(node, jsBoolean(true));
1226 constantWasSet = true;
1227 break;
1228 }
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001229 if (!(child.m_type & node->speculatedTypeForQuery())) {
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001230 setConstant(node, jsBoolean(false));
1231 constantWasSet = true;
1232 break;
1233 }
1234 break;
1235
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001236 case IsTypedArrayView:
1237 if (!(child.m_type & ~SpecTypedArrayView)) {
1238 setConstant(node, jsBoolean(true));
1239 constantWasSet = true;
1240 break;
1241 }
1242 if (!(child.m_type & SpecTypedArrayView)) {
1243 setConstant(node, jsBoolean(false));
1244 constantWasSet = true;
1245 break;
1246 }
1247 break;
1248
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001249 default:
1250 break;
1251 }
1252 if (constantWasSet)
1253 break;
1254
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001255 forNode(node).setType(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +00001256 break;
1257 }
oliver@apple.come722ad02013-01-09 02:37:29 +00001258
1259 case TypeOf: {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001260 VM* vm = m_codeBlock->vm();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001261 JSValue child = forNode(node->child1()).value();
1262 AbstractValue& abstractChild = forNode(node->child1());
oliver@apple.come722ad02013-01-09 02:37:29 +00001263 if (child) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001264 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001265 setConstant(node, *m_graph.freeze(typeString));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001266 break;
1267 }
1268
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001269 if (isFullNumberSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001270 setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001271 break;
1272 }
1273
1274 if (isStringSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001275 setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001276 break;
1277 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001278
1279 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1280 // https://bugs.webkit.org/show_bug.cgi?id=144456
sbarati@apple.com0004bde2016-03-31 18:28:48 +00001281 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001282 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001283 break;
1284 }
1285
1286 if (isFunctionSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001287 setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001288 break;
1289 }
1290
1291 if (isBooleanSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001292 setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001293 break;
fpizlo@apple.comcd81b572013-02-11 21:39:35 +00001294 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001295
utatane.tea@gmail.com23c2df72015-05-14 17:36:12 +00001296 if (isSymbolSpeculation(abstractChild.m_type)) {
1297 setConstant(node, *m_graph.freeze(vm->smallStrings.symbolString()));
1298 break;
1299 }
1300
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001301 forNode(node).setType(m_graph, SpecStringIdent);
oliver@apple.come722ad02013-01-09 02:37:29 +00001302 break;
1303 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001304
1305 case CompareLess:
1306 case CompareLessEq:
1307 case CompareGreater:
1308 case CompareGreaterEq:
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001309 case CompareEq: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001310 JSValue leftConst = forNode(node->child1()).value();
1311 JSValue rightConst = forNode(node->child2()).value();
oliver@apple.combd15be82013-07-25 04:03:42 +00001312 if (leftConst && rightConst) {
1313 if (leftConst.isNumber() && rightConst.isNumber()) {
1314 double a = leftConst.asNumber();
1315 double b = rightConst.asNumber();
1316 switch (node->op()) {
1317 case CompareLess:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001318 setConstant(node, jsBoolean(a < b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001319 break;
1320 case CompareLessEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001321 setConstant(node, jsBoolean(a <= b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001322 break;
1323 case CompareGreater:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001324 setConstant(node, jsBoolean(a > b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001325 break;
1326 case CompareGreaterEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001327 setConstant(node, jsBoolean(a >= b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001328 break;
1329 case CompareEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001330 setConstant(node, jsBoolean(a == b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001331 break;
1332 default:
1333 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001334 break;
1335 }
1336 break;
1337 }
1338
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00001339 if (leftConst.isString() && rightConst.isString()) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001340 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1341 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1342 if (a && b) {
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00001343 bool result;
1344 if (node->op() == CompareEq)
1345 result = WTF::equal(a, b);
1346 else if (node->op() == CompareLess)
1347 result = codePointCompare(a, b) < 0;
1348 else if (node->op() == CompareLessEq)
1349 result = codePointCompare(a, b) <= 0;
1350 else if (node->op() == CompareGreater)
1351 result = codePointCompare(a, b) > 0;
1352 else if (node->op() == CompareGreaterEq)
1353 result = codePointCompare(a, b) >= 0;
1354 else
1355 RELEASE_ASSERT_NOT_REACHED();
1356 setConstant(node, jsBoolean(result));
oliver@apple.combd15be82013-07-25 04:03:42 +00001357 break;
1358 }
1359 }
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001360
1361 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00001362 setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001363 break;
1364 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +00001365 }
1366
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001367 if (node->op() == CompareEq) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001368 SpeculatedType leftType = forNode(node->child1()).m_type;
1369 SpeculatedType rightType = forNode(node->child2()).m_type;
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001370 if (!valuesCouldBeEqual(leftType, rightType)) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001371 setConstant(node, jsBoolean(false));
1372 break;
1373 }
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001374
1375 if (leftType == SpecOther)
1376 std::swap(leftType, rightType);
1377 if (rightType == SpecOther) {
1378 // Undefined and Null are always equal when compared to eachother.
1379 if (!(leftType & ~SpecOther)) {
1380 setConstant(node, jsBoolean(true));
1381 break;
1382 }
1383
1384 // Any other type compared to Null or Undefined is always false
1385 // as long as the MasqueradesAsUndefined watchpoint is valid.
1386 //
1387 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1388 // cases are always "false".
1389 if (!(leftType & (SpecObjectOther | SpecOther))) {
1390 setConstant(node, jsBoolean(false));
1391 break;
1392 }
1393
1394 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1395 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1396 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1397 setConstant(node, jsBoolean(false));
1398 break;
1399 }
1400 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001401 }
1402
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001403 if (node->child1() == node->child2()) {
1404 if (node->isBinaryUseKind(Int32Use) ||
1405 node->isBinaryUseKind(Int52RepUse) ||
1406 node->isBinaryUseKind(StringUse) ||
1407 node->isBinaryUseKind(BooleanUse) ||
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001408 node->isBinaryUseKind(SymbolUse) ||
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001409 node->isBinaryUseKind(StringIdentUse) ||
1410 node->isBinaryUseKind(ObjectUse) ||
1411 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1412 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1413 switch (node->op()) {
1414 case CompareLess:
1415 case CompareGreater:
1416 setConstant(node, jsBoolean(false));
1417 break;
1418 case CompareLessEq:
1419 case CompareGreaterEq:
1420 case CompareEq:
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001421 setConstant(node, jsBoolean(true));
1422 break;
1423 default:
1424 DFG_CRASH(m_graph, node, "Unexpected node type");
1425 break;
1426 }
1427 break;
1428 }
1429 }
1430
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001431 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001432 break;
1433 }
1434
fpizlo@apple.com312efcd2014-03-10 22:11:35 +00001435 case CompareStrictEq: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001436 Node* leftNode = node->child1().node();
1437 Node* rightNode = node->child2().node();
1438 JSValue left = forNode(leftNode).value();
1439 JSValue right = forNode(rightNode).value();
oliver@apple.combd15be82013-07-25 04:03:42 +00001440 if (left && right) {
oliver@apple.combd15be82013-07-25 04:03:42 +00001441 if (left.isString() && right.isString()) {
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001442 // We need this case because JSValue::strictEqual is otherwise too racy for
1443 // string comparisons.
oliver@apple.combd15be82013-07-25 04:03:42 +00001444 const StringImpl* a = asString(left)->tryGetValueImpl();
1445 const StringImpl* b = asString(right)->tryGetValueImpl();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001446 if (a && b) {
1447 setConstant(node, jsBoolean(WTF::equal(a, b)));
oliver@apple.combd15be82013-07-25 04:03:42 +00001448 break;
1449 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001450 } else {
1451 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1452 break;
oliver@apple.combd15be82013-07-25 04:03:42 +00001453 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001454 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001455
1456 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1457 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1458 if (!(leftLUB & rightLUB)) {
1459 setConstant(node, jsBoolean(false));
1460 break;
1461 }
1462
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001463 if (node->child1() == node->child2()) {
1464 if (node->isBinaryUseKind(BooleanUse) ||
1465 node->isBinaryUseKind(Int32Use) ||
1466 node->isBinaryUseKind(Int52RepUse) ||
1467 node->isBinaryUseKind(StringUse) ||
1468 node->isBinaryUseKind(StringIdentUse) ||
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001469 node->isBinaryUseKind(SymbolUse) ||
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001470 node->isBinaryUseKind(ObjectUse) ||
1471 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1472 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1473 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1474 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1475 node->isBinaryUseKind(StringUse, UntypedUse) ||
1476 node->isBinaryUseKind(UntypedUse, StringUse)) {
1477 setConstant(node, jsBoolean(true));
1478 break;
1479 }
1480 }
1481
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001482 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001483 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001484 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001485
fpizlo@apple.com4077f612016-07-18 19:12:57 +00001486 case CompareEqPtr: {
1487 Node* childNode = node->child1().node();
1488 JSValue childValue = forNode(childNode).value();
1489 if (childValue) {
1490 setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
1491 break;
1492 }
1493
1494 forNode(node).setType(SpecBoolean);
1495 break;
1496 }
1497
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001498 case StringCharCodeAt:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001499 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001500 break;
1501
mark.lam@apple.com03a3e382016-01-08 18:44:36 +00001502 case StringFromCharCode:
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001503 forNode(node).setType(m_graph, SpecString);
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +00001504 break;
1505
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001506 case StringCharAt:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001507 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001508 break;
1509
1510 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001511 switch (node->arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001512 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +00001513 case Array::Unprofiled:
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00001514 case Array::SelectUsingArguments:
oliver@apple.com5598c182013-01-23 22:25:07 +00001515 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001516 break;
1517 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001518 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001519 break;
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00001520 case Array::Undecided: {
1521 JSValue index = forNode(node->child2()).value();
1522 if (index && index.isInt32() && index.asInt32() >= 0) {
1523 setConstant(node, jsUndefined());
1524 break;
1525 }
1526 forNode(node).setType(SpecOther);
1527 break;
1528 }
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001529 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001530 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001531 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001532 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001533 case Array::String:
oliver@apple.com211b3be2013-07-25 04:03:39 +00001534 if (node->arrayMode().isOutOfBounds()) {
1535 // If the watchpoint was still valid we could totally set this to be
1536 // SpecString | SpecOther. Except that we'd have to be careful. If we
1537 // tested the watchpoint state here then it could change by the time
1538 // we got to the backend. So to do this right, we'd have to get the
1539 // fixup phase to check the watchpoint state and then bake into the
1540 // GetByVal operation the fact that we're using a watchpoint, using
1541 // something like Array::SaneChain (except not quite, because that
1542 // implies an in-bounds access). None of this feels like it's worth it,
oliver@apple.come6427742013-07-25 04:05:12 +00001543 // so we're going with TOP for now. The same thing applies to
1544 // clobbering the world.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001545 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001546 forNode(node).makeHeapTop();
oliver@apple.com211b3be2013-07-25 04:03:39 +00001547 } else
1548 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001549 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001550 case Array::DirectArguments:
1551 case Array::ScopedArguments:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001552 forNode(node).makeHeapTop();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001553 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001554 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001555 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001556 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001557 forNode(node).makeHeapTop();
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001558 } else
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001559 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001560 break;
1561 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001562 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001563 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001564 forNode(node).makeHeapTop();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001565 } else if (node->arrayMode().isSaneChain())
fpizlo@apple.combeef4522014-04-16 22:44:00 +00001566 forNode(node).setType(SpecBytecodeDouble);
fpizlo@apple.com94e84e92012-11-11 02:56:12 +00001567 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001568 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001569 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001570 case Array::Contiguous:
1571 case Array::ArrayStorage:
1572 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001573 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001574 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001575 forNode(node).makeHeapTop();
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +00001576 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001577 case Array::Int8Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001578 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001579 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001580 case Array::Int16Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001581 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001582 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001583 case Array::Int32Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001584 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001585 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001586 case Array::Uint8Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001587 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001588 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001589 case Array::Uint8ClampedArray:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001590 forNode(node).setType(SpecInt32Only);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001591 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001592 case Array::Uint16Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001593 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001594 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001595 case Array::Uint32Array:
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001596 if (node->shouldSpeculateInt32())
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001597 forNode(node).setType(SpecInt32Only);
1598 else if (enableInt52() && node->shouldSpeculateAnyInt())
1599 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com691ac792012-03-13 22:59:43 +00001600 else
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001601 forNode(node).setType(SpecAnyIntAsDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001602 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001603 case Array::Float32Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001604 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001605 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001606 case Array::Float64Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001607 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001608 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001609 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001610 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001611 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001612 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001613 break;
1614 }
1615
oliver@apple.come050d642013-10-19 00:09:28 +00001616 case PutByValDirect:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001617 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001618 case PutByValAlias: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001619 switch (node->arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001620 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001621 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001622 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001623 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001624 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001625 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001626 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001627 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001628 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001629 break;
1630 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001631 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001632 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001633 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001634 case Array::Contiguous:
1635 case Array::ArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001636 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001637 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001638 break;
1639 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001640 if (node->arrayMode().mayStoreToHole())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001641 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001642 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001643 default:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001644 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001645 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001646 break;
1647 }
1648
1649 case ArrayPush:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001650 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001651 forNode(node).setType(SpecBytecodeNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001652 break;
1653
1654 case ArrayPop:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001655 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001656 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001657 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001658
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001659 case GetMyArgumentByVal:
1660 case GetMyArgumentByValOutOfBounds: {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001661 JSValue index = forNode(node->child2()).m_value;
1662 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1663
1664 if (index && index.isInt32()) {
1665 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1666 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001667 // paths as unreachable, or to return undefined. We could implement that eventually.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001668
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001669 unsigned argumentIndex = index.asUInt32() + node->numberOfArgumentsToSkip();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001670 if (inlineCallFrame) {
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001671 if (argumentIndex < inlineCallFrame->arguments.size() - 1) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001672 forNode(node) = m_state.variables().operand(
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001673 virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001674 m_state.setFoundConstants(true);
1675 break;
1676 }
1677 } else {
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001678 if (argumentIndex < m_state.variables().numberOfArguments() - 1) {
1679 forNode(node) = m_state.variables().argument(argumentIndex + 1);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001680 m_state.setFoundConstants(true);
1681 break;
1682 }
1683 }
1684 }
1685
1686 if (inlineCallFrame) {
1687 // We have a bound on the types even though it's random access. Take advantage of this.
1688
1689 AbstractValue result;
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001690 for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->arguments.size(); ++i) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001691 result.merge(
1692 m_state.variables().operand(
1693 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1694 }
1695
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001696 if (node->op() == GetMyArgumentByValOutOfBounds)
1697 result.merge(SpecOther);
1698
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001699 if (result.value())
1700 m_state.setFoundConstants(true);
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001701
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001702 forNode(node) = result;
1703 break;
1704 }
1705
1706 forNode(node).makeHeapTop();
1707 break;
1708 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001709
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001710 case RegExpExec:
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001711 if (node->child2().useKind() == RegExpObjectUse
1712 && node->child3().useKind() == StringUse) {
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00001713 // This doesn't clobber the world since there are no conversions to perform.
1714 } else
1715 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001716 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
1717 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(globalObjectValue)) {
1718 if (!globalObject->isHavingABadTime()) {
1719 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1720 Structure* structure = globalObject->regExpMatchesArrayStructure();
1721 m_graph.registerStructure(structure);
1722 forNode(node).set(m_graph, structure);
1723 forNode(node).merge(SpecOther);
1724 break;
1725 }
1726 }
1727 }
1728 forNode(node).setType(m_graph, SpecOther | SpecArray);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001729 break;
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001730
1731 case RegExpTest:
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001732 if (node->child2().useKind() == RegExpObjectUse
1733 && node->child3().useKind() == StringUse) {
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00001734 // This doesn't clobber the world since there are no conversions to perform.
1735 } else
1736 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.com67e0f332013-07-25 03:59:00 +00001737 forNode(node).setType(SpecBoolean);
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001738 break;
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001739
fpizlo@apple.come799b862016-03-01 21:18:42 +00001740 case StringReplace:
msaboff@apple.com69940442016-04-27 01:28:03 +00001741 case StringReplaceRegExp:
fpizlo@apple.come799b862016-03-01 21:18:42 +00001742 if (node->child1().useKind() == StringUse
1743 && node->child2().useKind() == RegExpObjectUse
1744 && node->child3().useKind() == StringUse) {
1745 // This doesn't clobber the world. It just reads and writes regexp state.
1746 } else
1747 clobberWorld(node->origin.semantic, clobberLimit);
1748 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1749 break;
1750
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001751 case Jump:
1752 break;
1753
1754 case Branch: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001755 Node* child = node->child1().node();
1756 BooleanResult result = booleanResult(node, forNode(child));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001757 if (result == DefinitelyTrue) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001758 m_state.setBranchDirection(TakeTrue);
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001759 break;
1760 }
1761 if (result == DefinitelyFalse) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001762 m_state.setBranchDirection(TakeFalse);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001763 break;
1764 }
1765 // FIXME: The above handles the trivial cases of sparse conditional
1766 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001767 // We can specialize the source variable's value on each direction of
1768 // the branch.
oliver@apple.com55d32d92013-07-25 04:05:03 +00001769 m_state.setBranchDirection(TakeBoth);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001770 break;
1771 }
oliver@apple.com9b7647b2013-07-25 04:03:00 +00001772
1773 case Switch: {
1774 // Nothing to do for now.
1775 // FIXME: Do sparse conditional things.
1776 break;
1777 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001778
1779 case Return:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001780 m_state.setIsValid(false);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001781 break;
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00001782
1783 case TailCall:
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00001784 case DirectTailCall:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00001785 case TailCallVarargs:
1786 case TailCallForwardVarargs:
1787 clobberWorld(node->origin.semantic, clobberLimit);
1788 m_state.setIsValid(false);
1789 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001790
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001791 case Throw:
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +00001792 case ThrowStaticError:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001793 m_state.setIsValid(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001794 break;
1795
1796 case ToPrimitive: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001797 JSValue childConst = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001798 if (childConst && childConst.isNumber()) {
1799 setConstant(node, childConst);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001800 break;
1801 }
1802
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001803 ASSERT(node->child1().useKind() == UntypedUse);
1804
utatane.tea@gmail.com23c2df72015-05-14 17:36:12 +00001805 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00001806 m_state.setFoundConstants(true);
1807 forNode(node) = forNode(node->child1());
1808 break;
1809 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001810
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001811 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001812
fpizlo@apple.com2b150e782015-08-27 23:59:57 +00001813 forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001814 break;
1815 }
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001816
1817 case ToNumber: {
1818 JSValue childConst = forNode(node->child1()).value();
1819 if (childConst && childConst.isNumber()) {
1820 setConstant(node, childConst);
1821 break;
1822 }
1823
1824 ASSERT(node->child1().useKind() == UntypedUse);
1825
1826 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
1827 m_state.setFoundConstants(true);
1828 forNode(node) = forNode(node->child1());
1829 break;
1830 }
1831
1832 clobberWorld(node->origin.semantic, clobberLimit);
1833 forNode(node).setType(m_graph, SpecBytecodeNumber);
1834 break;
1835 }
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001836
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +00001837 case ToString:
1838 case CallStringConstructor: {
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001839 switch (node->child1().useKind()) {
1840 case StringObjectUse:
1841 // This also filters that the StringObject has the primordial StringObject
1842 // structure.
oliver@apple.com33913872013-07-25 04:02:13 +00001843 filter(
1844 node->child1(),
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001845 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001846 break;
1847 case StringOrStringObjectUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001848 break;
1849 case CellUse:
1850 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001851 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001852 break;
1853 default:
1854 RELEASE_ASSERT_NOT_REACHED();
1855 break;
1856 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001857 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001858 break;
1859 }
1860
1861 case NewStringObject: {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001862 ASSERT(node->structure()->classInfo() == StringObject::info());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001863 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001864 break;
1865 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001866
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001867 case NewArray:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001868 forNode(node).set(
1869 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001870 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001871 break;
sbarati@apple.com99ed4792016-11-12 02:58:11 +00001872
1873 case NewArrayWithSpread:
1874 if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
1875 // We've compiled assuming we're not having a bad time, so to be consistent
1876 // with StructureRegisterationPhase we must say we produce an original array
1877 // allocation structure.
1878 forNode(node).set(
1879 m_graph,
1880 m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
1881 } else {
1882 forNode(node).set(
1883 m_graph,
1884 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
1885 }
1886
1887 break;
1888
1889 case Spread:
1890 forNode(node).set(
1891 m_graph, m_graph.m_vm.fixedArrayStructure.get());
1892 break;
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001893
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001894 case NewArrayBuffer:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001895 forNode(node).set(
1896 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001897 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001898 break;
1899
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001900 case NewArrayWithSize:
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001901 forNode(node).setType(m_graph, SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001902 break;
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001903
1904 case NewTypedArray:
1905 switch (node->child1().useKind()) {
1906 case Int32Use:
1907 break;
1908 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001909 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001910 break;
1911 default:
1912 RELEASE_ASSERT_NOT_REACHED();
1913 break;
1914 }
1915 forNode(node).set(
1916 m_graph,
fpizlo@apple.comcff2d0c2016-05-04 21:21:36 +00001917 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001918 node->typedArrayType()));
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001919 break;
fpizlo@apple.come799b862016-03-01 21:18:42 +00001920
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001921 case NewRegexp:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001922 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001923 break;
1924
oliver@apple.come2fe4ce2013-07-25 03:59:41 +00001925 case ToThis: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001926 AbstractValue& source = forNode(node->child1());
1927 AbstractValue& destination = forNode(node);
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001928 bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
utatane.tea@gmail.com44616d02016-01-31 23:05:10 +00001929
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001930 if (isToThisAnIdentity(strictMode, source)) {
utatane.tea@gmail.com44616d02016-01-31 23:05:10 +00001931 m_state.setFoundConstants(true);
1932 destination = source;
1933 break;
1934 }
1935
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001936 if (strictMode)
fpizlo@apple.com018818d2013-09-13 23:18:19 +00001937 destination.makeHeapTop();
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001938 else {
fpizlo@apple.com018818d2013-09-13 23:18:19 +00001939 destination = source;
1940 destination.merge(SpecObject);
1941 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001942 break;
1943 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001944
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001945 case CreateThis: {
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00001946 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001947 forNode(node).setType(m_graph, SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001948 break;
1949 }
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001950
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001951 case NewObject:
fpizlo@apple.com62203aa2013-12-03 22:24:53 +00001952 ASSERT(node->structure());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001953 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001954 break;
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001955
1956 case CallObjectConstructor: {
1957 AbstractValue& source = forNode(node->child1());
1958 AbstractValue& destination = forNode(node);
1959
1960 if (!(source.m_type & ~SpecObject)) {
1961 m_state.setFoundConstants(true);
1962 destination = source;
1963 break;
1964 }
1965
1966 forNode(node).setType(m_graph, SpecObject);
1967 break;
1968 }
1969
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001970 case PhantomNewObject:
commit-queue@webkit.org88ab4e72015-04-24 02:23:36 +00001971 case PhantomNewFunction:
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00001972 case PhantomNewGeneratorFunction:
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00001973 case PhantomNewAsyncFunction:
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001974 case PhantomCreateActivation:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001975 case PhantomDirectArguments:
1976 case PhantomClonedArguments:
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001977 case PhantomCreateRest:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001978 case BottomValue:
1979 m_state.setDidClobber(true); // Prevent constant folding.
1980 // This claims to return bottom.
1981 break;
1982
fpizlo@apple.com8ff74712015-03-17 15:50:44 +00001983 case PutHint:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001984 break;
1985
1986 case MaterializeNewObject: {
sbarati@apple.comb67210c2016-09-06 23:51:24 +00001987 forNode(node).set(m_graph, node->structureSet());
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001988 break;
1989 }
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001990
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001991 case CreateActivation:
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001992 case MaterializeCreateActivation:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001993 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001994 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001995 break;
fpizlo@apple.com1a724092013-11-28 07:10:10 +00001996
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001997 case CreateDirectArguments:
1998 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001999 break;
2000
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002001 case CreateScopedArguments:
2002 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00002003 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002004
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002005 case CreateClonedArguments:
mark.lam@apple.comd3506e62016-11-04 06:18:01 +00002006 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2007 forNode(node).setType(m_graph, SpecObject);
2008 break;
2009 }
keith_miller@apple.com26367392016-03-14 20:55:15 +00002010 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00002011 break;
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00002012
2013 case NewGeneratorFunction:
2014 forNode(node).set(
2015 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
2016 break;
2017
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00002018 case NewAsyncFunction:
2019 forNode(node).set(
2020 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
2021 break;
2022
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002023 case NewFunction:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00002024 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002025 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002026 break;
2027
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002028 case GetCallee:
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00002029 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
2030 InferredValue* singleton = executable->singletonFunction();
2031 if (JSValue value = singleton->inferredValue()) {
2032 m_graph.watchpoints().addLazily(singleton);
2033 JSFunction* function = jsCast<JSFunction*>(value);
2034 setConstant(node, *m_graph.freeze(function));
2035 break;
2036 }
2037 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002038 forNode(node).setType(m_graph, SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002039 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002040
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +00002041 case GetArgumentCountIncludingThis:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002042 forNode(node).setType(SpecInt32Only);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002043 break;
2044
sbarati@apple.com855d5602015-11-30 20:36:54 +00002045 case GetRestLength:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002046 forNode(node).setType(SpecInt32Only);
sbarati@apple.com855d5602015-11-30 20:36:54 +00002047 break;
2048
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002049 case GetGetter: {
2050 JSValue base = forNode(node->child1()).m_value;
2051 if (base) {
msaboff@apple.com9a7dc802014-12-09 19:52:40 +00002052 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2053 if (!getterSetter->isGetterNull()) {
2054 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002055 break;
2056 }
2057 }
2058
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002059 forNode(node).setType(m_graph, SpecObject);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002060 break;
2061 }
2062
2063 case GetSetter: {
2064 JSValue base = forNode(node->child1()).m_value;
2065 if (base) {
msaboff@apple.com9a7dc802014-12-09 19:52:40 +00002066 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2067 if (!getterSetter->isSetterNull()) {
2068 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002069 break;
2070 }
2071 }
2072
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002073 forNode(node).setType(m_graph, SpecObject);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002074 break;
2075 }
2076
fpizlo@apple.com90640ab2015-03-04 05:26:54 +00002077 case GetScope:
2078 if (JSValue base = forNode(node->child1()).m_value) {
2079 if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
2080 setConstant(node, *m_graph.freeze(function->scope()));
2081 break;
2082 }
2083 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002084 forNode(node).setType(m_graph, SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002085 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00002086
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002087 case SkipScope: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002088 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00002089 if (child) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002090 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002091 break;
2092 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002093 forNode(node).setType(m_graph, SpecObjectOther);
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002094 break;
2095 }
2096
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00002097 case GetGlobalObject: {
2098 JSValue child = forNode(node->child1()).value();
2099 if (child) {
2100 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
2101 break;
2102 }
2103
2104 if (forNode(node->child1()).m_structure.isFinite()) {
2105 JSGlobalObject* globalObject = nullptr;
2106 bool ok = true;
2107 forNode(node->child1()).m_structure.forEach(
2108 [&] (Structure* structure) {
2109 if (!globalObject)
2110 globalObject = structure->globalObject();
2111 else if (globalObject != structure->globalObject())
2112 ok = false;
2113 });
2114 if (globalObject && ok) {
2115 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2116 break;
2117 }
2118 }
2119
2120 forNode(node).setType(m_graph, SpecObjectOther);
2121 break;
2122 }
2123
oliver@apple.com58c86752013-07-25 04:02:40 +00002124 case GetClosureVar:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002125 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
fpizlo@apple.com90640ab2015-03-04 05:26:54 +00002126 setConstant(node, *m_graph.freeze(value));
2127 break;
2128 }
commit-queue@webkit.org98686d02015-11-05 22:21:19 +00002129 forNode(node).makeBytecodeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002130 break;
2131
oliver@apple.com58c86752013-07-25 04:02:40 +00002132 case PutClosureVar:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002133 break;
fpizlo@apple.comef515142016-03-04 06:36:24 +00002134
2135 case GetRegExpObjectLastIndex:
2136 forNode(node).makeHeapTop();
2137 break;
2138
2139 case SetRegExpObjectLastIndex:
fpizlo@apple.com280ef002016-04-05 22:13:16 +00002140 case RecordRegExpCachedResult:
fpizlo@apple.comef515142016-03-04 06:36:24 +00002141 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002142
2143 case GetFromArguments:
2144 forNode(node).makeHeapTop();
2145 break;
2146
2147 case PutToArguments:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002148 break;
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002149
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +00002150 case GetArgument:
2151 forNode(node).makeHeapTop();
2152 break;
2153
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002154 case TryGetById:
2155 // FIXME: This should constant fold at least as well as the normal GetById case.
2156 // https://bugs.webkit.org/show_bug.cgi?id=156422
2157 forNode(node).makeHeapTop();
2158 break;
2159
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002160 case GetById:
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002161 case GetByIdFlush: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002162 if (!node->prediction()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002163 m_state.setIsValid(false);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00002164 break;
2165 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002166
2167 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002168 if (value.m_structure.isFinite()
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002169 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00002170 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2171 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002172 if (status.isSimple()) {
2173 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2174 // something more subtle?
2175 AbstractValue result;
2176 for (unsigned i = status.numVariants(); i--;) {
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00002177 // This thing won't give us a variant that involves prototypes. If it did, we'd
2178 // have more work to do here.
2179 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002180
2181 result.merge(
2182 m_graph.inferredValueForProperty(
2183 value, uid, status[i].offset(), m_state.structureClobberState()));
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002184 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002185 m_state.setFoundConstants(true);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002186 forNode(node) = result;
2187 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002188 }
2189 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002190
cdumez@apple.comc412c1d2016-11-11 16:50:57 +00002191 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002192 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002193 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002194 }
sbarati@apple.com23315d62016-05-09 20:17:23 +00002195
2196 case GetByValWithThis:
2197 case GetByIdWithThis:
2198 clobberWorld(node->origin.semantic, clobberLimit);
2199 forNode(node).makeHeapTop();
2200 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002201
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002202 case GetArrayLength: {
2203 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2204 forNode(node->child1()).m_value, node->arrayMode());
2205 if (view) {
2206 setConstant(node, jsNumber(view->length()));
2207 break;
2208 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002209 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002210 break;
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002211 }
keith_miller@apple.com485f5392016-04-18 20:02:24 +00002212
keith_miller@apple.com806e80d2016-05-05 17:30:02 +00002213 case DeleteById:
2214 case DeleteByVal: {
keith_miller@apple.com485f5392016-04-18 20:02:24 +00002215 // FIXME: This could decide if the delete will be successful based on the set of structures that
2216 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2217 clobberWorld(node->origin.semantic, clobberLimit);
2218 forNode(node).setType(SpecBoolean);
2219 break;
2220 }
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002221
oliver@apple.com500b53a2013-07-25 04:05:25 +00002222 case CheckStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002223 AbstractValue& value = forNode(node->child1());
oliver@apple.com33913872013-07-25 04:02:13 +00002224
2225 StructureSet& set = node->structureSet();
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002226
2227 // It's interesting that we could have proven that the object has a larger structure set
2228 // that includes the set we're testing. In that case we could make the structure check
2229 // more efficient. We currently don't.
2230
fpizlo@apple.com12835772015-09-21 20:49:04 +00002231 if (value.m_structure.isSubsetOf(set))
oliver@apple.com55d32d92013-07-25 04:05:03 +00002232 m_state.setFoundConstants(true);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002233
2234 SpeculatedType admittedTypes = SpecNone;
2235 switch (node->child1().useKind()) {
2236 case CellUse:
2237 case KnownCellUse:
2238 admittedTypes = SpecNone;
2239 break;
2240 case CellOrOtherUse:
2241 admittedTypes = SpecOther;
2242 break;
2243 default:
2244 DFG_CRASH(m_graph, node, "Bad use kind");
oliver@apple.com33913872013-07-25 04:02:13 +00002245 break;
2246 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002247
2248 filter(value, set, admittedTypes);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002249 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00002250 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00002251
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002252 case CheckStructureImmediate: {
2253 // FIXME: This currently can only reason about one structure at a time.
2254 // https://bugs.webkit.org/show_bug.cgi?id=136988
2255
2256 AbstractValue& value = forNode(node->child1());
2257 StructureSet& set = node->structureSet();
2258
2259 if (value.value()) {
2260 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
2261 if (set.contains(structure)) {
2262 m_state.setFoundConstants(true);
2263 break;
2264 }
2265 }
2266 m_state.setIsValid(false);
2267 break;
2268 }
2269
2270 if (m_phiChildren) {
2271 bool allGood = true;
2272 m_phiChildren->forAllTransitiveIncomingValues(
2273 node,
2274 [&] (Node* incoming) {
2275 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
2276 if (set.contains(structure))
2277 return;
2278 }
2279 allGood = false;
2280 });
2281 if (allGood) {
2282 m_state.setFoundConstants(true);
2283 break;
2284 }
2285 }
2286
2287 if (Structure* structure = set.onlyStructure()) {
2288 filterByValue(node->child1(), *m_graph.freeze(structure));
2289 break;
2290 }
2291
2292 // Aw shucks, we can't do anything!
2293 break;
2294 }
2295
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002296 case PutStructure:
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002297 if (!forNode(node->child1()).m_structure.isClear()) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002298 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
2299 m_state.setFoundConstants(true);
2300 else {
2301 observeTransition(
2302 clobberLimit, node->transition()->previous, node->transition()->next);
2303 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
2304 }
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00002305 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002306 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00002307 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00002308 case AllocatePropertyStorage:
2309 case ReallocatePropertyStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002310 forNode(node).clear(); // The result is not a JS value.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002311 break;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00002312 case CheckDOM: {
2313 JSValue constant = forNode(node->child1()).value();
2314 if (constant) {
2315 if (constant.isCell() && constant.asCell()->inherits(node->classInfo())) {
2316 m_state.setFoundConstants(true);
2317 ASSERT(constant);
2318 break;
2319 }
2320 }
2321
2322 AbstractValue& value = forNode(node->child1());
2323
2324 if (value.m_structure.isSubClassOf(node->classInfo()))
2325 m_state.setFoundConstants(true);
2326
2327 filterClassInfo(value, node->classInfo());
2328 break;
2329 }
utatane.tea@gmail.comc9d8f862016-10-28 22:57:10 +00002330 case CallDOMGetter: {
2331 CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
2332 DOMJIT::CallDOMGetterPatchpoint* patchpoint = callDOMGetterData->patchpoint;
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +00002333 if (patchpoint->effect.writes)
2334 clobberWorld(node->origin.semantic, clobberLimit);
utatane.tea@gmail.comc9d8f862016-10-28 22:57:10 +00002335 forNode(node).setType(m_graph, callDOMGetterData->domJIT->resultType());
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00002336 break;
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +00002337 }
utatane.tea@gmail.com0d74c7c2016-11-03 03:20:53 +00002338 case CallDOM: {
2339 const DOMJIT::Signature* signature = node->signature();
2340 if (signature->effect.writes)
2341 clobberWorld(node->origin.semantic, clobberLimit);
2342 forNode(node).setType(m_graph, signature->result);
2343 break;
2344 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002345 case CheckArray: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002346 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002347 m_state.setFoundConstants(true);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002348 break;
2349 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002350 switch (node->arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002351 case Array::String:
oliver@apple.com33913872013-07-25 04:02:13 +00002352 filter(node->child1(), SpecString);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002353 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002354 case Array::Int32:
2355 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00002356 case Array::Contiguous:
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00002357 case Array::Undecided:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00002358 case Array::ArrayStorage:
2359 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002360 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002361 case Array::DirectArguments:
2362 filter(node->child1(), SpecDirectArguments);
2363 break;
2364 case Array::ScopedArguments:
2365 filter(node->child1(), SpecScopedArguments);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002366 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002367 case Array::Int8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002368 filter(node->child1(), SpecInt8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002369 break;
2370 case Array::Int16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002371 filter(node->child1(), SpecInt16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002372 break;
2373 case Array::Int32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002374 filter(node->child1(), SpecInt32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002375 break;
2376 case Array::Uint8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002377 filter(node->child1(), SpecUint8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002378 break;
2379 case Array::Uint8ClampedArray:
oliver@apple.com33913872013-07-25 04:02:13 +00002380 filter(node->child1(), SpecUint8ClampedArray);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002381 break;
2382 case Array::Uint16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002383 filter(node->child1(), SpecUint16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002384 break;
2385 case Array::Uint32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002386 filter(node->child1(), SpecUint32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002387 break;
2388 case Array::Float32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002389 filter(node->child1(), SpecFloat32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002390 break;
2391 case Array::Float64Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002392 filter(node->child1(), SpecFloat64Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002393 break;
keith_miller@apple.com59bba5d2015-10-16 22:18:42 +00002394 case Array::AnyTypedArray:
2395 filter(node->child1(), SpecTypedArrayView);
2396 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002397 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002398 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00002399 break;
2400 }
oliver@apple.com52be8f82013-07-25 04:04:33 +00002401 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002402 break;
2403 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00002404 case Arrayify: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002405 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002406 m_state.setFoundConstants(true);
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00002407 break;
2408 }
benjamin@webkit.org9f46ddc2015-04-30 04:40:55 +00002409 ASSERT(node->arrayMode().conversion() == Array::Convert);
oliver@apple.come17632e2013-07-25 04:05:31 +00002410 clobberStructures(clobberLimit);
oliver@apple.com33913872013-07-25 04:02:13 +00002411 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.com497c7512012-09-19 01:20:52 +00002412 break;
2413 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00002414 case ArrayifyToStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002415 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002416 if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
oliver@apple.com55d32d92013-07-25 04:05:03 +00002417 m_state.setFoundConstants(true);
oliver@apple.come17632e2013-07-25 04:05:31 +00002418 clobberStructures(clobberLimit);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002419
2420 // We have a bunch of options of how to express the abstract set at this point. Let set S
2421 // be the set of structures that the value had before clobbering and assume that all of
2422 // them are watchable. The new value should be the least expressible upper bound of the
2423 // intersection of "values that currently have structure = node->structure()" and "values
2424 // that have structure in S plus any structure transition-reachable from S". Assume that
2425 // node->structure() is not in S but it is transition-reachable from S. Then we would
2426 // like to say that the result is "values that have structure = node->structure() until
2427 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
2428 // we must choose between:
2429 //
2430 // 1) "values that currently have structure = node->structure()". This is a valid
2431 // superset of the value that we really want, and it's specific enough to satisfy the
2432 // preconditions of the array access that this is guarding. It's also specific enough
2433 // to allow relevant optimizations in the case that we didn't have a contradiction
2434 // like in this example. Notice that in the abscence of any contradiction, this result
2435 // is precise rather than being a conservative LUB.
2436 //
2437 // 2) "values that currently hava structure in S plus any structure transition-reachable
2438 // from S". This is also a valid superset of the value that we really want, but it's
2439 // not specific enough to satisfy the preconditions of the array access that this is
2440 // guarding - so playing such shenanigans would preclude us from having assertions on
2441 // the typing preconditions of any array accesses. This would also not be a desirable
2442 // answer in the absence of a contradiction.
2443 //
2444 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
2445 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
2446 // yet.
2447 value.set(m_graph, node->structure());
fpizlo@apple.com99f37622012-10-29 04:02:08 +00002448 break;
2449 }
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002450 case GetIndexedPropertyStorage: {
2451 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2452 forNode(node->child1()).m_value, node->arrayMode());
2453 if (view)
2454 m_state.setFoundConstants(true);
2455 forNode(node).clear();
2456 break;
2457 }
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00002458 case ConstantStoragePointer: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002459 forNode(node).clear();
oliver@apple.com43e511c2011-12-09 08:45:46 +00002460 break;
2461 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +00002462
2463 case GetTypedArrayByteOffset: {
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002464 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
2465 if (view) {
2466 setConstant(node, jsNumber(view->byteOffset()));
2467 break;
2468 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002469 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com537a4772013-08-19 23:16:01 +00002470 break;
2471 }
2472
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002473 case GetByOffset: {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00002474 StorageAccessData& data = node->storageAccessData();
fpizlo@apple.com12835772015-09-21 20:49:04 +00002475 UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2476
2477 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2478 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2479 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2480 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2481 // on the type that ByteCodeParser was able to prove.
2482 AbstractValue value = m_graph.inferredValueForProperty(
2483 forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2484
2485 // It's possible that the type that ByteCodeParser came up with is better.
2486 AbstractValue typeFromParsing;
2487 typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2488 value.filter(typeFromParsing);
2489
2490 // If we decide that there does not exist any value that this can return, then it's probably
2491 // because the compilation was already invalidated.
2492 if (value.isClear())
2493 m_state.setIsValid(false);
2494
2495 forNode(node) = value;
2496 if (value.m_value)
2497 m_state.setFoundConstants(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002498 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002499 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002500
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002501 case GetGetterSetterByOffset: {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00002502 StorageAccessData& data = node->storageAccessData();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002503 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2504 if (result && jsDynamicCast<GetterSetter*>(result)) {
2505 setConstant(node, *m_graph.freeze(result));
2506 break;
2507 }
2508
mark.lam@apple.com8d3c2692016-04-28 06:54:54 +00002509 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002510 break;
2511 }
2512
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002513 case MultiGetByOffset: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002514 // This code will filter the base value in a manner that is possibly different (either more
2515 // or less precise) than the way it would be filtered if this was strength-reduced to a
2516 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2517 // different things about the code, so long as all of them are sound. That even includes
2518 // one guy proving that code should never execute (due to a contradiction) and another guy
2519 // not finding that contradiction. If someone ever proved that there would be a
2520 // contradiction then there must always be a contradiction even if subsequent passes don't
2521 // realize it. This is the case here.
2522
2523 // Ordinarily you have to be careful with calling setFoundConstants()
2524 // because of the effect on compile times, but this node is FTL-only.
2525 m_state.setFoundConstants(true);
2526
fpizlo@apple.com12835772015-09-21 20:49:04 +00002527 UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2528
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002529 AbstractValue base = forNode(node->child1());
2530 StructureSet baseSet;
2531 AbstractValue result;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00002532 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
2533 StructureSet set = getCase.set();
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002534 set.filter(base);
2535 if (set.isEmpty())
2536 continue;
2537 baseSet.merge(set);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002538
2539 switch (getCase.method().kind()) {
2540 case GetByOffsetMethod::Constant: {
2541 AbstractValue thisResult;
2542 thisResult.set(
2543 m_graph,
2544 *getCase.method().constant(),
2545 m_state.structureClobberState());
2546 result.merge(thisResult);
2547 break;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002548 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002549
2550 case GetByOffsetMethod::Load: {
2551 result.merge(
2552 m_graph.inferredValueForProperty(
2553 set, uid, m_state.structureClobberState()));
2554 break;
2555 }
2556
2557 default: {
2558 result.makeHeapTop();
2559 break;
2560 } }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002561 }
2562
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002563 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2564 m_state.setIsValid(false);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002565
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002566 forNode(node) = result;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002567 break;
2568 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002569
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002570 case PutByOffset: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002571 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002572 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00002573
2574 case MultiPutByOffset: {
fpizlo@apple.com43219522014-02-25 02:02:50 +00002575 StructureSet newSet;
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002576 TransitionVector transitions;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002577
2578 // Ordinarily you have to be careful with calling setFoundConstants()
2579 // because of the effect on compile times, but this node is FTL-only.
2580 m_state.setFoundConstants(true);
2581
2582 AbstractValue base = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002583 AbstractValue originalValue = forNode(node->child2());
2584 AbstractValue resultingValue;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002585
fpizlo@apple.com43219522014-02-25 02:02:50 +00002586 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2587 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002588 StructureSet thisSet = variant.oldStructure();
2589 thisSet.filter(base);
2590 if (thisSet.isEmpty())
2591 continue;
fpizlo@apple.com12835772015-09-21 20:49:04 +00002592
2593 AbstractValue thisValue = originalValue;
2594 thisValue.filter(m_graph, variant.requiredType());
2595 resultingValue.merge(thisValue);
2596
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002597 if (variant.kind() == PutByIdVariant::Transition) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002598 if (thisSet.onlyStructure() != variant.newStructure()) {
2599 transitions.append(
2600 Transition(variant.oldStructureForTransition(), variant.newStructure()));
2601 } // else this is really a replace.
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002602 newSet.add(variant.newStructure());
2603 } else {
2604 ASSERT(variant.kind() == PutByIdVariant::Replace);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002605 newSet.merge(thisSet);
fpizlo@apple.com43219522014-02-25 02:02:50 +00002606 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00002607 }
2608
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002609 observeTransitions(clobberLimit, transitions);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002610 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2611 m_state.setIsValid(false);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002612 forNode(node->child2()) = resultingValue;
2613 if (!!originalValue && !resultingValue)
2614 m_state.setIsValid(false);
fpizlo@apple.com43219522014-02-25 02:02:50 +00002615 break;
2616 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002617
2618 case GetExecutable: {
fpizlo@apple.com731e7762014-08-25 22:35:40 +00002619 JSValue value = forNode(node->child1()).value();
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002620 if (value) {
2621 JSFunction* function = jsDynamicCast<JSFunction*>(value);
2622 if (function) {
2623 setConstant(node, *m_graph.freeze(function->executable()));
2624 break;
2625 }
2626 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002627 forNode(node).setType(m_graph, SpecCellOther);
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002628 break;
2629 }
2630
2631 case CheckCell: {
2632 JSValue value = forNode(node->child1()).value();
2633 if (value == node->cellOperand()->value()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002634 m_state.setFoundConstants(true);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002635 ASSERT(value);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002636 break;
2637 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002638 filterByValue(node->child1(), *node->cellOperand());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002639 break;
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002640 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +00002641
2642 case CheckNotEmpty: {
2643 AbstractValue& value = forNode(node->child1());
2644 if (!(value.m_type & SpecEmpty)) {
2645 m_state.setFoundConstants(true);
2646 break;
2647 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00002648
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +00002649 filter(value, ~SpecEmpty);
2650 break;
2651 }
2652
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002653 case CheckStringIdent: {
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002654 AbstractValue& value = forNode(node->child1());
2655 UniquedStringImpl* uid = node->uidOperand();
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002656 ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002657
2658 JSValue childConstant = value.value();
2659 if (childConstant) {
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002660 ASSERT(childConstant.isString());
2661 if (asString(childConstant)->tryGetValueImpl() == uid) {
2662 m_state.setFoundConstants(true);
2663 break;
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002664 }
2665 }
2666
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002667 filter(value, SpecStringIdent);
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002668 break;
2669 }
2670
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00002671 case CheckInBounds: {
2672 JSValue left = forNode(node->child1()).value();
2673 JSValue right = forNode(node->child2()).value();
2674 if (left && right && left.isInt32() && right.isInt32()
2675 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2676 m_state.setFoundConstants(true);
2677 break;
2678 }
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00002679 break;
2680 }
2681
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002682 case PutById:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +00002683 case PutByIdFlush:
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002684 case PutByIdDirect: {
2685 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002686 if (value.m_structure.isFinite()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002687 PutByIdStatus status = PutByIdStatus::computeFor(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002688 m_graph.globalObjectFor(node->origin.semantic),
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002689 value.m_structure.set(),
oliver@apple.com90fce822013-07-25 04:00:13 +00002690 m_graph.identifiers()[node->identifierNumber()],
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002691 node->op() == PutByIdDirect);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002692
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002693 if (status.isSimple()) {
2694 StructureSet newSet;
2695 TransitionVector transitions;
2696
2697 for (unsigned i = status.numVariants(); i--;) {
2698 const PutByIdVariant& variant = status[i];
2699 if (variant.kind() == PutByIdVariant::Transition) {
2700 transitions.append(
2701 Transition(
2702 variant.oldStructureForTransition(), variant.newStructure()));
fpizlo@apple.com920c1672014-08-19 00:55:31 +00002703 m_graph.registerStructure(variant.newStructure());
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002704 newSet.add(variant.newStructure());
2705 } else {
2706 ASSERT(variant.kind() == PutByIdVariant::Replace);
2707 newSet.merge(variant.oldStructure());
2708 }
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002709 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002710
2711 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002712 m_state.setFoundConstants(true);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002713
2714 observeTransitions(clobberLimit, transitions);
2715 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2716 m_state.setIsValid(false);
2717 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002718 }
2719 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002720
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002721 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002722 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002723 }
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00002724
sbarati@apple.com23315d62016-05-09 20:17:23 +00002725 case PutByValWithThis:
2726 case PutByIdWithThis:
2727 clobberWorld(node->origin.semantic, clobberLimit);
2728 break;
2729
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00002730 case PutGetterById:
2731 case PutSetterById:
2732 case PutGetterSetterById:
2733 case PutGetterByVal:
2734 case PutSetterByVal: {
2735 clobberWorld(node->origin.semantic, clobberLimit);
2736 break;
2737 }
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00002738
2739 case DefineDataProperty:
2740 case DefineAccessorProperty:
2741 clobberWorld(node->origin.semantic, clobberLimit);
2742 break;
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002743
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002744 case In: {
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002745 // FIXME: We can determine when the property definitely exists based on abstract
2746 // value information.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002747 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002748 forNode(node).setType(SpecBoolean);
2749 break;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002750 }
sbarati@apple.coma3db4652016-09-20 01:05:50 +00002751
2752 case HasOwnProperty: {
2753 clobberWorld(node->origin.semantic, clobberLimit);
2754 forNode(node).setType(SpecBoolean);
2755 break;
2756 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002757
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002758 case GetEnumerableLength: {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002759 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002760 break;
2761 }
2762 case HasGenericProperty: {
2763 forNode(node).setType(SpecBoolean);
2764 break;
2765 }
2766 case HasStructureProperty: {
2767 forNode(node).setType(SpecBoolean);
2768 break;
2769 }
2770 case HasIndexedProperty: {
2771 ArrayMode mode = node->arrayMode();
2772 switch (mode.type()) {
2773 case Array::Int32:
2774 case Array::Double:
2775 case Array::Contiguous:
2776 case Array::ArrayStorage: {
2777 break;
2778 }
2779 default: {
2780 clobberWorld(node->origin.semantic, clobberLimit);
2781 break;
2782 }
2783 }
2784 forNode(node).setType(SpecBoolean);
2785 break;
2786 }
2787 case GetDirectPname: {
2788 clobberWorld(node->origin.semantic, clobberLimit);
2789 forNode(node).makeHeapTop();
2790 break;
2791 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002792 case GetPropertyEnumerator: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002793 forNode(node).setType(m_graph, SpecCell);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002794 break;
2795 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002796 case GetEnumeratorStructurePname: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002797 forNode(node).setType(m_graph, SpecString | SpecOther);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002798 break;
2799 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002800 case GetEnumeratorGenericPname: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002801 forNode(node).setType(m_graph, SpecString | SpecOther);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002802 break;
2803 }
2804 case ToIndexString: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002805 forNode(node).setType(m_graph, SpecString);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002806 break;
2807 }
2808
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002809 case GetGlobalVar:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002810 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002811 break;
sbarati@apple.come67fd782016-04-19 01:38:30 +00002812
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002813 case GetGlobalLexicalVariable:
2814 forNode(node).makeBytecodeTop();
2815 break;
sbarati@apple.come67fd782016-04-19 01:38:30 +00002816
2817 case GetDynamicVar:
2818 clobberWorld(node->origin.semantic, clobberLimit);
2819 forNode(node).makeBytecodeTop();
2820 break;
2821
2822 case PutDynamicVar:
2823 clobberWorld(node->origin.semantic, clobberLimit);
2824 break;
2825
2826 case ResolveScope:
2827 clobberWorld(node->origin.semantic, clobberLimit);
2828 forNode(node).setType(m_graph, SpecObject);
2829 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00002830
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002831 case PutGlobalVariable:
fpizlo@apple.com86468342013-11-27 02:47:43 +00002832 case NotifyWrite:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002833 break;
2834
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002835 case OverridesHasInstance:
2836 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002837 break;
2838
2839 case InstanceOf:
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002840 // Sadly, we don't propagate the fact that we've done InstanceOf
2841 forNode(node).setType(SpecBoolean);
2842 break;
2843
2844 case InstanceOfCustom:
2845 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00002846 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002847 break;
2848
2849 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002850 RELEASE_ASSERT(m_graph.m_form == SSA);
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00002851 forNode(node) = forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow));
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002852 // The state of this node would have already been decided, but it may have become a
2853 // constant, in which case we'd like to know.
2854 if (forNode(node).m_value)
2855 m_state.setFoundConstants(true);
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002856 break;
2857
2858 case Upsilon: {
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00002859 NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
2860 if (shadow.isStillValid()) {
2861 m_state.createValueForNode(shadow);
2862 forNode(shadow) = forNode(node->child1());
2863 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002864 break;
2865 }
2866
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00002867 case Flush:
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +00002868 case PhantomLocal:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002869 break;
2870
2871 case Call:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002872 case TailCallInlinedCaller:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002873 case Construct:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00002874 case CallVarargs:
2875 case CallForwardVarargs:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002876 case TailCallVarargsInlinedCaller:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00002877 case ConstructVarargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002878 case ConstructForwardVarargs:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002879 case TailCallForwardVarargsInlinedCaller:
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00002880 case CallEval:
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00002881 case DirectCall:
2882 case DirectConstruct:
2883 case DirectTailCallInlinedCaller:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002884 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002885 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002886 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002887
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002888 case ForceOSRExit:
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002889 case CheckBadCell:
oliver@apple.com55d32d92013-07-25 04:05:03 +00002890 m_state.setIsValid(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002891 break;
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00002892
2893 case InvalidationPoint:
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002894 forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2895 m_state.setStructureClobberState(StructuresAreWatched);
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00002896 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002897
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00002898 case CheckWatchdogTimer:
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002899 case LogShadowChickenPrologue:
2900 case LogShadowChickenTail:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00002901 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002902
saambarati1@gmail.comdaf10202014-10-01 20:47:51 +00002903 case ProfileType:
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002904 case ProfileControlFlow:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002905 case Phantom:
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00002906 case CountExecution:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002907 case CheckTierUpInLoop:
2908 case CheckTierUpAtReturn:
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002909 case CheckTypeInfoFlags:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002910 break;
2911
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00002912 case CreateRest:
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00002913 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2914 // This means we're already having a bad time.
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00002915 clobberWorld(node->origin.semantic, clobberLimit);
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00002916 forNode(node).setType(m_graph, SpecArray);
2917 break;
2918 }
2919 forNode(node).set(
2920 m_graph,
2921 m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
sbarati@apple.comc0722da2015-11-20 02:37:47 +00002922 break;
2923
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002924 case Check: {
2925 // Simplify out checks that don't actually do checking.
2926 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2927 Edge edge = node->children.child(i);
2928 if (!edge)
2929 break;
2930 if (edge.isProved() || edge.willNotHaveCheck()) {
2931 m_state.setFoundConstants(true);
2932 break;
2933 }
2934 }
2935 break;
2936 }
2937
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00002938 case SetFunctionName: {
2939 clobberWorld(node->origin.semantic, clobberLimit);
2940 break;
2941 }
2942
fpizlo@apple.com9a175952016-09-28 21:55:53 +00002943 case StoreBarrier:
2944 case FencedStoreBarrier: {
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00002945 filter(node->child1(), SpecCell);
2946 break;
2947 }
fpizlo@apple.com9a175952016-09-28 21:55:53 +00002948
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002949 case CheckTierUpAndOSREnter:
2950 case LoopHint:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002951 case ZombieHint:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00002952 case ExitOK:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002953 break;
oliver@apple.com1fc04182013-08-19 19:40:13 +00002954
2955 case Unreachable:
fpizlo@apple.comf4b38f02016-05-05 19:20:23 +00002956 // It may be that during a previous run of AI we proved that something was unreachable, but
2957 // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
2958 // monotonically stronger over time. So, we don't assert that AI doesn't reach the
2959 // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
2960 // crash whenever AI fails to be as powerful on run K as it was on run K-1.
2961 m_state.setIsValid(false);
2962 break;
2963
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00002964 case LastNodeType:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00002965 case ArithIMul:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00002966 case FiatInt52:
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002967 DFG_CRASH(m_graph, node, "Unexpected node type");
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00002968 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002969 }
2970
oliver@apple.com55d32d92013-07-25 04:05:03 +00002971 return m_state.isValid();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002972}
2973
oliver@apple.com55d32d92013-07-25 04:05:03 +00002974template<typename AbstractStateType>
2975bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002976{
oliver@apple.com55d32d92013-07-25 04:05:03 +00002977 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002978}
2979
oliver@apple.com55d32d92013-07-25 04:05:03 +00002980template<typename AbstractStateType>
2981bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002982{
oliver@apple.com55d32d92013-07-25 04:05:03 +00002983 Node* node = m_state.block()->at(indexInBlock);
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00002984
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002985 startExecuting();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002986 executeEdges(node);
2987 return executeEffects(indexInBlock, node);
2988}
2989
oliver@apple.com55d32d92013-07-25 04:05:03 +00002990template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +00002991bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2992{
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002993 startExecuting();
oliver@apple.come17632e2013-07-25 04:05:31 +00002994 executeEdges(node);
2995 return executeEffects(UINT_MAX, node);
2996}
2997
2998template<typename AbstractStateType>
oliver@apple.com55d32d92013-07-25 04:05:03 +00002999void AbstractInterpreter<AbstractStateType>::clobberWorld(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003000 const CodeOrigin&, unsigned clobberLimit)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00003001{
oliver@apple.come17632e2013-07-25 04:05:31 +00003002 clobberStructures(clobberLimit);
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00003003}
3004
oliver@apple.com55d32d92013-07-25 04:05:03 +00003005template<typename AbstractStateType>
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003006template<typename Functor>
3007void AbstractInterpreter<AbstractStateType>::forAllValues(
3008 unsigned clobberLimit, Functor& functor)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003009{
oliver@apple.come17632e2013-07-25 04:05:31 +00003010 if (clobberLimit >= m_state.block()->size())
3011 clobberLimit = m_state.block()->size();
3012 else
3013 clobberLimit++;
3014 ASSERT(clobberLimit <= m_state.block()->size());
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003015 for (size_t i = clobberLimit; i--;) {
3016 NodeFlowProjection::forEach(
3017 m_state.block()->at(i),
3018 [&] (NodeFlowProjection nodeProjection) {
3019 functor(forNode(nodeProjection));
3020 });
3021 }
oliver@apple.com96feafa2013-07-25 04:04:57 +00003022 if (m_graph.m_form == SSA) {
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003023 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
3024 if (node.isStillValid())
3025 functor(forNode(node));
3026 }
oliver@apple.com96feafa2013-07-25 04:04:57 +00003027 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00003028 for (size_t i = m_state.variables().numberOfArguments(); i--;)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003029 functor(m_state.variables().argument(i));
oliver@apple.com55d32d92013-07-25 04:05:03 +00003030 for (size_t i = m_state.variables().numberOfLocals(); i--;)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003031 functor(m_state.variables().local(i));
3032}
3033
3034template<typename AbstractStateType>
3035void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
3036{
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003037 forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
3038 setDidClobber();
3039}
3040
3041template<typename AbstractStateType>
3042void AbstractInterpreter<AbstractStateType>::observeTransition(
3043 unsigned clobberLimit, Structure* from, Structure* to)
3044{
3045 AbstractValue::TransitionObserver transitionObserver(from, to);
3046 forAllValues(clobberLimit, transitionObserver);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00003047
3048 ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003049}
3050
3051template<typename AbstractStateType>
3052void AbstractInterpreter<AbstractStateType>::observeTransitions(
3053 unsigned clobberLimit, const TransitionVector& vector)
3054{
3055 AbstractValue::TransitionsObserver transitionsObserver(vector);
3056 forAllValues(clobberLimit, transitionsObserver);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00003057
3058 if (!ASSERT_DISABLED) {
3059 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
3060 for (unsigned i = vector.size(); i--;)
3061 ASSERT(!vector[i].previous->dfgShouldWatch());
3062 }
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003063}
3064
3065template<typename AbstractStateType>
3066void AbstractInterpreter<AbstractStateType>::setDidClobber()
3067{
oliver@apple.com55d32d92013-07-25 04:05:03 +00003068 m_state.setDidClobber(true);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003069 m_state.setStructureClobberState(StructuresAreClobbered);
3070}
3071
3072template<typename AbstractStateType>
3073void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
3074{
3075 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003076}
3077
oliver@apple.com55d32d92013-07-25 04:05:03 +00003078template<typename AbstractStateType>
3079void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003080{
oliver@apple.com96feafa2013-07-25 04:04:57 +00003081 CommaPrinter comma(" ");
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003082 HashSet<NodeFlowProjection> seen;
oliver@apple.com96feafa2013-07-25 04:04:57 +00003083 if (m_graph.m_form == SSA) {
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003084 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003085 seen.add(node);
oliver@apple.com96feafa2013-07-25 04:04:57 +00003086 AbstractValue& value = forNode(node);
3087 if (value.isClear())
3088 continue;
3089 out.print(comma, node, ":", value);
3090 }
3091 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00003092 for (size_t i = 0; i < m_state.block()->size(); ++i) {
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003093 NodeFlowProjection::forEach(
3094 m_state.block()->at(i), [&] (NodeFlowProjection nodeProjection) {
3095 seen.add(nodeProjection);
3096 AbstractValue& value = forNode(nodeProjection);
3097 if (value.isClear())
3098 return;
3099 out.print(comma, nodeProjection, ":", value);
3100 });
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003101 }
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003102 if (m_graph.m_form == SSA) {
fpizlo@apple.com8ff2aef2016-11-04 05:28:35 +00003103 for (NodeFlowProjection node : m_state.block()->ssa->liveAtTail) {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003104 if (seen.contains(node))
3105 continue;
3106 AbstractValue& value = forNode(node);
3107 if (value.isClear())
3108 continue;
3109 out.print(comma, node, ":", value);
3110 }
3111 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003112}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003113
oliver@apple.com55d32d92013-07-25 04:05:03 +00003114template<typename AbstractStateType>
3115FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
fpizlo@apple.com12835772015-09-21 20:49:04 +00003116 AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
oliver@apple.com33913872013-07-25 04:02:13 +00003117{
fpizlo@apple.com12835772015-09-21 20:49:04 +00003118 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
oliver@apple.com33913872013-07-25 04:02:13 +00003119 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003120 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003121 return Contradiction;
3122}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003123
3124template<typename AbstractStateType>
3125FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
3126 AbstractValue& value, ArrayModes arrayModes)
oliver@apple.com33913872013-07-25 04:02:13 +00003127{
3128 if (value.filterArrayModes(arrayModes) == FiltrationOK)
3129 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003130 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003131 return Contradiction;
3132}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003133
3134template<typename AbstractStateType>
3135FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3136 AbstractValue& value, SpeculatedType type)
oliver@apple.com33913872013-07-25 04:02:13 +00003137{
3138 if (value.filter(type) == FiltrationOK)
3139 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003140 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003141 return Contradiction;
3142}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003143
3144template<typename AbstractStateType>
3145FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00003146 AbstractValue& abstractValue, FrozenValue concreteValue)
oliver@apple.com33913872013-07-25 04:02:13 +00003147{
3148 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
3149 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003150 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003151 return Contradiction;
3152}
3153
commit-queue@webkit.org7936e482016-08-25 23:02:52 +00003154template<typename AbstractStateType>
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00003155FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo(
3156 AbstractValue& value, const ClassInfo* classInfo)
3157{
3158 if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK)
3159 return FiltrationOK;
3160 m_state.setIsValid(false);
3161 return Contradiction;
3162}
3163
3164template<typename AbstractStateType>
commit-queue@webkit.org7936e482016-08-25 23:02:52 +00003165void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
3166{
3167 JSValue child = forNode(node->child1()).value();
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003168 if (std::optional<double> number = child.toNumberFromPrimitive()) {
commit-queue@webkit.org7936e482016-08-25 23:02:52 +00003169 setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
3170 return;
3171 }
3172 SpeculatedType type = SpecFullNumber;
3173 if (node->child1().useKind() == DoubleRepUse)
3174 type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
3175 forNode(node).setType(type);
3176}
3177
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003178} } // namespace JSC::DFG
3179
3180#endif // ENABLE(DFG_JIT)