blob: ebdc79c60f6f2f6d9063ea16c4c286c4553a1003 [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
oliver@apple.com55d32d92013-07-25 04:05:03 +000026#ifndef DFGAbstractInterpreterInlines_h
27#define DFGAbstractInterpreterInlines_h
28
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000029#if ENABLE(DFG_JIT)
30
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000031#include "ArrayConstructor.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000032#include "DFGAbstractInterpreter.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000033#include "GetByIdStatus.h"
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000034#include "GetterSetter.h"
benjamin@webkit.org903025b2015-02-14 04:20:21 +000035#include "JITOperations.h"
benjamin@webkit.org28b4f2d2015-02-18 08:01:01 +000036#include "MathCommon.h"
oliver@apple.come722ad02013-01-09 02:37:29 +000037#include "Operations.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000038#include "PutByIdStatus.h"
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +000039#include "StringObject.h"
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000040
41namespace JSC { namespace DFG {
42
oliver@apple.com55d32d92013-07-25 04:05:03 +000043template<typename AbstractStateType>
44AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000045 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000046 , m_graph(graph)
oliver@apple.com55d32d92013-07-25 04:05:03 +000047 , m_state(state)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000048{
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000049 if (m_graph.m_form == SSA)
50 m_phiChildren = std::make_unique<PhiChildren>(m_graph);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000051}
52
oliver@apple.com55d32d92013-07-25 04:05:03 +000053template<typename AbstractStateType>
54AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000055{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000056}
57
oliver@apple.com55d32d92013-07-25 04:05:03 +000058template<typename AbstractStateType>
59typename AbstractInterpreter<AbstractStateType>::BooleanResult
60AbstractInterpreter<AbstractStateType>::booleanResult(
61 Node* node, AbstractValue& value)
fpizlo@apple.com367a1102012-11-10 23:33:29 +000062{
63 JSValue childConst = value.value();
64 if (childConst) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +000065 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
fpizlo@apple.com367a1102012-11-10 23:33:29 +000066 return DefinitelyTrue;
67 return DefinitelyFalse;
68 }
69
70 // 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 +000071 if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
72 bool allTrue = true;
73 for (unsigned i = value.m_structure.size(); i--;) {
74 Structure* structure = value.m_structure[i];
75 if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
76 || structure->typeInfo().type() == StringType) {
77 allTrue = false;
78 break;
79 }
80 }
81 if (allTrue)
fpizlo@apple.com367a1102012-11-10 23:33:29 +000082 return DefinitelyTrue;
83 }
84
85 return UnknownBooleanResult;
86}
87
oliver@apple.com55d32d92013-07-25 04:05:03 +000088template<typename AbstractStateType>
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000089void AbstractInterpreter<AbstractStateType>::startExecuting()
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000090{
oliver@apple.com55d32d92013-07-25 04:05:03 +000091 ASSERT(m_state.block());
92 ASSERT(m_state.isValid());
fpizlo@apple.comb75911b2012-06-13 20:53:52 +000093
oliver@apple.com55d32d92013-07-25 04:05:03 +000094 m_state.setDidClobber(false);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000095}
96
oliver@apple.com55d32d92013-07-25 04:05:03 +000097template<typename AbstractStateType>
98void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000099{
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000100 m_graph.doToChildren(
101 node,
102 [&] (Edge& edge) {
103 filterEdgeByUse(edge);
104 });
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000105}
106
oliver@apple.com55d32d92013-07-25 04:05:03 +0000107template<typename AbstractStateType>
108void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000109{
oliver@apple.com55d32d92013-07-25 04:05:03 +0000110 executeEdges(m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000111}
112
oliver@apple.com55d32d92013-07-25 04:05:03 +0000113template<typename AbstractStateType>
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000114void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000115{
fpizlo@apple.com96679c02015-09-01 18:27:13 +0000116 // Some use kinds are required to not have checks, because we know somehow that the incoming
117 // 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 +0000118 // prove that this is indeed the case. But the existance of the edge is enough to prove that
119 // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
120 // and FTL backends may emit checks in a node that lacks a valid exit origin.
121 m_graph.doToChildren(
122 node,
123 [&] (Edge& edge) {
124 if (mayHaveTypeCheck(edge.useKind()))
125 return;
126
127 filterEdgeByUse(edge);
128 });
129}
130
131template<typename AbstractStateType>
132void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
133{
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000134 if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
135 return;
136
fpizlo@apple.com97812a32014-10-04 17:18:25 +0000137 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 +0000138}
139
oliver@apple.com55d32d92013-07-25 04:05:03 +0000140template<typename AbstractStateType>
141void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000142{
143 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
144}
145
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +0000146inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
147{
148 // We look at the type first since that will cover most cases and does not require iterating all the structures.
149 if (isStrictMode) {
150 if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
151 return true;
152 } else {
153 if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
154 return true;
155 }
156
157 if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
158 bool overridesToThis = false;
159 valueForNode.m_structure.forEach([&](Structure* structure) {
160 TypeInfo type = structure->typeInfo();
161 ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
162 if (!isStrictMode)
163 ASSERT(type.isObject());
164 // We don't need to worry about strings/symbols here since either:
165 // 1) We are in strict mode and strings/symbols are not wrapped
166 // 2) The AI has proven that the type of this is a subtype of object
167 if (type.isObject() && type.overridesToThis())
168 overridesToThis = true;
169 });
170 return overridesToThis;
171 }
172
173 return false;
174}
175
oliver@apple.com55d32d92013-07-25 04:05:03 +0000176template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +0000177bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000178{
179 if (!ASSERT_DISABLED)
180 verifyEdges(node);
181
oliver@apple.com02e7a972013-07-25 04:05:04 +0000182 m_state.createValueForNode(node);
183
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000184 switch (node->op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000185 case JSConstant:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000186 case DoubleConstant:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000187 case Int52Constant: {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000188 setBuiltInConstant(node, *node->constant());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000189 break;
190 }
fpizlo@apple.com024424c2016-03-09 05:16:47 +0000191
192 case LazyJSConstant: {
193 LazyJSValue value = node->lazyJSValue();
194 switch (value.kind()) {
195 case LazyJSValue::KnownValue:
196 setConstant(node, value.value()->value());
197 break;
198 case LazyJSValue::SingleCharacterString:
199 case LazyJSValue::KnownStringImpl:
200 case LazyJSValue::NewStringImpl:
201 forNode(node).setType(m_graph, SpecString);
202 break;
203 }
204 break;
205 }
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000206
207 case Identity: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000208 forNode(node) = forNode(node->child1());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000209 if (forNode(node).value())
210 m_state.setFoundConstants(true);
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000211 break;
212 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000213
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000214 case ExtractOSREntryLocal: {
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000215 forNode(node).makeBytecodeTop();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000216 break;
217 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000218
219 case GetLocal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000220 VariableAccessData* variableAccessData = node->variableAccessData();
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000221 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000222 // The value in the local should already be checked.
223 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000224 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000225 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000226 forNode(node) = value;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000227 break;
228 }
229
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000230 case GetStack: {
231 StackAccessData* data = node->stackAccessData();
232 AbstractValue value = m_state.variables().operand(data->local);
233 // The value in the local should already be checked.
234 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
235 if (value.value())
236 m_state.setFoundConstants(true);
237 forNode(node) = value;
238 break;
239 }
240
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000241 case GetLocalUnlinked: {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000242 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000243 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000244 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000245 forNode(node) = value;
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000246 break;
247 }
248
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000249 case SetLocal: {
250 m_state.variables().operand(node->local()) = forNode(node->child1());
251 break;
252 }
253
254 case PutStack: {
255 m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000256 break;
257 }
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000258
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000259 case MovHint: {
260 // Don't need to do anything. A MovHint only informs us about what would have happened
261 // in bytecode, but this code is just concerned with what is actually happening during
262 // DFG execution.
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000263 break;
264 }
265
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000266 case KillStack: {
fpizlo@apple.com832490a2014-10-01 20:12:11 +0000267 // This is just a hint telling us that the OSR state of the local is no longer inside the
268 // flushed data.
269 break;
270 }
271
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000272 case SetArgument:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000273 // Assert that the state of arguments has been set. SetArgument means that someone set
274 // the argument values out-of-band, and currently this always means setting to a
275 // non-clear value.
276 ASSERT(!m_state.variables().operand(node->local()).isClear());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000277 break;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000278
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000279 case LoadVarargs:
280 case ForwardVarargs: {
281 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
282 // itself into a straight-line sequence of GetStack/PutStack.
283 // https://bugs.webkit.org/show_bug.cgi?id=143071
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000284 clobberWorld(node->origin.semantic, clobberLimit);
285 LoadVarargsData* data = node->loadVarargsData();
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000286 m_state.variables().operand(data->count).setType(SpecInt32Only);
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000287 for (unsigned i = data->limit - 1; i--;)
288 m_state.variables().operand(data->start.offset() + i).makeHeapTop();
289 break;
290 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000291
292 case BitAnd:
293 case BitOr:
294 case BitXor:
295 case BitRShift:
296 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000297 case BitURShift: {
mark.lam@apple.comc0008652015-12-15 21:19:31 +0000298 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
299 clobberWorld(node->origin.semantic, clobberLimit);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000300 forNode(node).setType(m_graph, SpecInt32Only);
mark.lam@apple.comc0008652015-12-15 21:19:31 +0000301 break;
302 }
303
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000304 JSValue left = forNode(node->child1()).value();
305 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000306 if (left && right && left.isInt32() && right.isInt32()) {
307 int32_t a = left.asInt32();
308 int32_t b = right.asInt32();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000309 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000310 case BitAnd:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000311 setConstant(node, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000312 break;
313 case BitOr:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000314 setConstant(node, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000315 break;
316 case BitXor:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000317 setConstant(node, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000318 break;
319 case BitRShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000320 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000321 break;
322 case BitLShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000323 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000324 break;
325 case BitURShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000326 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000327 break;
328 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000329 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000330 break;
331 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000332 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000333 }
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000334
335 if (node->op() == BitAnd
336 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
337 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
338 forNode(node).setType(SpecBoolInt32);
339 break;
340 }
341
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000342 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000343 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000344 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000345
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000346 case UInt32ToNumber: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000347 JSValue child = forNode(node->child1()).value();
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000348 if (doesOverflow(node->arithMode())) {
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000349 if (enableInt52()) {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000350 if (child && child.isAnyInt()) {
commit-queue@webkit.org1f3678b2016-04-26 04:08:22 +0000351 int64_t machineInt = child.asAnyInt();
352 setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000353 break;
354 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000355 forNode(node).setType(SpecAnyInt);
commit-queue@webkit.orge086f372016-04-08 18:07:25 +0000356 break;
357 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000358 if (child && child.isInt32()) {
359 uint32_t value = child.asInt32();
360 setConstant(node, jsNumber(value));
361 break;
362 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000363 forNode(node).setType(SpecAnyIntAsDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000364 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000365 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000366 if (child && child.isInt32()) {
367 int32_t value = child.asInt32();
368 if (value >= 0) {
369 setConstant(node, jsNumber(value));
370 break;
371 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000372 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000373 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000374 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000375 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000376
377 case BooleanToNumber: {
378 JSValue concreteValue = forNode(node->child1()).value();
379 if (concreteValue) {
380 if (concreteValue.isBoolean())
381 setConstant(node, jsNumber(concreteValue.asBoolean()));
382 else
fpizlo@apple.comf8cb6182015-02-23 18:03:49 +0000383 setConstant(node, *m_graph.freeze(concreteValue));
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000384 break;
385 }
386 AbstractValue& value = forNode(node);
387 value = forNode(node->child1());
388 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
389 m_state.setFoundConstants(true);
390 if (value.m_type & SpecBoolean) {
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000391 value.merge(SpecBoolInt32);
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000392 value.filter(~SpecBoolean);
393 }
394 break;
395 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000396
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000397 case DoubleAsInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000398 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000399 if (child && child.isNumber()) {
400 double asDouble = child.asNumber();
401 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000402 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
403 setConstant(node, JSValue(asInt));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000404 break;
405 }
406 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000407 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000408 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000409 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000410
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000411 case ValueToInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000412 JSValue child = forNode(node->child1()).value();
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000413 if (child) {
414 if (child.isNumber()) {
415 if (child.isInt32())
416 setConstant(node, child);
417 else
418 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
419 break;
420 }
421 if (child.isBoolean()) {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000422 setConstant(node, jsNumber(child.asBoolean()));
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000423 break;
424 }
fpizlo@apple.com29594fe2014-03-21 00:32:37 +0000425 if (child.isUndefinedOrNull()) {
426 setConstant(node, jsNumber(0));
427 break;
428 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000429 }
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000430
fpizlo@apple.com8c7a7cf2015-05-19 02:30:00 +0000431 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
432 forNode(node).setType(SpecBoolInt32);
433 break;
434 }
435
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000436 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000437 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000438 }
oliver@apple.com500b53a2013-07-25 04:05:25 +0000439
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000440 case DoubleRep: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000441 JSValue child = forNode(node->child1()).value();
commit-queue@webkit.orgfab33f42016-04-17 04:55:02 +0000442 if (child) {
443 if (child.isNumber()) {
444 setConstant(node, jsDoubleNumber(child.asNumber()));
445 break;
446 }
447 if (child.isUndefined()) {
448 setConstant(node, jsDoubleNumber(PNaN));
449 break;
450 }
451 if (child.isNull() || child.isFalse()) {
452 setConstant(node, jsDoubleNumber(0));
453 break;
454 }
455 if (child.isTrue()) {
456 setConstant(node, jsDoubleNumber(1));
457 break;
458 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000459 }
benjamin@webkit.orgbf928092015-05-28 01:30:58 +0000460
461 SpeculatedType type = forNode(node->child1()).m_type;
462 switch (node->child1().useKind()) {
463 case NotCellUse: {
464 if (type & SpecOther) {
465 type &= ~SpecOther;
466 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
467 }
468 if (type & SpecBoolean) {
469 type &= ~SpecBoolean;
470 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
471 }
472 type &= SpecBytecodeNumber;
473 break;
474 }
475
476 case Int52RepUse:
477 case NumberUse:
fpizlo@apple.com318af072015-06-05 04:59:28 +0000478 case RealNumberUse:
benjamin@webkit.orgbf928092015-05-28 01:30:58 +0000479 break;
480
481 default:
482 RELEASE_ASSERT_NOT_REACHED();
483 }
484 forNode(node).setType(type);
fpizlo@apple.com12381022015-05-13 23:57:17 +0000485 forNode(node).fixTypeForRepresentation(m_graph, node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000486 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000487 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000488
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000489 case Int52Rep: {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000490 JSValue child = forNode(node->child1()).value();
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000491 if (child && child.isAnyInt()) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000492 setConstant(node, child);
493 break;
494 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000495
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000496 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000497 break;
498 }
499
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000500 case ValueRep: {
501 JSValue value = forNode(node->child1()).value();
502 if (value) {
503 setConstant(node, value);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000504 break;
505 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000506
fpizlo@apple.combaac2b92015-04-29 15:55:54 +0000507 forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
fpizlo@apple.com12381022015-05-13 23:57:17 +0000508 forNode(node).fixTypeForRepresentation(m_graph, node);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000509 break;
510 }
511
fpizlo@apple.com97756552014-01-02 20:15:25 +0000512 case ValueAdd: {
fpizlo@apple.com97756552014-01-02 20:15:25 +0000513 ASSERT(node->binaryUseKind() == UntypedUse);
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000514 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.combaac2b92015-04-29 15:55:54 +0000515 forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
fpizlo@apple.com97756552014-01-02 20:15:25 +0000516 break;
517 }
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +0000518
519 case StrCat: {
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +0000520 forNode(node).setType(m_graph, SpecString);
521 break;
522 }
fpizlo@apple.com97756552014-01-02 20:15:25 +0000523
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000524 case ArithAdd: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000525 JSValue left = forNode(node->child1()).value();
526 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000527 switch (node->binaryUseKind()) {
528 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000529 if (left && right && left.isInt32() && right.isInt32()) {
530 if (!shouldCheckOverflow(node->arithMode())) {
531 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
532 break;
533 }
534 JSValue result = jsNumber(left.asNumber() + right.asNumber());
535 if (result.isInt32()) {
536 setConstant(node, result);
537 break;
538 }
539 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000540 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000541 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000542 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000543 if (left && right && left.isAnyInt() && right.isAnyInt()) {
544 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
545 if (result.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000546 setConstant(node, result);
547 break;
548 }
549 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000550 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000551 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000552 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000553 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000554 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000555 break;
556 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000557 forNode(node).setType(
558 typeOfDoubleSum(
559 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000560 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000561 default:
fpizlo@apple.com97756552014-01-02 20:15:25 +0000562 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000563 break;
564 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000565 break;
566 }
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000567
568 case ArithClz32: {
569 JSValue operand = forNode(node->child1()).value();
570 if (operand && operand.isNumber()) {
571 uint32_t value = toUInt32(operand.asNumber());
572 setConstant(node, jsNumber(clz32(value)));
573 break;
574 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000575 forNode(node).setType(SpecInt32Only);
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000576 break;
577 }
578
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000579 case MakeRope: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000580 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000581 break;
582 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000583
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000584 case ArithSub: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000585 JSValue left = forNode(node->child1()).value();
586 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000587 switch (node->binaryUseKind()) {
588 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000589 if (left && right && left.isInt32() && right.isInt32()) {
590 if (!shouldCheckOverflow(node->arithMode())) {
591 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
592 break;
593 }
594 JSValue result = jsNumber(left.asNumber() - right.asNumber());
595 if (result.isInt32()) {
596 setConstant(node, result);
597 break;
598 }
599 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000600 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000601 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000602 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000603 if (left && right && left.isAnyInt() && right.isAnyInt()) {
604 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
605 if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000606 setConstant(node, result);
607 break;
608 }
609 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000610 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000611 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000612 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000613 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000614 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000615 break;
616 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000617 forNode(node).setType(
618 typeOfDoubleDifference(
619 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000620 break;
mark.lam@apple.com75249092015-10-16 23:26:14 +0000621 case UntypedUse:
mark.lam@apple.com39515722015-12-02 19:15:33 +0000622 clobberWorld(node->origin.semantic, clobberLimit);
623 forNode(node).setType(m_graph, SpecBytecodeNumber);
mark.lam@apple.com75249092015-10-16 23:26:14 +0000624 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000625 default:
626 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000627 break;
628 }
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000629 break;
630 }
631
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000632 case ArithNegate: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000633 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000634 switch (node->child1().useKind()) {
635 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000636 if (child && child.isInt32()) {
637 if (!shouldCheckOverflow(node->arithMode())) {
638 setConstant(node, jsNumber(-child.asInt32()));
639 break;
640 }
641 double doubleResult;
642 if (shouldCheckNegativeZero(node->arithMode()))
643 doubleResult = -child.asNumber();
644 else
645 doubleResult = 0 - child.asNumber();
646 JSValue valueResult = jsNumber(doubleResult);
647 if (valueResult.isInt32()) {
648 setConstant(node, valueResult);
649 break;
650 }
651 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000652 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000653 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000654 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000655 if (child && child.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000656 double doubleResult;
657 if (shouldCheckNegativeZero(node->arithMode()))
658 doubleResult = -child.asNumber();
659 else
660 doubleResult = 0 - child.asNumber();
661 JSValue valueResult = jsNumber(doubleResult);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000662 if (valueResult.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000663 setConstant(node, valueResult);
664 break;
665 }
666 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000667 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000668 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000669 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000670 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000671 setConstant(node, jsDoubleNumber(-child.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000672 break;
673 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000674 forNode(node).setType(
675 typeOfDoubleNegation(
676 forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000677 break;
678 default:
679 RELEASE_ASSERT_NOT_REACHED();
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000680 break;
681 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000682 break;
683 }
684
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000685 case ArithMul: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000686 JSValue left = forNode(node->child1()).value();
687 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000688 switch (node->binaryUseKind()) {
689 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000690 if (left && right && left.isInt32() && right.isInt32()) {
691 if (!shouldCheckOverflow(node->arithMode())) {
692 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
693 break;
694 }
695 double doubleResult = left.asNumber() * right.asNumber();
696 if (!shouldCheckNegativeZero(node->arithMode()))
697 doubleResult += 0; // Sanitizes zero.
698 JSValue valueResult = jsNumber(doubleResult);
699 if (valueResult.isInt32()) {
700 setConstant(node, valueResult);
701 break;
702 }
703 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000704 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000705 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000706 case Int52RepUse:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000707 if (left && right && left.isAnyInt() && right.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000708 double doubleResult = left.asNumber() * right.asNumber();
709 if (!shouldCheckNegativeZero(node->arithMode()))
710 doubleResult += 0;
711 JSValue valueResult = jsNumber(doubleResult);
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000712 if (valueResult.isAnyInt()) {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000713 setConstant(node, valueResult);
714 break;
715 }
716 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000717 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000718 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000719 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000720 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000721 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000722 break;
723 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000724 forNode(node).setType(
725 typeOfDoubleProduct(
726 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000727 break;
mark.lam@apple.com1d936142015-12-03 05:42:56 +0000728 case UntypedUse:
729 clobberWorld(node->origin.semantic, clobberLimit);
730 forNode(node).setType(m_graph, SpecBytecodeNumber);
731 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000732 default:
733 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000734 break;
735 }
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000736 break;
737 }
738
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000739 case ArithDiv: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000740 JSValue left = forNode(node->child1()).value();
741 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000742 switch (node->binaryUseKind()) {
743 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000744 if (left && right && left.isInt32() && right.isInt32()) {
745 double doubleResult = left.asNumber() / right.asNumber();
746 if (!shouldCheckOverflow(node->arithMode()))
747 doubleResult = toInt32(doubleResult);
748 else if (!shouldCheckNegativeZero(node->arithMode()))
749 doubleResult += 0; // Sanitizes zero.
750 JSValue valueResult = jsNumber(doubleResult);
751 if (valueResult.isInt32()) {
752 setConstant(node, valueResult);
753 break;
754 }
755 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000756 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000757 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000758 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000759 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000760 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000761 break;
762 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000763 forNode(node).setType(
764 typeOfDoubleQuotient(
765 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000766 break;
mark.lam@apple.com224ce4d2015-12-08 21:44:12 +0000767 case UntypedUse:
768 clobberWorld(node->origin.semantic, clobberLimit);
769 forNode(node).setType(m_graph, SpecBytecodeNumber);
770 break;
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000771 default:
772 RELEASE_ASSERT_NOT_REACHED();
773 break;
774 }
775 break;
776 }
777
778 case ArithMod: {
779 JSValue left = forNode(node->child1()).value();
780 JSValue right = forNode(node->child2()).value();
781 switch (node->binaryUseKind()) {
782 case Int32Use:
783 if (left && right && left.isInt32() && right.isInt32()) {
784 double doubleResult = fmod(left.asNumber(), right.asNumber());
785 if (!shouldCheckOverflow(node->arithMode()))
786 doubleResult = toInt32(doubleResult);
787 else if (!shouldCheckNegativeZero(node->arithMode()))
788 doubleResult += 0; // Sanitizes zero.
789 JSValue valueResult = jsNumber(doubleResult);
790 if (valueResult.isInt32()) {
791 setConstant(node, valueResult);
792 break;
793 }
794 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000795 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000796 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000797 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000798 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000799 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000800 break;
801 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000802 forNode(node).setType(
803 typeOfDoubleBinaryOp(
804 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000805 break;
806 default:
807 RELEASE_ASSERT_NOT_REACHED();
808 break;
809 }
810 break;
811 }
812
813 case ArithMin: {
814 JSValue left = forNode(node->child1()).value();
815 JSValue right = forNode(node->child2()).value();
816 switch (node->binaryUseKind()) {
817 case Int32Use:
818 if (left && right && left.isInt32() && right.isInt32()) {
819 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
820 break;
821 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000822 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000823 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000824 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000825 if (left && right && left.isNumber() && right.isNumber()) {
826 double a = left.asNumber();
827 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000828 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000829 break;
830 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000831 forNode(node).setType(
832 typeOfDoubleMinMax(
833 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000834 break;
835 default:
836 RELEASE_ASSERT_NOT_REACHED();
837 break;
838 }
839 break;
840 }
841
842 case ArithMax: {
843 JSValue left = forNode(node->child1()).value();
844 JSValue right = forNode(node->child2()).value();
845 switch (node->binaryUseKind()) {
846 case Int32Use:
847 if (left && right && left.isInt32() && right.isInt32()) {
848 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
849 break;
850 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000851 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000852 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000853 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000854 if (left && right && left.isNumber() && right.isNumber()) {
855 double a = left.asNumber();
856 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000857 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000858 break;
859 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000860 forNode(node).setType(
861 typeOfDoubleMinMax(
862 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000863 break;
864 default:
865 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000866 break;
867 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000868 break;
869 }
870
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000871 case ArithAbs: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000872 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000873 switch (node->child1().useKind()) {
874 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000875 if (child && child.isInt32()) {
876 JSValue result = jsNumber(fabs(child.asNumber()));
877 if (result.isInt32()) {
878 setConstant(node, result);
879 break;
880 }
881 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000882 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000883 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000884 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000885 if (child && child.isNumber()) {
basile_clement@apple.com88804062015-05-01 22:35:36 +0000886 setConstant(node, jsDoubleNumber(fabs(child.asNumber())));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000887 break;
888 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000889 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000890 break;
891 default:
892 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000893 break;
894 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000895 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000896 }
benjamin@webkit.org903025b2015-02-14 04:20:21 +0000897
898 case ArithPow: {
899 JSValue childY = forNode(node->child2()).value();
900 if (childY && childY.isNumber()) {
901 if (!childY.asNumber()) {
902 setConstant(node, jsDoubleNumber(1));
903 break;
904 }
905
906 JSValue childX = forNode(node->child1()).value();
907 if (childX && childX.isNumber()) {
908 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
909 break;
910 }
911 }
912 forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
913 break;
914 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000915
utatane.tea@gmail.comd2fca0a2015-12-15 03:51:42 +0000916 case ArithRandom: {
917 forNode(node).setType(m_graph, SpecDoubleReal);
918 break;
919 }
920
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000921 case ArithRound:
922 case ArithFloor:
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000923 case ArithCeil:
924 case ArithTrunc: {
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000925 JSValue operand = forNode(node->child1()).value();
926 if (operand && operand.isNumber()) {
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000927 double roundedValue = 0;
928 if (node->op() == ArithRound)
929 roundedValue = jsRound(operand.asNumber());
930 else if (node->op() == ArithFloor)
931 roundedValue = floor(operand.asNumber());
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000932 else if (node->op() == ArithCeil)
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000933 roundedValue = ceil(operand.asNumber());
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000934 else {
935 ASSERT(node->op() == ArithTrunc);
936 roundedValue = trunc(operand.asNumber());
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000937 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000938
939 if (producesInteger(node->arithRoundingMode())) {
940 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
941 if (roundedValueAsInt32 == roundedValue) {
942 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
943 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
944 setConstant(node, jsNumber(roundedValueAsInt32));
945 break;
946 }
947 } else {
948 setConstant(node, jsNumber(roundedValueAsInt32));
949 break;
950 }
951 }
952 } else {
953 setConstant(node, jsDoubleNumber(roundedValue));
954 break;
955 }
956 }
957 if (producesInteger(node->arithRoundingMode()))
mark.lam@apple.com39e9c982016-04-25 17:48:46 +0000958 forNode(node).setType(SpecInt32Only);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000959 else
960 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
961 break;
962 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000963
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000964 case ArithSqrt: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000965 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000966 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000967 setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000968 break;
969 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000970 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000971 break;
972 }
973
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000974 case ArithFRound: {
975 JSValue child = forNode(node->child1()).value();
976 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000977 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000978 break;
979 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000980 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000981 break;
982 }
983
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000984 case ArithSin: {
985 JSValue child = forNode(node->child1()).value();
basile_clement@apple.com818d6902015-05-11 18:41:51 +0000986 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000987 setConstant(node, jsDoubleNumber(sin(child.asNumber())));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000988 break;
989 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000990 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000991 break;
992 }
993
994 case ArithCos: {
995 JSValue child = forNode(node->child1()).value();
basile_clement@apple.com818d6902015-05-11 18:41:51 +0000996 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000997 setConstant(node, jsDoubleNumber(cos(child.asNumber())));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000998 break;
999 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +00001000 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001001 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001002 }
benjamin@webkit.org2b5682d2015-03-04 22:39:28 +00001003
1004 case ArithLog: {
1005 JSValue child = forNode(node->child1()).value();
1006 if (child && child.isNumber()) {
1007 setConstant(node, jsDoubleNumber(log(child.asNumber())));
1008 break;
1009 }
1010 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
1011 break;
1012 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001013
1014 case LogicalNot: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001015 switch (booleanResult(node, forNode(node->child1()))) {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001016 case DefinitelyTrue:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001017 setConstant(node, jsBoolean(false));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001018 break;
1019 case DefinitelyFalse:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001020 setConstant(node, jsBoolean(true));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001021 break;
1022 default:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001023 forNode(node).setType(SpecBoolean);
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001024 break;
1025 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001026 break;
1027 }
keith_miller@apple.com32fbcb72016-04-13 00:37:52 +00001028
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001029 case IsEmpty:
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001030 case IsJSArray:
fpizlo@apple.com1d216892012-04-12 00:55:44 +00001031 case IsUndefined:
1032 case IsBoolean:
1033 case IsNumber:
1034 case IsString:
1035 case IsObject:
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00001036 case IsObjectOrNull:
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001037 case IsFunction:
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001038 case IsRegExpObject:
1039 case IsTypedArrayView: {
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001040 AbstractValue child = forNode(node->child1());
1041 if (child.value()) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001042 bool constantWasSet = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001043 switch (node->op()) {
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001044 case IsJSArray:
1045 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
1046 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001047 case IsUndefined:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001048 setConstant(node, jsBoolean(
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001049 child.value().isCell()
1050 ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1051 : child.value().isUndefined()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001052 break;
1053 case IsBoolean:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001054 setConstant(node, jsBoolean(child.value().isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001055 break;
1056 case IsNumber:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001057 setConstant(node, jsBoolean(child.value().isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001058 break;
1059 case IsString:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001060 setConstant(node, jsBoolean(isJSString(child.value())));
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001061 break;
oliver@apple.come722ad02013-01-09 02:37:29 +00001062 case IsObject:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001063 setConstant(node, jsBoolean(child.value().isObject()));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00001064 break;
1065 case IsObjectOrNull:
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001066 if (child.value().isObject()) {
1067 JSObject* object = asObject(child.value());
1068 if (object->type() == JSFunctionType)
1069 setConstant(node, jsBoolean(false));
1070 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1071 setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1072 else {
1073 // FIXME: This could just call getCallData.
1074 // https://bugs.webkit.org/show_bug.cgi?id=144457
1075 constantWasSet = false;
1076 }
1077 } else
1078 setConstant(node, jsBoolean(child.value().isNull()));
1079 break;
1080 case IsFunction:
1081 if (child.value().isObject()) {
1082 JSObject* object = asObject(child.value());
1083 if (object->type() == JSFunctionType)
1084 setConstant(node, jsBoolean(true));
1085 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1086 setConstant(node, jsBoolean(false));
1087 else {
1088 // FIXME: This could just call getCallData.
1089 // https://bugs.webkit.org/show_bug.cgi?id=144457
1090 constantWasSet = false;
1091 }
1092 } else
1093 setConstant(node, jsBoolean(false));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001094 break;
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001095 case IsRegExpObject:
1096 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
1097 break;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001098 case IsEmpty:
1099 setConstant(node, jsBoolean(child.value().isEmpty()));
1100 break;
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001101 case IsTypedArrayView:
1102 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo()->typedArrayStorageType)));
1103 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001104 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +00001105 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001106 break;
1107 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001108 if (constantWasSet)
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001109 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001110 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001111
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001112 // FIXME: This code should really use AbstractValue::isType() and
1113 // AbstractValue::couldBeType().
1114 // https://bugs.webkit.org/show_bug.cgi?id=146870
1115
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001116 bool constantWasSet = false;
1117 switch (node->op()) {
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001118 case IsJSArray:
1119 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1120 if (!(child.m_type & ~SpecArray)) {
1121 setConstant(node, jsBoolean(true));
1122 constantWasSet = true;
1123 break;
1124 }
1125
1126 if (!(child.m_type & SpecObject)) {
1127 setConstant(node, jsBoolean(false));
1128 constantWasSet = true;
1129 break;
1130 }
1131
1132 break;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001133 case IsEmpty: {
1134 if (child.m_type && !(child.m_type & SpecEmpty)) {
1135 setConstant(node, jsBoolean(false));
1136 constantWasSet = true;
1137 break;
1138 }
1139
1140 if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1141 setConstant(node, jsBoolean(true));
1142 constantWasSet = true;
1143 break;
1144 }
1145
1146 break;
1147 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001148 case IsUndefined:
1149 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1150 // https://bugs.webkit.org/show_bug.cgi?id=144456
1151
1152 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1153 setConstant(node, jsBoolean(false));
1154 constantWasSet = true;
1155 break;
1156 }
1157
1158 break;
1159 case IsBoolean:
1160 if (!(child.m_type & ~SpecBoolean)) {
1161 setConstant(node, jsBoolean(true));
1162 constantWasSet = true;
1163 break;
1164 }
1165
1166 if (!(child.m_type & SpecBoolean)) {
1167 setConstant(node, jsBoolean(false));
1168 constantWasSet = true;
1169 break;
1170 }
1171
1172 break;
1173 case IsNumber:
1174 if (!(child.m_type & ~SpecFullNumber)) {
1175 setConstant(node, jsBoolean(true));
1176 constantWasSet = true;
1177 break;
1178 }
1179
1180 if (!(child.m_type & SpecFullNumber)) {
1181 setConstant(node, jsBoolean(false));
1182 constantWasSet = true;
1183 break;
1184 }
1185
1186 break;
1187 case IsString:
1188 if (!(child.m_type & ~SpecString)) {
1189 setConstant(node, jsBoolean(true));
1190 constantWasSet = true;
1191 break;
1192 }
1193
1194 if (!(child.m_type & SpecString)) {
1195 setConstant(node, jsBoolean(false));
1196 constantWasSet = true;
1197 break;
1198 }
1199
1200 break;
1201 case IsObject:
1202 if (!(child.m_type & ~SpecObject)) {
1203 setConstant(node, jsBoolean(true));
1204 constantWasSet = true;
1205 break;
1206 }
1207
1208 if (!(child.m_type & SpecObject)) {
1209 setConstant(node, jsBoolean(false));
1210 constantWasSet = true;
1211 break;
1212 }
1213
1214 break;
1215 case IsObjectOrNull:
1216 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1217 // https://bugs.webkit.org/show_bug.cgi?id=144456
1218
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001219 // These expressions are complicated to parse. A helpful way to parse this is that
1220 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1221 // disjoint set from S". Things like "T - S" means that, provided that S is a
1222 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1223 // mean the "union of T and S".
1224
1225 // Is the child's type an object that isn't an other-object (i.e. object that could
1226 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1227 // this to true.
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001228 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1229 setConstant(node, jsBoolean(true));
1230 constantWasSet = true;
1231 break;
1232 }
1233
fpizlo@apple.coma06fb552015-07-11 03:01:20 +00001234 // Is the child's type definitely not either of: an object that isn't a function,
1235 // or either undefined or null? Then: we should fold this to false. This means
1236 // for example that if it's any non-function object, including those that have
1237 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1238 // if it's undefined-or-null, since the type bits don't distinguish between
1239 // undefined (which should fold to false) and null (which should fold to true).
1240 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001241 setConstant(node, jsBoolean(false));
1242 constantWasSet = true;
1243 break;
1244 }
1245
1246 break;
1247 case IsFunction:
1248 if (!(child.m_type & ~SpecFunction)) {
1249 setConstant(node, jsBoolean(true));
1250 constantWasSet = true;
1251 break;
1252 }
1253
1254 if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
1255 setConstant(node, jsBoolean(false));
1256 constantWasSet = true;
1257 break;
1258 }
1259 break;
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00001260
1261 case IsRegExpObject:
1262 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1263 if (!(child.m_type & ~SpecRegExpObject)) {
1264 setConstant(node, jsBoolean(true));
1265 constantWasSet = true;
1266 break;
1267 }
1268 if (!(child.m_type & SpecObject)) {
1269 setConstant(node, jsBoolean(false));
1270 constantWasSet = true;
1271 break;
1272 }
1273 break;
1274
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00001275 case IsTypedArrayView:
1276 if (!(child.m_type & ~SpecTypedArrayView)) {
1277 setConstant(node, jsBoolean(true));
1278 constantWasSet = true;
1279 break;
1280 }
1281 if (!(child.m_type & SpecTypedArrayView)) {
1282 setConstant(node, jsBoolean(false));
1283 constantWasSet = true;
1284 break;
1285 }
1286 break;
1287
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001288 default:
1289 break;
1290 }
1291 if (constantWasSet)
1292 break;
1293
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001294 forNode(node).setType(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +00001295 break;
1296 }
oliver@apple.come722ad02013-01-09 02:37:29 +00001297
1298 case TypeOf: {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001299 VM* vm = m_codeBlock->vm();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001300 JSValue child = forNode(node->child1()).value();
1301 AbstractValue& abstractChild = forNode(node->child1());
oliver@apple.come722ad02013-01-09 02:37:29 +00001302 if (child) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001303 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001304 setConstant(node, *m_graph.freeze(typeString));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001305 break;
1306 }
1307
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001308 if (isFullNumberSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001309 setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001310 break;
1311 }
1312
1313 if (isStringSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001314 setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001315 break;
1316 }
fpizlo@apple.comd4335282015-04-30 17:36:26 +00001317
1318 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1319 // https://bugs.webkit.org/show_bug.cgi?id=144456
sbarati@apple.com0004bde2016-03-31 18:28:48 +00001320 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001321 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001322 break;
1323 }
1324
1325 if (isFunctionSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001326 setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001327 break;
1328 }
1329
1330 if (isBooleanSpeculation(abstractChild.m_type)) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001331 setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001332 break;
fpizlo@apple.comcd81b572013-02-11 21:39:35 +00001333 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001334
utatane.tea@gmail.com23c2df72015-05-14 17:36:12 +00001335 if (isSymbolSpeculation(abstractChild.m_type)) {
1336 setConstant(node, *m_graph.freeze(vm->smallStrings.symbolString()));
1337 break;
1338 }
1339
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001340 forNode(node).setType(m_graph, SpecStringIdent);
oliver@apple.come722ad02013-01-09 02:37:29 +00001341 break;
1342 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001343
1344 case CompareLess:
1345 case CompareLessEq:
1346 case CompareGreater:
1347 case CompareGreaterEq:
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001348 case CompareEq: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001349 JSValue leftConst = forNode(node->child1()).value();
1350 JSValue rightConst = forNode(node->child2()).value();
oliver@apple.combd15be82013-07-25 04:03:42 +00001351 if (leftConst && rightConst) {
1352 if (leftConst.isNumber() && rightConst.isNumber()) {
1353 double a = leftConst.asNumber();
1354 double b = rightConst.asNumber();
1355 switch (node->op()) {
1356 case CompareLess:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001357 setConstant(node, jsBoolean(a < b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001358 break;
1359 case CompareLessEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001360 setConstant(node, jsBoolean(a <= b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001361 break;
1362 case CompareGreater:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001363 setConstant(node, jsBoolean(a > b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001364 break;
1365 case CompareGreaterEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001366 setConstant(node, jsBoolean(a >= b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001367 break;
1368 case CompareEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001369 setConstant(node, jsBoolean(a == b));
oliver@apple.combd15be82013-07-25 04:03:42 +00001370 break;
1371 default:
1372 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001373 break;
1374 }
1375 break;
1376 }
1377
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00001378 if (leftConst.isString() && rightConst.isString()) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001379 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1380 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1381 if (a && b) {
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00001382 bool result;
1383 if (node->op() == CompareEq)
1384 result = WTF::equal(a, b);
1385 else if (node->op() == CompareLess)
1386 result = codePointCompare(a, b) < 0;
1387 else if (node->op() == CompareLessEq)
1388 result = codePointCompare(a, b) <= 0;
1389 else if (node->op() == CompareGreater)
1390 result = codePointCompare(a, b) > 0;
1391 else if (node->op() == CompareGreaterEq)
1392 result = codePointCompare(a, b) >= 0;
1393 else
1394 RELEASE_ASSERT_NOT_REACHED();
1395 setConstant(node, jsBoolean(result));
oliver@apple.combd15be82013-07-25 04:03:42 +00001396 break;
1397 }
1398 }
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001399
1400 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1401 setConstant(node, jsBoolean(asSymbol(leftConst)->privateName() == asSymbol(rightConst)->privateName()));
1402 break;
1403 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +00001404 }
1405
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001406 if (node->op() == CompareEq) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001407 SpeculatedType leftType = forNode(node->child1()).m_type;
1408 SpeculatedType rightType = forNode(node->child2()).m_type;
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001409 if (!valuesCouldBeEqual(leftType, rightType)) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001410 setConstant(node, jsBoolean(false));
1411 break;
1412 }
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00001413
1414 if (leftType == SpecOther)
1415 std::swap(leftType, rightType);
1416 if (rightType == SpecOther) {
1417 // Undefined and Null are always equal when compared to eachother.
1418 if (!(leftType & ~SpecOther)) {
1419 setConstant(node, jsBoolean(true));
1420 break;
1421 }
1422
1423 // Any other type compared to Null or Undefined is always false
1424 // as long as the MasqueradesAsUndefined watchpoint is valid.
1425 //
1426 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1427 // cases are always "false".
1428 if (!(leftType & (SpecObjectOther | SpecOther))) {
1429 setConstant(node, jsBoolean(false));
1430 break;
1431 }
1432
1433 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1434 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1435 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1436 setConstant(node, jsBoolean(false));
1437 break;
1438 }
1439 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001440 }
1441
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001442 if (node->child1() == node->child2()) {
1443 if (node->isBinaryUseKind(Int32Use) ||
1444 node->isBinaryUseKind(Int52RepUse) ||
1445 node->isBinaryUseKind(StringUse) ||
1446 node->isBinaryUseKind(BooleanUse) ||
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001447 node->isBinaryUseKind(SymbolUse) ||
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001448 node->isBinaryUseKind(StringIdentUse) ||
1449 node->isBinaryUseKind(ObjectUse) ||
1450 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1451 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1452 switch (node->op()) {
1453 case CompareLess:
1454 case CompareGreater:
1455 setConstant(node, jsBoolean(false));
1456 break;
1457 case CompareLessEq:
1458 case CompareGreaterEq:
1459 case CompareEq:
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001460 setConstant(node, jsBoolean(true));
1461 break;
1462 default:
1463 DFG_CRASH(m_graph, node, "Unexpected node type");
1464 break;
1465 }
1466 break;
1467 }
1468 }
1469
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001470 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001471 break;
1472 }
1473
fpizlo@apple.com312efcd2014-03-10 22:11:35 +00001474 case CompareStrictEq: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001475 Node* leftNode = node->child1().node();
1476 Node* rightNode = node->child2().node();
1477 JSValue left = forNode(leftNode).value();
1478 JSValue right = forNode(rightNode).value();
oliver@apple.combd15be82013-07-25 04:03:42 +00001479 if (left && right) {
oliver@apple.combd15be82013-07-25 04:03:42 +00001480 if (left.isString() && right.isString()) {
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001481 // We need this case because JSValue::strictEqual is otherwise too racy for
1482 // string comparisons.
oliver@apple.combd15be82013-07-25 04:03:42 +00001483 const StringImpl* a = asString(left)->tryGetValueImpl();
1484 const StringImpl* b = asString(right)->tryGetValueImpl();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001485 if (a && b) {
1486 setConstant(node, jsBoolean(WTF::equal(a, b)));
oliver@apple.combd15be82013-07-25 04:03:42 +00001487 break;
1488 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001489 } else {
1490 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1491 break;
oliver@apple.combd15be82013-07-25 04:03:42 +00001492 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001493 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001494
1495 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1496 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1497 if (!(leftLUB & rightLUB)) {
1498 setConstant(node, jsBoolean(false));
1499 break;
1500 }
1501
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001502 if (node->child1() == node->child2()) {
1503 if (node->isBinaryUseKind(BooleanUse) ||
1504 node->isBinaryUseKind(Int32Use) ||
1505 node->isBinaryUseKind(Int52RepUse) ||
1506 node->isBinaryUseKind(StringUse) ||
1507 node->isBinaryUseKind(StringIdentUse) ||
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00001508 node->isBinaryUseKind(SymbolUse) ||
fpizlo@apple.come815f4d2015-07-23 04:51:48 +00001509 node->isBinaryUseKind(ObjectUse) ||
1510 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1511 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1512 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1513 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1514 node->isBinaryUseKind(StringUse, UntypedUse) ||
1515 node->isBinaryUseKind(UntypedUse, StringUse)) {
1516 setConstant(node, jsBoolean(true));
1517 break;
1518 }
1519 }
1520
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001521 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001522 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001523 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001524
1525 case StringCharCodeAt:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001526 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001527 break;
1528
mark.lam@apple.com03a3e382016-01-08 18:44:36 +00001529 case StringFromCharCode:
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001530 forNode(node).setType(m_graph, SpecString);
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +00001531 break;
1532
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001533 case StringCharAt:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001534 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001535 break;
1536
1537 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001538 switch (node->arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001539 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +00001540 case Array::Unprofiled:
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00001541 case Array::SelectUsingArguments:
oliver@apple.com5598c182013-01-23 22:25:07 +00001542 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001543 break;
1544 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001545 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001546 break;
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00001547 case Array::Undecided: {
1548 JSValue index = forNode(node->child2()).value();
1549 if (index && index.isInt32() && index.asInt32() >= 0) {
1550 setConstant(node, jsUndefined());
1551 break;
1552 }
1553 forNode(node).setType(SpecOther);
1554 break;
1555 }
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001556 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001557 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001558 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001559 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001560 case Array::String:
oliver@apple.com211b3be2013-07-25 04:03:39 +00001561 if (node->arrayMode().isOutOfBounds()) {
1562 // If the watchpoint was still valid we could totally set this to be
1563 // SpecString | SpecOther. Except that we'd have to be careful. If we
1564 // tested the watchpoint state here then it could change by the time
1565 // we got to the backend. So to do this right, we'd have to get the
1566 // fixup phase to check the watchpoint state and then bake into the
1567 // GetByVal operation the fact that we're using a watchpoint, using
1568 // something like Array::SaneChain (except not quite, because that
1569 // implies an in-bounds access). None of this feels like it's worth it,
oliver@apple.come6427742013-07-25 04:05:12 +00001570 // so we're going with TOP for now. The same thing applies to
1571 // clobbering the world.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001572 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001573 forNode(node).makeHeapTop();
oliver@apple.com211b3be2013-07-25 04:03:39 +00001574 } else
1575 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001576 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001577 case Array::DirectArguments:
1578 case Array::ScopedArguments:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001579 forNode(node).makeHeapTop();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001580 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001581 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001582 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001583 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001584 forNode(node).makeHeapTop();
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001585 } else
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001586 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001587 break;
1588 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001589 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001590 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001591 forNode(node).makeHeapTop();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001592 } else if (node->arrayMode().isSaneChain())
fpizlo@apple.combeef4522014-04-16 22:44:00 +00001593 forNode(node).setType(SpecBytecodeDouble);
fpizlo@apple.com94e84e92012-11-11 02:56:12 +00001594 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001595 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001596 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001597 case Array::Contiguous:
1598 case Array::ArrayStorage:
1599 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001600 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001601 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001602 forNode(node).makeHeapTop();
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +00001603 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001604 case Array::Int8Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001605 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001606 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001607 case Array::Int16Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001608 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001609 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001610 case Array::Int32Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001611 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001612 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001613 case Array::Uint8Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001614 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001615 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001616 case Array::Uint8ClampedArray:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001617 forNode(node).setType(SpecInt32Only);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001618 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001619 case Array::Uint16Array:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001620 forNode(node).setType(SpecInt32Only);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001621 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001622 case Array::Uint32Array:
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001623 if (node->shouldSpeculateInt32())
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001624 forNode(node).setType(SpecInt32Only);
1625 else if (enableInt52() && node->shouldSpeculateAnyInt())
1626 forNode(node).setType(SpecAnyInt);
fpizlo@apple.com691ac792012-03-13 22:59:43 +00001627 else
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001628 forNode(node).setType(SpecAnyIntAsDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001629 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001630 case Array::Float32Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001631 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001632 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001633 case Array::Float64Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001634 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001635 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001636 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001637 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001638 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001639 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001640 break;
1641 }
1642
oliver@apple.come050d642013-10-19 00:09:28 +00001643 case PutByValDirect:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001644 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001645 case PutByValAlias: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001646 switch (node->arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001647 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001648 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001649 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001650 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001651 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001652 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001653 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001654 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001655 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001656 break;
1657 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001658 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001659 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001660 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001661 case Array::Contiguous:
1662 case Array::ArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001663 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001664 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001665 break;
1666 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001667 if (node->arrayMode().mayStoreToHole())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001668 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001669 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001670 default:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001671 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001672 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001673 break;
1674 }
1675
1676 case ArrayPush:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001677 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001678 forNode(node).setType(SpecBytecodeNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001679 break;
1680
1681 case ArrayPop:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001682 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001683 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001684 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001685
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001686 case GetMyArgumentByVal:
1687 case GetMyArgumentByValOutOfBounds: {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001688 JSValue index = forNode(node->child2()).m_value;
1689 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1690
1691 if (index && index.isInt32()) {
1692 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1693 // 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 +00001694 // paths as unreachable, or to return undefined. We could implement that eventually.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001695
1696 if (inlineCallFrame) {
1697 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
1698 forNode(node) = m_state.variables().operand(
1699 virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
1700 m_state.setFoundConstants(true);
1701 break;
1702 }
1703 } else {
1704 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
1705 forNode(node) = m_state.variables().argument(index.asInt32() + 1);
1706 m_state.setFoundConstants(true);
1707 break;
1708 }
1709 }
1710 }
1711
1712 if (inlineCallFrame) {
1713 // We have a bound on the types even though it's random access. Take advantage of this.
1714
1715 AbstractValue result;
1716 for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
1717 result.merge(
1718 m_state.variables().operand(
1719 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1720 }
1721
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001722 if (node->op() == GetMyArgumentByValOutOfBounds)
1723 result.merge(SpecOther);
1724
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001725 if (result.value())
1726 m_state.setFoundConstants(true);
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00001727
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001728 forNode(node) = result;
1729 break;
1730 }
1731
1732 forNode(node).makeHeapTop();
1733 break;
1734 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001735
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001736 case RegExpExec:
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001737 if (node->child2().useKind() == RegExpObjectUse
1738 && node->child3().useKind() == StringUse) {
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00001739 // This doesn't clobber the world since there are no conversions to perform.
1740 } else
1741 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001742 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
1743 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(globalObjectValue)) {
1744 if (!globalObject->isHavingABadTime()) {
1745 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1746 Structure* structure = globalObject->regExpMatchesArrayStructure();
1747 m_graph.registerStructure(structure);
1748 forNode(node).set(m_graph, structure);
1749 forNode(node).merge(SpecOther);
1750 break;
1751 }
1752 }
1753 }
1754 forNode(node).setType(m_graph, SpecOther | SpecArray);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001755 break;
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001756
1757 case RegExpTest:
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00001758 if (node->child2().useKind() == RegExpObjectUse
1759 && node->child3().useKind() == StringUse) {
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00001760 // This doesn't clobber the world since there are no conversions to perform.
1761 } else
1762 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.com67e0f332013-07-25 03:59:00 +00001763 forNode(node).setType(SpecBoolean);
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001764 break;
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001765
fpizlo@apple.come799b862016-03-01 21:18:42 +00001766 case StringReplace:
msaboff@apple.com69940442016-04-27 01:28:03 +00001767 case StringReplaceRegExp:
fpizlo@apple.come799b862016-03-01 21:18:42 +00001768 if (node->child1().useKind() == StringUse
1769 && node->child2().useKind() == RegExpObjectUse
1770 && node->child3().useKind() == StringUse) {
1771 // This doesn't clobber the world. It just reads and writes regexp state.
1772 } else
1773 clobberWorld(node->origin.semantic, clobberLimit);
1774 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1775 break;
1776
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001777 case Jump:
1778 break;
1779
1780 case Branch: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001781 Node* child = node->child1().node();
1782 BooleanResult result = booleanResult(node, forNode(child));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001783 if (result == DefinitelyTrue) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001784 m_state.setBranchDirection(TakeTrue);
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001785 break;
1786 }
1787 if (result == DefinitelyFalse) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001788 m_state.setBranchDirection(TakeFalse);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001789 break;
1790 }
1791 // FIXME: The above handles the trivial cases of sparse conditional
1792 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001793 // We can specialize the source variable's value on each direction of
1794 // the branch.
oliver@apple.com55d32d92013-07-25 04:05:03 +00001795 m_state.setBranchDirection(TakeBoth);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001796 break;
1797 }
oliver@apple.com9b7647b2013-07-25 04:03:00 +00001798
1799 case Switch: {
1800 // Nothing to do for now.
1801 // FIXME: Do sparse conditional things.
1802 break;
1803 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001804
1805 case Return:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001806 m_state.setIsValid(false);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001807 break;
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00001808
1809 case TailCall:
1810 case TailCallVarargs:
1811 case TailCallForwardVarargs:
1812 clobberWorld(node->origin.semantic, clobberLimit);
1813 m_state.setIsValid(false);
1814 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001815
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001816 case Throw:
1817 case ThrowReferenceError:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001818 m_state.setIsValid(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001819 break;
1820
1821 case ToPrimitive: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001822 JSValue childConst = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001823 if (childConst && childConst.isNumber()) {
1824 setConstant(node, childConst);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001825 break;
1826 }
1827
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001828 ASSERT(node->child1().useKind() == UntypedUse);
1829
utatane.tea@gmail.com23c2df72015-05-14 17:36:12 +00001830 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00001831 m_state.setFoundConstants(true);
1832 forNode(node) = forNode(node->child1());
1833 break;
1834 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001835
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001836 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001837
fpizlo@apple.com2b150e782015-08-27 23:59:57 +00001838 forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001839 break;
1840 }
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001841
1842 case ToNumber: {
1843 JSValue childConst = forNode(node->child1()).value();
1844 if (childConst && childConst.isNumber()) {
1845 setConstant(node, childConst);
1846 break;
1847 }
1848
1849 ASSERT(node->child1().useKind() == UntypedUse);
1850
1851 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
1852 m_state.setFoundConstants(true);
1853 forNode(node) = forNode(node->child1());
1854 break;
1855 }
1856
1857 clobberWorld(node->origin.semantic, clobberLimit);
1858 forNode(node).setType(m_graph, SpecBytecodeNumber);
1859 break;
1860 }
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001861
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +00001862 case ToString:
1863 case CallStringConstructor: {
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001864 switch (node->child1().useKind()) {
1865 case StringObjectUse:
1866 // This also filters that the StringObject has the primordial StringObject
1867 // structure.
oliver@apple.com33913872013-07-25 04:02:13 +00001868 filter(
1869 node->child1(),
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001870 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001871 break;
1872 case StringOrStringObjectUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001873 break;
1874 case CellUse:
1875 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001876 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001877 break;
1878 default:
1879 RELEASE_ASSERT_NOT_REACHED();
1880 break;
1881 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001882 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001883 break;
1884 }
1885
1886 case NewStringObject: {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001887 ASSERT(node->structure()->classInfo() == StringObject::info());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001888 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001889 break;
1890 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001891
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001892 case NewArray:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001893 forNode(node).set(
1894 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001895 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001896 break;
1897
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001898 case NewArrayBuffer:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001899 forNode(node).set(
1900 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001901 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001902 break;
1903
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001904 case NewArrayWithSize:
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001905 forNode(node).setType(m_graph, SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001906 break;
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001907
1908 case NewTypedArray:
1909 switch (node->child1().useKind()) {
1910 case Int32Use:
1911 break;
1912 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001913 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001914 break;
1915 default:
1916 RELEASE_ASSERT_NOT_REACHED();
1917 break;
1918 }
1919 forNode(node).set(
1920 m_graph,
fpizlo@apple.comcff2d0c2016-05-04 21:21:36 +00001921 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001922 node->typedArrayType()));
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001923 break;
fpizlo@apple.come799b862016-03-01 21:18:42 +00001924
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001925 case NewRegexp:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001926 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001927 break;
1928
oliver@apple.come2fe4ce2013-07-25 03:59:41 +00001929 case ToThis: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001930 AbstractValue& source = forNode(node->child1());
1931 AbstractValue& destination = forNode(node);
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001932 bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
utatane.tea@gmail.com44616d02016-01-31 23:05:10 +00001933
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001934 if (isToThisAnIdentity(strictMode, source)) {
utatane.tea@gmail.com44616d02016-01-31 23:05:10 +00001935 m_state.setFoundConstants(true);
1936 destination = source;
1937 break;
1938 }
1939
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001940 if (strictMode)
fpizlo@apple.com018818d2013-09-13 23:18:19 +00001941 destination.makeHeapTop();
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +00001942 else {
fpizlo@apple.com018818d2013-09-13 23:18:19 +00001943 destination = source;
1944 destination.merge(SpecObject);
1945 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001946 break;
1947 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001948
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001949 case CreateThis: {
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00001950 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00001951 forNode(node).setType(m_graph, SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001952 break;
1953 }
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001954
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001955 case NewObject:
fpizlo@apple.com62203aa2013-12-03 22:24:53 +00001956 ASSERT(node->structure());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001957 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001958 break;
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001959
1960 case CallObjectConstructor: {
1961 AbstractValue& source = forNode(node->child1());
1962 AbstractValue& destination = forNode(node);
1963
1964 if (!(source.m_type & ~SpecObject)) {
1965 m_state.setFoundConstants(true);
1966 destination = source;
1967 break;
1968 }
1969
1970 forNode(node).setType(m_graph, SpecObject);
1971 break;
1972 }
1973
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001974 case PhantomNewObject:
commit-queue@webkit.org88ab4e72015-04-24 02:23:36 +00001975 case PhantomNewFunction:
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00001976 case PhantomNewGeneratorFunction:
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001977 case PhantomCreateActivation:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001978 case PhantomDirectArguments:
1979 case PhantomClonedArguments:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001980 case BottomValue:
1981 m_state.setDidClobber(true); // Prevent constant folding.
1982 // This claims to return bottom.
1983 break;
1984
fpizlo@apple.com8ff74712015-03-17 15:50:44 +00001985 case PutHint:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001986 break;
1987
1988 case MaterializeNewObject: {
1989 StructureSet set;
1990
1991 m_phiChildren->forAllTransitiveIncomingValues(
1992 m_graph.varArgChild(node, 0).node(),
1993 [&] (Node* incoming) {
1994 set.add(incoming->castConstant<Structure*>());
1995 });
1996
1997 forNode(node).set(m_graph, set);
1998 break;
1999 }
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00002000
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002001 case CreateActivation:
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00002002 case MaterializeCreateActivation:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00002003 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002004 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002005 break;
fpizlo@apple.com1a724092013-11-28 07:10:10 +00002006
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002007 case CreateDirectArguments:
2008 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00002009 break;
2010
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002011 case CreateScopedArguments:
2012 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00002013 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002014
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002015 case CreateClonedArguments:
keith_miller@apple.com26367392016-03-14 20:55:15 +00002016 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00002017 break;
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00002018
2019 case NewGeneratorFunction:
2020 forNode(node).set(
2021 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
2022 break;
2023
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002024 case NewFunction:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00002025 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002026 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00002027 break;
2028
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002029 case GetCallee:
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00002030 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
2031 InferredValue* singleton = executable->singletonFunction();
2032 if (JSValue value = singleton->inferredValue()) {
2033 m_graph.watchpoints().addLazily(singleton);
2034 JSFunction* function = jsCast<JSFunction*>(value);
2035 setConstant(node, *m_graph.freeze(function));
2036 break;
2037 }
2038 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002039 forNode(node).setType(m_graph, SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002040 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002041
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +00002042 case GetArgumentCountIncludingThis:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002043 forNode(node).setType(SpecInt32Only);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002044 break;
2045
sbarati@apple.com855d5602015-11-30 20:36:54 +00002046 case GetRestLength:
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002047 forNode(node).setType(SpecInt32Only);
sbarati@apple.com855d5602015-11-30 20:36:54 +00002048 break;
2049
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002050 case GetGetter: {
2051 JSValue base = forNode(node->child1()).m_value;
2052 if (base) {
msaboff@apple.com9a7dc802014-12-09 19:52:40 +00002053 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2054 if (!getterSetter->isGetterNull()) {
2055 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002056 break;
2057 }
2058 }
2059
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002060 forNode(node).setType(m_graph, SpecObject);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002061 break;
2062 }
2063
2064 case GetSetter: {
2065 JSValue base = forNode(node->child1()).m_value;
2066 if (base) {
msaboff@apple.com9a7dc802014-12-09 19:52:40 +00002067 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2068 if (!getterSetter->isSetterNull()) {
2069 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002070 break;
2071 }
2072 }
2073
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002074 forNode(node).setType(m_graph, SpecObject);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002075 break;
2076 }
2077
fpizlo@apple.com90640ab2015-03-04 05:26:54 +00002078 case GetScope:
2079 if (JSValue base = forNode(node->child1()).m_value) {
2080 if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
2081 setConstant(node, *m_graph.freeze(function->scope()));
2082 break;
2083 }
2084 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002085 forNode(node).setType(m_graph, SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002086 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00002087
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002088 case SkipScope: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002089 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00002090 if (child) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002091 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002092 break;
2093 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002094 forNode(node).setType(m_graph, SpecObjectOther);
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00002095 break;
2096 }
2097
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00002098 case GetGlobalObject: {
2099 JSValue child = forNode(node->child1()).value();
2100 if (child) {
2101 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
2102 break;
2103 }
2104
2105 if (forNode(node->child1()).m_structure.isFinite()) {
2106 JSGlobalObject* globalObject = nullptr;
2107 bool ok = true;
2108 forNode(node->child1()).m_structure.forEach(
2109 [&] (Structure* structure) {
2110 if (!globalObject)
2111 globalObject = structure->globalObject();
2112 else if (globalObject != structure->globalObject())
2113 ok = false;
2114 });
2115 if (globalObject && ok) {
2116 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2117 break;
2118 }
2119 }
2120
2121 forNode(node).setType(m_graph, SpecObjectOther);
2122 break;
2123 }
2124
oliver@apple.com58c86752013-07-25 04:02:40 +00002125 case GetClosureVar:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002126 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
fpizlo@apple.com90640ab2015-03-04 05:26:54 +00002127 setConstant(node, *m_graph.freeze(value));
2128 break;
2129 }
commit-queue@webkit.org98686d02015-11-05 22:21:19 +00002130 forNode(node).makeBytecodeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002131 break;
2132
oliver@apple.com58c86752013-07-25 04:02:40 +00002133 case PutClosureVar:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002134 break;
fpizlo@apple.comef515142016-03-04 06:36:24 +00002135
2136 case GetRegExpObjectLastIndex:
2137 forNode(node).makeHeapTop();
2138 break;
2139
2140 case SetRegExpObjectLastIndex:
fpizlo@apple.com280ef002016-04-05 22:13:16 +00002141 case RecordRegExpCachedResult:
fpizlo@apple.comef515142016-03-04 06:36:24 +00002142 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002143
2144 case GetFromArguments:
2145 forNode(node).makeHeapTop();
2146 break;
2147
2148 case PutToArguments:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002149 break;
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002150
2151 case TryGetById:
2152 // FIXME: This should constant fold at least as well as the normal GetById case.
2153 // https://bugs.webkit.org/show_bug.cgi?id=156422
2154 forNode(node).makeHeapTop();
2155 break;
2156
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002157 case GetById:
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002158 case GetByIdFlush: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002159 if (!node->prediction()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002160 m_state.setIsValid(false);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00002161 break;
2162 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002163
2164 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002165 if (value.m_structure.isFinite()
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002166 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00002167 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2168 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002169 if (status.isSimple()) {
2170 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2171 // something more subtle?
2172 AbstractValue result;
2173 for (unsigned i = status.numVariants(); i--;) {
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00002174 // This thing won't give us a variant that involves prototypes. If it did, we'd
2175 // have more work to do here.
2176 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002177
2178 result.merge(
2179 m_graph.inferredValueForProperty(
2180 value, uid, status[i].offset(), m_state.structureClobberState()));
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002181 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002182 m_state.setFoundConstants(true);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002183 forNode(node) = result;
2184 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002185 }
2186 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002187
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002188 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002189 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002190 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002191 }
sbarati@apple.com23315d62016-05-09 20:17:23 +00002192
2193 case GetByValWithThis:
2194 case GetByIdWithThis:
2195 clobberWorld(node->origin.semantic, clobberLimit);
2196 forNode(node).makeHeapTop();
2197 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002198
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002199 case GetArrayLength: {
2200 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2201 forNode(node->child1()).m_value, node->arrayMode());
2202 if (view) {
2203 setConstant(node, jsNumber(view->length()));
2204 break;
2205 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002206 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002207 break;
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002208 }
keith_miller@apple.com485f5392016-04-18 20:02:24 +00002209
keith_miller@apple.com806e80d2016-05-05 17:30:02 +00002210 case DeleteById:
2211 case DeleteByVal: {
keith_miller@apple.com485f5392016-04-18 20:02:24 +00002212 // FIXME: This could decide if the delete will be successful based on the set of structures that
2213 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2214 clobberWorld(node->origin.semantic, clobberLimit);
2215 forNode(node).setType(SpecBoolean);
2216 break;
2217 }
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002218
oliver@apple.com500b53a2013-07-25 04:05:25 +00002219 case CheckStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002220 AbstractValue& value = forNode(node->child1());
oliver@apple.com33913872013-07-25 04:02:13 +00002221
2222 StructureSet& set = node->structureSet();
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002223
2224 // It's interesting that we could have proven that the object has a larger structure set
2225 // that includes the set we're testing. In that case we could make the structure check
2226 // more efficient. We currently don't.
2227
fpizlo@apple.com12835772015-09-21 20:49:04 +00002228 if (value.m_structure.isSubsetOf(set))
oliver@apple.com55d32d92013-07-25 04:05:03 +00002229 m_state.setFoundConstants(true);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002230
2231 SpeculatedType admittedTypes = SpecNone;
2232 switch (node->child1().useKind()) {
2233 case CellUse:
2234 case KnownCellUse:
2235 admittedTypes = SpecNone;
2236 break;
2237 case CellOrOtherUse:
2238 admittedTypes = SpecOther;
2239 break;
2240 default:
2241 DFG_CRASH(m_graph, node, "Bad use kind");
oliver@apple.com33913872013-07-25 04:02:13 +00002242 break;
2243 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002244
2245 filter(value, set, admittedTypes);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002246 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00002247 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00002248
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002249 case CheckStructureImmediate: {
2250 // FIXME: This currently can only reason about one structure at a time.
2251 // https://bugs.webkit.org/show_bug.cgi?id=136988
2252
2253 AbstractValue& value = forNode(node->child1());
2254 StructureSet& set = node->structureSet();
2255
2256 if (value.value()) {
2257 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
2258 if (set.contains(structure)) {
2259 m_state.setFoundConstants(true);
2260 break;
2261 }
2262 }
2263 m_state.setIsValid(false);
2264 break;
2265 }
2266
2267 if (m_phiChildren) {
2268 bool allGood = true;
2269 m_phiChildren->forAllTransitiveIncomingValues(
2270 node,
2271 [&] (Node* incoming) {
2272 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
2273 if (set.contains(structure))
2274 return;
2275 }
2276 allGood = false;
2277 });
2278 if (allGood) {
2279 m_state.setFoundConstants(true);
2280 break;
2281 }
2282 }
2283
2284 if (Structure* structure = set.onlyStructure()) {
2285 filterByValue(node->child1(), *m_graph.freeze(structure));
2286 break;
2287 }
2288
2289 // Aw shucks, we can't do anything!
2290 break;
2291 }
2292
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002293 case PutStructure:
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002294 if (!forNode(node->child1()).m_structure.isClear()) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002295 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
2296 m_state.setFoundConstants(true);
2297 else {
2298 observeTransition(
2299 clobberLimit, node->transition()->previous, node->transition()->next);
2300 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
2301 }
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00002302 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002303 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00002304 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00002305 case AllocatePropertyStorage:
2306 case ReallocatePropertyStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002307 forNode(node).clear(); // The result is not a JS value.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002308 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002309 case CheckArray: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002310 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002311 m_state.setFoundConstants(true);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002312 break;
2313 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002314 switch (node->arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002315 case Array::String:
oliver@apple.com33913872013-07-25 04:02:13 +00002316 filter(node->child1(), SpecString);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002317 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002318 case Array::Int32:
2319 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00002320 case Array::Contiguous:
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00002321 case Array::Undecided:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00002322 case Array::ArrayStorage:
2323 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002324 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002325 case Array::DirectArguments:
2326 filter(node->child1(), SpecDirectArguments);
2327 break;
2328 case Array::ScopedArguments:
2329 filter(node->child1(), SpecScopedArguments);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002330 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002331 case Array::Int8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002332 filter(node->child1(), SpecInt8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002333 break;
2334 case Array::Int16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002335 filter(node->child1(), SpecInt16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002336 break;
2337 case Array::Int32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002338 filter(node->child1(), SpecInt32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002339 break;
2340 case Array::Uint8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002341 filter(node->child1(), SpecUint8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002342 break;
2343 case Array::Uint8ClampedArray:
oliver@apple.com33913872013-07-25 04:02:13 +00002344 filter(node->child1(), SpecUint8ClampedArray);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002345 break;
2346 case Array::Uint16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002347 filter(node->child1(), SpecUint16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002348 break;
2349 case Array::Uint32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002350 filter(node->child1(), SpecUint32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002351 break;
2352 case Array::Float32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002353 filter(node->child1(), SpecFloat32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002354 break;
2355 case Array::Float64Array:
oliver@apple.com33913872013-07-25 04:02:13 +00002356 filter(node->child1(), SpecFloat64Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002357 break;
keith_miller@apple.com59bba5d2015-10-16 22:18:42 +00002358 case Array::AnyTypedArray:
2359 filter(node->child1(), SpecTypedArrayView);
2360 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00002361 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002362 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00002363 break;
2364 }
oliver@apple.com52be8f82013-07-25 04:04:33 +00002365 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00002366 break;
2367 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00002368 case Arrayify: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002369 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002370 m_state.setFoundConstants(true);
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00002371 break;
2372 }
benjamin@webkit.org9f46ddc2015-04-30 04:40:55 +00002373 ASSERT(node->arrayMode().conversion() == Array::Convert);
oliver@apple.come17632e2013-07-25 04:05:31 +00002374 clobberStructures(clobberLimit);
oliver@apple.com33913872013-07-25 04:02:13 +00002375 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.com497c7512012-09-19 01:20:52 +00002376 break;
2377 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00002378 case ArrayifyToStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002379 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002380 if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
oliver@apple.com55d32d92013-07-25 04:05:03 +00002381 m_state.setFoundConstants(true);
oliver@apple.come17632e2013-07-25 04:05:31 +00002382 clobberStructures(clobberLimit);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002383
2384 // We have a bunch of options of how to express the abstract set at this point. Let set S
2385 // be the set of structures that the value had before clobbering and assume that all of
2386 // them are watchable. The new value should be the least expressible upper bound of the
2387 // intersection of "values that currently have structure = node->structure()" and "values
2388 // that have structure in S plus any structure transition-reachable from S". Assume that
2389 // node->structure() is not in S but it is transition-reachable from S. Then we would
2390 // like to say that the result is "values that have structure = node->structure() until
2391 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
2392 // we must choose between:
2393 //
2394 // 1) "values that currently have structure = node->structure()". This is a valid
2395 // superset of the value that we really want, and it's specific enough to satisfy the
2396 // preconditions of the array access that this is guarding. It's also specific enough
2397 // to allow relevant optimizations in the case that we didn't have a contradiction
2398 // like in this example. Notice that in the abscence of any contradiction, this result
2399 // is precise rather than being a conservative LUB.
2400 //
2401 // 2) "values that currently hava structure in S plus any structure transition-reachable
2402 // from S". This is also a valid superset of the value that we really want, but it's
2403 // not specific enough to satisfy the preconditions of the array access that this is
2404 // guarding - so playing such shenanigans would preclude us from having assertions on
2405 // the typing preconditions of any array accesses. This would also not be a desirable
2406 // answer in the absence of a contradiction.
2407 //
2408 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
2409 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
2410 // yet.
2411 value.set(m_graph, node->structure());
fpizlo@apple.com99f37622012-10-29 04:02:08 +00002412 break;
2413 }
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002414 case GetIndexedPropertyStorage: {
2415 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2416 forNode(node->child1()).m_value, node->arrayMode());
2417 if (view)
2418 m_state.setFoundConstants(true);
2419 forNode(node).clear();
2420 break;
2421 }
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00002422 case ConstantStoragePointer: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002423 forNode(node).clear();
oliver@apple.com43e511c2011-12-09 08:45:46 +00002424 break;
2425 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +00002426
2427 case GetTypedArrayByteOffset: {
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00002428 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
2429 if (view) {
2430 setConstant(node, jsNumber(view->byteOffset()));
2431 break;
2432 }
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002433 forNode(node).setType(SpecInt32Only);
fpizlo@apple.com537a4772013-08-19 23:16:01 +00002434 break;
2435 }
2436
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002437 case GetByOffset: {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00002438 StorageAccessData& data = node->storageAccessData();
fpizlo@apple.com12835772015-09-21 20:49:04 +00002439 UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2440
2441 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2442 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2443 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2444 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2445 // on the type that ByteCodeParser was able to prove.
2446 AbstractValue value = m_graph.inferredValueForProperty(
2447 forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2448
2449 // It's possible that the type that ByteCodeParser came up with is better.
2450 AbstractValue typeFromParsing;
2451 typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2452 value.filter(typeFromParsing);
2453
2454 // If we decide that there does not exist any value that this can return, then it's probably
2455 // because the compilation was already invalidated.
2456 if (value.isClear())
2457 m_state.setIsValid(false);
2458
2459 forNode(node) = value;
2460 if (value.m_value)
2461 m_state.setFoundConstants(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002462 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002463 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002464
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002465 case GetGetterSetterByOffset: {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00002466 StorageAccessData& data = node->storageAccessData();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002467 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2468 if (result && jsDynamicCast<GetterSetter*>(result)) {
2469 setConstant(node, *m_graph.freeze(result));
2470 break;
2471 }
2472
mark.lam@apple.com8d3c2692016-04-28 06:54:54 +00002473 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002474 break;
2475 }
2476
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002477 case MultiGetByOffset: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002478 // This code will filter the base value in a manner that is possibly different (either more
2479 // or less precise) than the way it would be filtered if this was strength-reduced to a
2480 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2481 // different things about the code, so long as all of them are sound. That even includes
2482 // one guy proving that code should never execute (due to a contradiction) and another guy
2483 // not finding that contradiction. If someone ever proved that there would be a
2484 // contradiction then there must always be a contradiction even if subsequent passes don't
2485 // realize it. This is the case here.
2486
2487 // Ordinarily you have to be careful with calling setFoundConstants()
2488 // because of the effect on compile times, but this node is FTL-only.
2489 m_state.setFoundConstants(true);
2490
fpizlo@apple.com12835772015-09-21 20:49:04 +00002491 UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2492
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002493 AbstractValue base = forNode(node->child1());
2494 StructureSet baseSet;
2495 AbstractValue result;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00002496 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
2497 StructureSet set = getCase.set();
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002498 set.filter(base);
2499 if (set.isEmpty())
2500 continue;
2501 baseSet.merge(set);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002502
2503 switch (getCase.method().kind()) {
2504 case GetByOffsetMethod::Constant: {
2505 AbstractValue thisResult;
2506 thisResult.set(
2507 m_graph,
2508 *getCase.method().constant(),
2509 m_state.structureClobberState());
2510 result.merge(thisResult);
2511 break;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002512 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00002513
2514 case GetByOffsetMethod::Load: {
2515 result.merge(
2516 m_graph.inferredValueForProperty(
2517 set, uid, m_state.structureClobberState()));
2518 break;
2519 }
2520
2521 default: {
2522 result.makeHeapTop();
2523 break;
2524 } }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002525 }
2526
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002527 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2528 m_state.setIsValid(false);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002529
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002530 forNode(node) = result;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00002531 break;
2532 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002533
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002534 case PutByOffset: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002535 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002536 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00002537
2538 case MultiPutByOffset: {
fpizlo@apple.com43219522014-02-25 02:02:50 +00002539 StructureSet newSet;
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002540 TransitionVector transitions;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002541
2542 // Ordinarily you have to be careful with calling setFoundConstants()
2543 // because of the effect on compile times, but this node is FTL-only.
2544 m_state.setFoundConstants(true);
2545
2546 AbstractValue base = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002547 AbstractValue originalValue = forNode(node->child2());
2548 AbstractValue resultingValue;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002549
fpizlo@apple.com43219522014-02-25 02:02:50 +00002550 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2551 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002552 StructureSet thisSet = variant.oldStructure();
2553 thisSet.filter(base);
2554 if (thisSet.isEmpty())
2555 continue;
fpizlo@apple.com12835772015-09-21 20:49:04 +00002556
2557 AbstractValue thisValue = originalValue;
2558 thisValue.filter(m_graph, variant.requiredType());
2559 resultingValue.merge(thisValue);
2560
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002561 if (variant.kind() == PutByIdVariant::Transition) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002562 if (thisSet.onlyStructure() != variant.newStructure()) {
2563 transitions.append(
2564 Transition(variant.oldStructureForTransition(), variant.newStructure()));
2565 } // else this is really a replace.
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002566 newSet.add(variant.newStructure());
2567 } else {
2568 ASSERT(variant.kind() == PutByIdVariant::Replace);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002569 newSet.merge(thisSet);
fpizlo@apple.com43219522014-02-25 02:02:50 +00002570 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00002571 }
2572
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002573 observeTransitions(clobberLimit, transitions);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002574 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2575 m_state.setIsValid(false);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002576 forNode(node->child2()) = resultingValue;
2577 if (!!originalValue && !resultingValue)
2578 m_state.setIsValid(false);
fpizlo@apple.com43219522014-02-25 02:02:50 +00002579 break;
2580 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002581
2582 case GetExecutable: {
fpizlo@apple.com731e7762014-08-25 22:35:40 +00002583 JSValue value = forNode(node->child1()).value();
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002584 if (value) {
2585 JSFunction* function = jsDynamicCast<JSFunction*>(value);
2586 if (function) {
2587 setConstant(node, *m_graph.freeze(function->executable()));
2588 break;
2589 }
2590 }
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002591 forNode(node).setType(m_graph, SpecCellOther);
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002592 break;
2593 }
2594
2595 case CheckCell: {
2596 JSValue value = forNode(node->child1()).value();
2597 if (value == node->cellOperand()->value()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002598 m_state.setFoundConstants(true);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002599 ASSERT(value);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002600 break;
2601 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002602 filterByValue(node->child1(), *node->cellOperand());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002603 break;
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00002604 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +00002605
2606 case CheckNotEmpty: {
2607 AbstractValue& value = forNode(node->child1());
2608 if (!(value.m_type & SpecEmpty)) {
2609 m_state.setFoundConstants(true);
2610 break;
2611 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00002612
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +00002613 filter(value, ~SpecEmpty);
2614 break;
2615 }
2616
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002617 case CheckIdent: {
2618 AbstractValue& value = forNode(node->child1());
2619 UniquedStringImpl* uid = node->uidOperand();
2620 ASSERT(uid->isSymbol() ? !(value.m_type & ~SpecSymbol) : !(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
2621
2622 JSValue childConstant = value.value();
2623 if (childConstant) {
2624 if (uid->isSymbol()) {
2625 ASSERT(childConstant.isSymbol());
2626 if (asSymbol(childConstant)->privateName().uid() == uid) {
2627 m_state.setFoundConstants(true);
2628 break;
2629 }
2630 } else {
2631 ASSERT(childConstant.isString());
2632 if (asString(childConstant)->tryGetValueImpl() == uid) {
2633 m_state.setFoundConstants(true);
2634 break;
2635 }
2636 }
2637 }
2638
2639 filter(value, uid->isSymbol() ? SpecSymbol : SpecStringIdent);
2640 break;
2641 }
2642
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00002643 case CheckInBounds: {
2644 JSValue left = forNode(node->child1()).value();
2645 JSValue right = forNode(node->child2()).value();
2646 if (left && right && left.isInt32() && right.isInt32()
2647 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2648 m_state.setFoundConstants(true);
2649 break;
2650 }
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00002651 break;
2652 }
2653
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002654 case PutById:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +00002655 case PutByIdFlush:
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002656 case PutByIdDirect: {
2657 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com12835772015-09-21 20:49:04 +00002658 if (value.m_structure.isFinite()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002659 PutByIdStatus status = PutByIdStatus::computeFor(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002660 m_graph.globalObjectFor(node->origin.semantic),
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002661 value.m_structure.set(),
oliver@apple.com90fce822013-07-25 04:00:13 +00002662 m_graph.identifiers()[node->identifierNumber()],
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002663 node->op() == PutByIdDirect);
fpizlo@apple.com12835772015-09-21 20:49:04 +00002664
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002665 if (status.isSimple()) {
2666 StructureSet newSet;
2667 TransitionVector transitions;
2668
2669 for (unsigned i = status.numVariants(); i--;) {
2670 const PutByIdVariant& variant = status[i];
2671 if (variant.kind() == PutByIdVariant::Transition) {
2672 transitions.append(
2673 Transition(
2674 variant.oldStructureForTransition(), variant.newStructure()));
fpizlo@apple.com920c1672014-08-19 00:55:31 +00002675 m_graph.registerStructure(variant.newStructure());
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002676 newSet.add(variant.newStructure());
2677 } else {
2678 ASSERT(variant.kind() == PutByIdVariant::Replace);
2679 newSet.merge(variant.oldStructure());
2680 }
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002681 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002682
2683 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
fpizlo@apple.com9f624432014-07-26 19:06:44 +00002684 m_state.setFoundConstants(true);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002685
2686 observeTransitions(clobberLimit, transitions);
2687 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2688 m_state.setIsValid(false);
2689 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00002690 }
2691 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002692
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002693 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002694 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002695 }
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00002696
sbarati@apple.com23315d62016-05-09 20:17:23 +00002697 case PutByValWithThis:
2698 case PutByIdWithThis:
2699 clobberWorld(node->origin.semantic, clobberLimit);
2700 break;
2701
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00002702 case PutGetterById:
2703 case PutSetterById:
2704 case PutGetterSetterById:
2705 case PutGetterByVal:
2706 case PutSetterByVal: {
2707 clobberWorld(node->origin.semantic, clobberLimit);
2708 break;
2709 }
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002710
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002711 case In: {
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002712 // FIXME: We can determine when the property definitely exists based on abstract
2713 // value information.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002714 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00002715 forNode(node).setType(SpecBoolean);
2716 break;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002717 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002718
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002719 case GetEnumerableLength: {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002720 forNode(node).setType(SpecInt32Only);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002721 break;
2722 }
2723 case HasGenericProperty: {
2724 forNode(node).setType(SpecBoolean);
2725 break;
2726 }
2727 case HasStructureProperty: {
2728 forNode(node).setType(SpecBoolean);
2729 break;
2730 }
2731 case HasIndexedProperty: {
2732 ArrayMode mode = node->arrayMode();
2733 switch (mode.type()) {
2734 case Array::Int32:
2735 case Array::Double:
2736 case Array::Contiguous:
2737 case Array::ArrayStorage: {
2738 break;
2739 }
2740 default: {
2741 clobberWorld(node->origin.semantic, clobberLimit);
2742 break;
2743 }
2744 }
2745 forNode(node).setType(SpecBoolean);
2746 break;
2747 }
2748 case GetDirectPname: {
2749 clobberWorld(node->origin.semantic, clobberLimit);
2750 forNode(node).makeHeapTop();
2751 break;
2752 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002753 case GetPropertyEnumerator: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002754 forNode(node).setType(m_graph, SpecCell);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002755 break;
2756 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002757 case GetEnumeratorStructurePname: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002758 forNode(node).setType(m_graph, SpecString | SpecOther);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002759 break;
2760 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00002761 case GetEnumeratorGenericPname: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002762 forNode(node).setType(m_graph, SpecString | SpecOther);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002763 break;
2764 }
2765 case ToIndexString: {
fpizlo@apple.combaac2b92015-04-29 15:55:54 +00002766 forNode(node).setType(m_graph, SpecString);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002767 break;
2768 }
2769
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002770 case GetGlobalVar:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002771 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002772 break;
sbarati@apple.come67fd782016-04-19 01:38:30 +00002773
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002774 case GetGlobalLexicalVariable:
2775 forNode(node).makeBytecodeTop();
2776 break;
sbarati@apple.come67fd782016-04-19 01:38:30 +00002777
2778 case GetDynamicVar:
2779 clobberWorld(node->origin.semantic, clobberLimit);
2780 forNode(node).makeBytecodeTop();
2781 break;
2782
2783 case PutDynamicVar:
2784 clobberWorld(node->origin.semantic, clobberLimit);
2785 break;
2786
2787 case ResolveScope:
2788 clobberWorld(node->origin.semantic, clobberLimit);
2789 forNode(node).setType(m_graph, SpecObject);
2790 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00002791
oliver@apple.com58c86752013-07-25 04:02:40 +00002792 case VarInjectionWatchpoint:
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002793 case PutGlobalVariable:
fpizlo@apple.com86468342013-11-27 02:47:43 +00002794 case NotifyWrite:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002795 break;
2796
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002797 case OverridesHasInstance:
2798 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002799 break;
2800
2801 case InstanceOf:
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002802 // Sadly, we don't propagate the fact that we've done InstanceOf
2803 forNode(node).setType(SpecBoolean);
2804 break;
2805
2806 case InstanceOfCustom:
2807 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00002808 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002809 break;
2810
2811 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002812 RELEASE_ASSERT(m_graph.m_form == SSA);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002813 // The state of this node would have already been decided, but it may have become a
2814 // constant, in which case we'd like to know.
2815 if (forNode(node).m_value)
2816 m_state.setFoundConstants(true);
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002817 break;
2818
2819 case Upsilon: {
oliver@apple.com02e7a972013-07-25 04:05:04 +00002820 m_state.createValueForNode(node->phi());
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002821 forNode(node->phi()) = forNode(node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002822 break;
2823 }
2824
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00002825 case Flush:
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +00002826 case PhantomLocal:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002827 break;
2828
2829 case Call:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002830 case TailCallInlinedCaller:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002831 case Construct:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00002832 case CallVarargs:
2833 case CallForwardVarargs:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002834 case TailCallVarargsInlinedCaller:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00002835 case ConstructVarargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002836 case ConstructForwardVarargs:
msaboff@apple.coma3dc7532015-09-24 21:42:59 +00002837 case TailCallForwardVarargsInlinedCaller:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00002838 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00002839 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002840 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002841
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002842 case ForceOSRExit:
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002843 case CheckBadCell:
oliver@apple.com55d32d92013-07-25 04:05:03 +00002844 m_state.setIsValid(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002845 break;
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00002846
2847 case InvalidationPoint:
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002848 forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2849 m_state.setStructureClobberState(StructuresAreWatched);
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00002850 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002851
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00002852 case CheckWatchdogTimer:
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002853 case LogShadowChickenPrologue:
2854 case LogShadowChickenTail:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00002855 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002856
saambarati1@gmail.comdaf10202014-10-01 20:47:51 +00002857 case ProfileType:
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002858 case ProfileControlFlow:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002859 case Phantom:
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00002860 case CountExecution:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002861 case CheckTierUpInLoop:
2862 case CheckTierUpAtReturn:
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002863 case CheckTypeInfoFlags:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002864 break;
2865
sbarati@apple.comc0722da2015-11-20 02:37:47 +00002866 case CopyRest:
2867 break;
2868
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002869 case Check: {
2870 // Simplify out checks that don't actually do checking.
2871 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2872 Edge edge = node->children.child(i);
2873 if (!edge)
2874 break;
2875 if (edge.isProved() || edge.willNotHaveCheck()) {
2876 m_state.setFoundConstants(true);
2877 break;
2878 }
2879 }
2880 break;
2881 }
2882
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00002883 case SetFunctionName: {
2884 clobberWorld(node->origin.semantic, clobberLimit);
2885 break;
2886 }
2887
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00002888 case StoreBarrier: {
2889 filter(node->child1(), SpecCell);
2890 break;
2891 }
2892
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002893 case CheckTierUpAndOSREnter:
2894 case LoopHint:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002895 case ZombieHint:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00002896 case ExitOK:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002897 break;
oliver@apple.com1fc04182013-08-19 19:40:13 +00002898
2899 case Unreachable:
fpizlo@apple.comf4b38f02016-05-05 19:20:23 +00002900 // It may be that during a previous run of AI we proved that something was unreachable, but
2901 // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
2902 // monotonically stronger over time. So, we don't assert that AI doesn't reach the
2903 // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
2904 // crash whenever AI fails to be as powerful on run K as it was on run K-1.
2905 m_state.setIsValid(false);
2906 break;
2907
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00002908 case LastNodeType:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00002909 case ArithIMul:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00002910 case FiatInt52:
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002911 DFG_CRASH(m_graph, node, "Unexpected node type");
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00002912 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002913 }
2914
oliver@apple.com55d32d92013-07-25 04:05:03 +00002915 return m_state.isValid();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002916}
2917
oliver@apple.com55d32d92013-07-25 04:05:03 +00002918template<typename AbstractStateType>
2919bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002920{
oliver@apple.com55d32d92013-07-25 04:05:03 +00002921 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002922}
2923
oliver@apple.com55d32d92013-07-25 04:05:03 +00002924template<typename AbstractStateType>
2925bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002926{
oliver@apple.com55d32d92013-07-25 04:05:03 +00002927 Node* node = m_state.block()->at(indexInBlock);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002928
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002929 startExecuting();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00002930 executeEdges(node);
2931 return executeEffects(indexInBlock, node);
2932}
2933
oliver@apple.com55d32d92013-07-25 04:05:03 +00002934template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +00002935bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2936{
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002937 startExecuting();
oliver@apple.come17632e2013-07-25 04:05:31 +00002938 executeEdges(node);
2939 return executeEffects(UINT_MAX, node);
2940}
2941
2942template<typename AbstractStateType>
oliver@apple.com55d32d92013-07-25 04:05:03 +00002943void AbstractInterpreter<AbstractStateType>::clobberWorld(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002944 const CodeOrigin&, unsigned clobberLimit)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00002945{
oliver@apple.come17632e2013-07-25 04:05:31 +00002946 clobberStructures(clobberLimit);
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00002947}
2948
oliver@apple.com55d32d92013-07-25 04:05:03 +00002949template<typename AbstractStateType>
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002950template<typename Functor>
2951void AbstractInterpreter<AbstractStateType>::forAllValues(
2952 unsigned clobberLimit, Functor& functor)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002953{
oliver@apple.come17632e2013-07-25 04:05:31 +00002954 if (clobberLimit >= m_state.block()->size())
2955 clobberLimit = m_state.block()->size();
2956 else
2957 clobberLimit++;
2958 ASSERT(clobberLimit <= m_state.block()->size());
2959 for (size_t i = clobberLimit; i--;)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002960 functor(forNode(m_state.block()->at(i)));
oliver@apple.com96feafa2013-07-25 04:04:57 +00002961 if (m_graph.m_form == SSA) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002962 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2963 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
oliver@apple.com96feafa2013-07-25 04:04:57 +00002964 for (; iter != end; ++iter)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002965 functor(forNode(*iter));
oliver@apple.com96feafa2013-07-25 04:04:57 +00002966 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00002967 for (size_t i = m_state.variables().numberOfArguments(); i--;)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002968 functor(m_state.variables().argument(i));
oliver@apple.com55d32d92013-07-25 04:05:03 +00002969 for (size_t i = m_state.variables().numberOfLocals(); i--;)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002970 functor(m_state.variables().local(i));
2971}
2972
2973template<typename AbstractStateType>
2974void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
2975{
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00002976 forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
2977 setDidClobber();
2978}
2979
2980template<typename AbstractStateType>
2981void AbstractInterpreter<AbstractStateType>::observeTransition(
2982 unsigned clobberLimit, Structure* from, Structure* to)
2983{
2984 AbstractValue::TransitionObserver transitionObserver(from, to);
2985 forAllValues(clobberLimit, transitionObserver);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002986
2987 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 +00002988}
2989
2990template<typename AbstractStateType>
2991void AbstractInterpreter<AbstractStateType>::observeTransitions(
2992 unsigned clobberLimit, const TransitionVector& vector)
2993{
2994 AbstractValue::TransitionsObserver transitionsObserver(vector);
2995 forAllValues(clobberLimit, transitionsObserver);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002996
2997 if (!ASSERT_DISABLED) {
2998 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2999 for (unsigned i = vector.size(); i--;)
3000 ASSERT(!vector[i].previous->dfgShouldWatch());
3001 }
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003002}
3003
3004template<typename AbstractStateType>
3005void AbstractInterpreter<AbstractStateType>::setDidClobber()
3006{
oliver@apple.com55d32d92013-07-25 04:05:03 +00003007 m_state.setDidClobber(true);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003008 m_state.setStructureClobberState(StructuresAreClobbered);
3009}
3010
3011template<typename AbstractStateType>
3012void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
3013{
3014 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003015}
3016
oliver@apple.com55d32d92013-07-25 04:05:03 +00003017template<typename AbstractStateType>
3018void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003019{
oliver@apple.com96feafa2013-07-25 04:04:57 +00003020 CommaPrinter comma(" ");
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003021 HashSet<Node*> seen;
oliver@apple.com96feafa2013-07-25 04:04:57 +00003022 if (m_graph.m_form == SSA) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00003023 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
3024 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
oliver@apple.com96feafa2013-07-25 04:04:57 +00003025 for (; iter != end; ++iter) {
3026 Node* node = *iter;
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003027 seen.add(node);
oliver@apple.com96feafa2013-07-25 04:04:57 +00003028 AbstractValue& value = forNode(node);
3029 if (value.isClear())
3030 continue;
3031 out.print(comma, node, ":", value);
3032 }
3033 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00003034 for (size_t i = 0; i < m_state.block()->size(); ++i) {
3035 Node* node = m_state.block()->at(i);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003036 seen.add(node);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00003037 AbstractValue& value = forNode(node);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00003038 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003039 continue;
oliver@apple.com96feafa2013-07-25 04:04:57 +00003040 out.print(comma, node, ":", value);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003041 }
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00003042 if (m_graph.m_form == SSA) {
3043 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtTail.begin();
3044 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtTail.end();
3045 for (; iter != end; ++iter) {
3046 Node* node = *iter;
3047 if (seen.contains(node))
3048 continue;
3049 AbstractValue& value = forNode(node);
3050 if (value.isClear())
3051 continue;
3052 out.print(comma, node, ":", value);
3053 }
3054 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003055}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003056
oliver@apple.com55d32d92013-07-25 04:05:03 +00003057template<typename AbstractStateType>
3058FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
fpizlo@apple.com12835772015-09-21 20:49:04 +00003059 AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
oliver@apple.com33913872013-07-25 04:02:13 +00003060{
fpizlo@apple.com12835772015-09-21 20:49:04 +00003061 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
oliver@apple.com33913872013-07-25 04:02:13 +00003062 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003063 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003064 return Contradiction;
3065}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003066
3067template<typename AbstractStateType>
3068FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
3069 AbstractValue& value, ArrayModes arrayModes)
oliver@apple.com33913872013-07-25 04:02:13 +00003070{
3071 if (value.filterArrayModes(arrayModes) == FiltrationOK)
3072 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003073 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003074 return Contradiction;
3075}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003076
3077template<typename AbstractStateType>
3078FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3079 AbstractValue& value, SpeculatedType type)
oliver@apple.com33913872013-07-25 04:02:13 +00003080{
3081 if (value.filter(type) == FiltrationOK)
3082 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003083 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003084 return Contradiction;
3085}
oliver@apple.com55d32d92013-07-25 04:05:03 +00003086
3087template<typename AbstractStateType>
3088FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00003089 AbstractValue& abstractValue, FrozenValue concreteValue)
oliver@apple.com33913872013-07-25 04:02:13 +00003090{
3091 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
3092 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00003093 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00003094 return Contradiction;
3095}
3096
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00003097} } // namespace JSC::DFG
3098
3099#endif // ENABLE(DFG_JIT)
3100
oliver@apple.com55d32d92013-07-25 04:05:03 +00003101#endif // DFGAbstractInterpreterInlines_h
3102