blob: 5e51dea89d44aabb5886958b9ce06c24f3779247 [file] [log] [blame]
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001/*
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002 * Copyright (C) 2013, 2014 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
oliver@apple.com55d32d92013-07-25 04:05:03 +000031#include "DFGAbstractInterpreter.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000032#include "GetByIdStatus.h"
oliver@apple.come722ad02013-01-09 02:37:29 +000033#include "Operations.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000034#include "PutByIdStatus.h"
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +000035#include "StringObject.h"
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000036
37namespace JSC { namespace DFG {
38
oliver@apple.com55d32d92013-07-25 04:05:03 +000039template<typename AbstractStateType>
40AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000041 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000042 , m_graph(graph)
oliver@apple.com55d32d92013-07-25 04:05:03 +000043 , m_state(state)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000044{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000045}
46
oliver@apple.com55d32d92013-07-25 04:05:03 +000047template<typename AbstractStateType>
48AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000049{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000050}
51
oliver@apple.com55d32d92013-07-25 04:05:03 +000052template<typename AbstractStateType>
53typename AbstractInterpreter<AbstractStateType>::BooleanResult
54AbstractInterpreter<AbstractStateType>::booleanResult(
55 Node* node, AbstractValue& value)
fpizlo@apple.com367a1102012-11-10 23:33:29 +000056{
57 JSValue childConst = value.value();
58 if (childConst) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +000059 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
fpizlo@apple.com367a1102012-11-10 23:33:29 +000060 return DefinitelyTrue;
61 return DefinitelyFalse;
62 }
63
64 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
65 if (isCellSpeculation(value.m_type)
66 && value.m_currentKnownStructure.hasSingleton()) {
67 Structure* structure = value.m_currentKnownStructure.singleton();
fpizlo@apple.com6793a322014-02-12 05:42:32 +000068 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
fpizlo@apple.com367a1102012-11-10 23:33:29 +000069 && structure->typeInfo().type() != StringType)
70 return DefinitelyTrue;
71 }
72
73 return UnknownBooleanResult;
74}
75
oliver@apple.com55d32d92013-07-25 04:05:03 +000076template<typename AbstractStateType>
77bool AbstractInterpreter<AbstractStateType>::startExecuting(Node* node)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000078{
oliver@apple.com55d32d92013-07-25 04:05:03 +000079 ASSERT(m_state.block());
80 ASSERT(m_state.isValid());
fpizlo@apple.comb75911b2012-06-13 20:53:52 +000081
oliver@apple.com55d32d92013-07-25 04:05:03 +000082 m_state.setDidClobber(false);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +000083
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000084 node->setCanExit(false);
85
oliver@apple.com96feafa2013-07-25 04:04:57 +000086 return node->shouldGenerate();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000087}
88
oliver@apple.com55d32d92013-07-25 04:05:03 +000089template<typename AbstractStateType>
90bool AbstractInterpreter<AbstractStateType>::startExecuting(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000091{
oliver@apple.com55d32d92013-07-25 04:05:03 +000092 return startExecuting(m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000093}
94
oliver@apple.com55d32d92013-07-25 04:05:03 +000095template<typename AbstractStateType>
96void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000097{
98 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
99}
100
oliver@apple.com55d32d92013-07-25 04:05:03 +0000101template<typename AbstractStateType>
102void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000103{
oliver@apple.com55d32d92013-07-25 04:05:03 +0000104 executeEdges(m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000105}
106
oliver@apple.com55d32d92013-07-25 04:05:03 +0000107template<typename AbstractStateType>
108void AbstractInterpreter<AbstractStateType>::verifyEdge(Node*, Edge edge)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000109{
110 RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
111}
112
oliver@apple.com55d32d92013-07-25 04:05:03 +0000113template<typename AbstractStateType>
114void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000115{
116 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
117}
118
oliver@apple.com55d32d92013-07-25 04:05:03 +0000119template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +0000120bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000121{
122 if (!ASSERT_DISABLED)
123 verifyEdges(node);
124
oliver@apple.com02e7a972013-07-25 04:05:04 +0000125 m_state.createValueForNode(node);
126
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000127 switch (node->op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000128 case JSConstant:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000129 case DoubleConstant:
130 case Int52Constant:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +0000131 case WeakJSConstant:
132 case PhantomArguments: {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000133 setBuiltInConstant(node, m_graph.valueOfJSConstant(node));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000134 break;
135 }
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000136
137 case Identity: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000138 forNode(node) = forNode(node->child1());
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000139 break;
140 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000141
142 case GetArgument: {
143 ASSERT(m_graph.m_form == SSA);
144 VariableAccessData* variable = node->variableAccessData();
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000145 AbstractValue& value = m_state.variables().operand(variable->local().offset());
fpizlo@apple.comff779d02013-09-10 21:55:45 +0000146 ASSERT(value.isHeapTop());
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000147 FiltrationResult result =
148 value.filter(typeFilterFor(useKindFor(variable->flushFormat())));
149 ASSERT_UNUSED(result, result == FiltrationOK);
150 forNode(node) = value;
151 break;
152 }
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000153
154 case ExtractOSREntryLocal: {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000155 if (!(node->unlinkedLocal().isArgument())
156 && m_graph.m_lazyVars.get(node->unlinkedLocal().toLocal())) {
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000157 // This is kind of pessimistic - we could know in some cases that the
158 // DFG code at the point of the OSR had already initialized the lazy
159 // variable. But maybe this is fine, since we're inserting OSR
160 // entrypoints very early in the pipeline - so any lazy initializations
161 // ought to be hoisted out anyway.
fpizlo@apple.comff779d02013-09-10 21:55:45 +0000162 forNode(node).makeBytecodeTop();
163 } else
164 forNode(node).makeHeapTop();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000165 break;
166 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000167
168 case GetLocal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000169 VariableAccessData* variableAccessData = node->variableAccessData();
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000170 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000171 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000172 if (value.isClear())
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000173 node->setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000174 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000175 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000176 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000177 forNode(node) = value;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000178 break;
179 }
180
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000181 case GetLocalUnlinked: {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000182 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000183 if (value.value())
oliver@apple.com55d32d92013-07-25 04:05:03 +0000184 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000185 forNode(node) = value;
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000186 break;
187 }
188
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000189 case SetLocal: {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000190 m_state.variables().operand(node->local().offset()) = forNode(node->child1());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000191 break;
192 }
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000193
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000194 case MovHint: {
195 // Don't need to do anything. A MovHint only informs us about what would have happened
196 // in bytecode, but this code is just concerned with what is actually happening during
197 // DFG execution.
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000198 break;
199 }
200
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000201 case SetArgument:
202 // Assert that the state of arguments has been set.
oliver@apple.com55d32d92013-07-25 04:05:03 +0000203 ASSERT(!m_state.block()->valuesAtHead.operand(node->local()).isClear());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000204 break;
205
206 case BitAnd:
207 case BitOr:
208 case BitXor:
209 case BitRShift:
210 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000211 case BitURShift: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000212 JSValue left = forNode(node->child1()).value();
213 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000214 if (left && right && left.isInt32() && right.isInt32()) {
215 int32_t a = left.asInt32();
216 int32_t b = right.asInt32();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000217 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000218 case BitAnd:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000219 setConstant(node, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000220 break;
221 case BitOr:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000222 setConstant(node, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000223 break;
224 case BitXor:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000225 setConstant(node, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000226 break;
227 case BitRShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000228 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000229 break;
230 case BitLShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000231 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000232 break;
233 case BitURShift:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000234 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000235 break;
236 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000237 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000238 break;
239 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000240 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000241 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000242 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000243 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000244 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000245
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000246 case UInt32ToNumber: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000247 JSValue child = forNode(node->child1()).value();
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000248 if (doesOverflow(node->arithMode())) {
249 if (child && child.isInt32()) {
250 uint32_t value = child.asInt32();
251 setConstant(node, jsNumber(value));
252 break;
253 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000254 forNode(node).setType(SpecInt52AsDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000255 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000256 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000257 if (child && child.isInt32()) {
258 int32_t value = child.asInt32();
259 if (value >= 0) {
260 setConstant(node, jsNumber(value));
261 break;
262 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000263 }
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000264 forNode(node).setType(SpecInt32);
265 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000266 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000267 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000268
269 case BooleanToNumber: {
270 JSValue concreteValue = forNode(node->child1()).value();
271 if (concreteValue) {
272 if (concreteValue.isBoolean())
273 setConstant(node, jsNumber(concreteValue.asBoolean()));
274 else
275 setConstant(node, concreteValue);
276 break;
277 }
278 AbstractValue& value = forNode(node);
279 value = forNode(node->child1());
280 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
281 m_state.setFoundConstants(true);
282 if (value.m_type & SpecBoolean) {
283 value.merge(SpecInt32);
284 value.filter(~SpecBoolean);
285 }
286 break;
287 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000288
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000289 case DoubleAsInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000290 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000291 if (child && child.isNumber()) {
292 double asDouble = child.asNumber();
293 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000294 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
295 setConstant(node, JSValue(asInt));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000296 break;
297 }
298 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000299 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000300 forNode(node).setType(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000301 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000302 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000303
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000304 case ValueToInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000305 JSValue child = forNode(node->child1()).value();
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000306 if (child) {
307 if (child.isNumber()) {
308 if (child.isInt32())
309 setConstant(node, child);
310 else
311 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
312 break;
313 }
314 if (child.isBoolean()) {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000315 setConstant(node, jsNumber(child.asBoolean()));
commit-queue@webkit.orga4990a52013-10-03 08:43:07 +0000316 break;
317 }
fpizlo@apple.com29594fe2014-03-21 00:32:37 +0000318 if (child.isUndefinedOrNull()) {
319 setConstant(node, jsNumber(0));
320 break;
321 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000322 }
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000323
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000324 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000325 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000326 }
oliver@apple.com500b53a2013-07-25 04:05:25 +0000327
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000328 case DoubleRep: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000329 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000330 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000331 setConstant(node, jsDoubleNumber(child.asNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000332 break;
333 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000334 forNode(node).setType(forNode(node->child1()).m_type);
335 forNode(node).fixTypeForRepresentation(node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000336 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000337 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000338
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000339 case Int52Rep: {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000340 JSValue child = forNode(node->child1()).value();
fpizlo@apple.comf2999932014-07-15 00:41:39 +0000341 if (child && child.isMachineInt()) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000342 setConstant(node, child);
343 break;
344 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000345
346 forNode(node).setType(SpecInt32);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000347 break;
348 }
349
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000350 case ValueRep: {
351 JSValue value = forNode(node->child1()).value();
352 if (value) {
353 setConstant(node, value);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000354 break;
355 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000356
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +0000357 forNode(node).setType(forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000358 forNode(node).fixTypeForRepresentation(node);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000359 break;
360 }
361
fpizlo@apple.com97756552014-01-02 20:15:25 +0000362 case ValueAdd: {
fpizlo@apple.com97756552014-01-02 20:15:25 +0000363 ASSERT(node->binaryUseKind() == UntypedUse);
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000364 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com97756552014-01-02 20:15:25 +0000365 forNode(node).setType(SpecString | SpecBytecodeNumber);
366 break;
367 }
368
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000369 case ArithAdd: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000370 JSValue left = forNode(node->child1()).value();
371 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000372 switch (node->binaryUseKind()) {
373 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000374 if (left && right && left.isInt32() && right.isInt32()) {
375 if (!shouldCheckOverflow(node->arithMode())) {
376 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
377 break;
378 }
379 JSValue result = jsNumber(left.asNumber() + right.asNumber());
380 if (result.isInt32()) {
381 setConstant(node, result);
382 break;
383 }
384 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000385 forNode(node).setType(SpecInt32);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000386 if (shouldCheckOverflow(node->arithMode()))
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000387 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000388 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000389 case Int52RepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000390 if (left && right && left.isMachineInt() && right.isMachineInt()) {
391 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt());
392 if (result.isMachineInt()) {
393 setConstant(node, result);
394 break;
395 }
396 }
fpizlo@apple.com2058e2e2014-05-02 17:23:30 +0000397 forNode(node).setType(SpecMachineInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000398 if (!forNode(node->child1()).isType(SpecInt32)
399 || !forNode(node->child2()).isType(SpecInt32))
400 node->setCanExit(true);
401 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000402 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000403 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000404 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000405 break;
406 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000407 forNode(node).setType(
408 typeOfDoubleSum(
409 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000410 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000411 default:
fpizlo@apple.com97756552014-01-02 20:15:25 +0000412 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000413 break;
414 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000415 break;
416 }
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000417
418 case MakeRope: {
fpizlo@apple.com5c97de32014-04-16 02:42:22 +0000419 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000420 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000421 break;
422 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000423
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000424 case ArithSub: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000425 JSValue left = forNode(node->child1()).value();
426 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000427 switch (node->binaryUseKind()) {
428 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000429 if (left && right && left.isInt32() && right.isInt32()) {
430 if (!shouldCheckOverflow(node->arithMode())) {
431 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
432 break;
433 }
434 JSValue result = jsNumber(left.asNumber() - right.asNumber());
435 if (result.isInt32()) {
436 setConstant(node, result);
437 break;
438 }
439 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000440 forNode(node).setType(SpecInt32);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000441 if (shouldCheckOverflow(node->arithMode()))
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000442 node->setCanExit(true);
443 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000444 case Int52RepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000445 if (left && right && left.isMachineInt() && right.isMachineInt()) {
446 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt());
447 if (result.isMachineInt() || !shouldCheckOverflow(node->arithMode())) {
448 setConstant(node, result);
449 break;
450 }
451 }
fpizlo@apple.com2058e2e2014-05-02 17:23:30 +0000452 forNode(node).setType(SpecMachineInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000453 if (!forNode(node->child1()).isType(SpecInt32)
454 || !forNode(node->child2()).isType(SpecInt32))
455 node->setCanExit(true);
456 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000457 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000458 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000459 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000460 break;
461 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000462 forNode(node).setType(
463 typeOfDoubleDifference(
464 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000465 break;
466 default:
467 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000468 break;
469 }
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000470 break;
471 }
472
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000473 case ArithNegate: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000474 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000475 switch (node->child1().useKind()) {
476 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000477 if (child && child.isInt32()) {
478 if (!shouldCheckOverflow(node->arithMode())) {
479 setConstant(node, jsNumber(-child.asInt32()));
480 break;
481 }
482 double doubleResult;
483 if (shouldCheckNegativeZero(node->arithMode()))
484 doubleResult = -child.asNumber();
485 else
486 doubleResult = 0 - child.asNumber();
487 JSValue valueResult = jsNumber(doubleResult);
488 if (valueResult.isInt32()) {
489 setConstant(node, valueResult);
490 break;
491 }
492 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000493 forNode(node).setType(SpecInt32);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000494 if (shouldCheckOverflow(node->arithMode()))
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000495 node->setCanExit(true);
496 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000497 case Int52RepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000498 if (child && child.isMachineInt()) {
499 double doubleResult;
500 if (shouldCheckNegativeZero(node->arithMode()))
501 doubleResult = -child.asNumber();
502 else
503 doubleResult = 0 - child.asNumber();
504 JSValue valueResult = jsNumber(doubleResult);
505 if (valueResult.isMachineInt()) {
506 setConstant(node, valueResult);
507 break;
508 }
509 }
fpizlo@apple.com2058e2e2014-05-02 17:23:30 +0000510 forNode(node).setType(SpecMachineInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000511 if (m_state.forNode(node->child1()).couldBeType(SpecInt52))
512 node->setCanExit(true);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000513 if (shouldCheckNegativeZero(node->arithMode()))
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000514 node->setCanExit(true);
515 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000516 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000517 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000518 setConstant(node, jsDoubleNumber(-child.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000519 break;
520 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000521 forNode(node).setType(
522 typeOfDoubleNegation(
523 forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000524 break;
525 default:
526 RELEASE_ASSERT_NOT_REACHED();
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000527 break;
528 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000529 break;
530 }
531
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000532 case ArithMul: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000533 JSValue left = forNode(node->child1()).value();
534 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000535 switch (node->binaryUseKind()) {
536 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000537 if (left && right && left.isInt32() && right.isInt32()) {
538 if (!shouldCheckOverflow(node->arithMode())) {
539 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
540 break;
541 }
542 double doubleResult = left.asNumber() * right.asNumber();
543 if (!shouldCheckNegativeZero(node->arithMode()))
544 doubleResult += 0; // Sanitizes zero.
545 JSValue valueResult = jsNumber(doubleResult);
546 if (valueResult.isInt32()) {
547 setConstant(node, valueResult);
548 break;
549 }
550 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000551 forNode(node).setType(SpecInt32);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000552 if (shouldCheckOverflow(node->arithMode()))
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000553 node->setCanExit(true);
554 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000555 case Int52RepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000556 if (left && right && left.isMachineInt() && right.isMachineInt()) {
557 double doubleResult = left.asNumber() * right.asNumber();
558 if (!shouldCheckNegativeZero(node->arithMode()))
559 doubleResult += 0;
560 JSValue valueResult = jsNumber(doubleResult);
561 if (valueResult.isMachineInt()) {
562 setConstant(node, valueResult);
563 break;
564 }
565 }
fpizlo@apple.com2058e2e2014-05-02 17:23:30 +0000566 forNode(node).setType(SpecMachineInt);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000567 node->setCanExit(true);
568 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000569 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000570 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000571 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000572 break;
573 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000574 forNode(node).setType(
575 typeOfDoubleProduct(
576 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000577 break;
578 default:
579 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000580 break;
581 }
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000582 break;
583 }
584
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000585 case ArithDiv: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000586 JSValue left = forNode(node->child1()).value();
587 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000588 switch (node->binaryUseKind()) {
589 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000590 if (left && right && left.isInt32() && right.isInt32()) {
591 double doubleResult = left.asNumber() / right.asNumber();
592 if (!shouldCheckOverflow(node->arithMode()))
593 doubleResult = toInt32(doubleResult);
594 else if (!shouldCheckNegativeZero(node->arithMode()))
595 doubleResult += 0; // Sanitizes zero.
596 JSValue valueResult = jsNumber(doubleResult);
597 if (valueResult.isInt32()) {
598 setConstant(node, valueResult);
599 break;
600 }
601 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000602 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000603 node->setCanExit(true);
604 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000605 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000606 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000607 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000608 break;
609 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000610 forNode(node).setType(
611 typeOfDoubleQuotient(
612 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000613 break;
614 default:
615 RELEASE_ASSERT_NOT_REACHED();
616 break;
617 }
618 break;
619 }
620
621 case ArithMod: {
622 JSValue left = forNode(node->child1()).value();
623 JSValue right = forNode(node->child2()).value();
624 switch (node->binaryUseKind()) {
625 case Int32Use:
626 if (left && right && left.isInt32() && right.isInt32()) {
627 double doubleResult = fmod(left.asNumber(), right.asNumber());
628 if (!shouldCheckOverflow(node->arithMode()))
629 doubleResult = toInt32(doubleResult);
630 else if (!shouldCheckNegativeZero(node->arithMode()))
631 doubleResult += 0; // Sanitizes zero.
632 JSValue valueResult = jsNumber(doubleResult);
633 if (valueResult.isInt32()) {
634 setConstant(node, valueResult);
635 break;
636 }
637 }
638 forNode(node).setType(SpecInt32);
639 node->setCanExit(true);
640 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000641 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000642 if (left && right && left.isNumber() && right.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000643 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000644 break;
645 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000646 forNode(node).setType(
647 typeOfDoubleBinaryOp(
648 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000649 break;
650 default:
651 RELEASE_ASSERT_NOT_REACHED();
652 break;
653 }
654 break;
655 }
656
657 case ArithMin: {
658 JSValue left = forNode(node->child1()).value();
659 JSValue right = forNode(node->child2()).value();
660 switch (node->binaryUseKind()) {
661 case Int32Use:
662 if (left && right && left.isInt32() && right.isInt32()) {
663 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
664 break;
665 }
666 forNode(node).setType(SpecInt32);
667 node->setCanExit(true);
668 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000669 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000670 if (left && right && left.isNumber() && right.isNumber()) {
671 double a = left.asNumber();
672 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000673 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000674 break;
675 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000676 forNode(node).setType(
677 typeOfDoubleMinMax(
678 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000679 break;
680 default:
681 RELEASE_ASSERT_NOT_REACHED();
682 break;
683 }
684 break;
685 }
686
687 case ArithMax: {
688 JSValue left = forNode(node->child1()).value();
689 JSValue right = forNode(node->child2()).value();
690 switch (node->binaryUseKind()) {
691 case Int32Use:
692 if (left && right && left.isInt32() && right.isInt32()) {
693 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
694 break;
695 }
696 forNode(node).setType(SpecInt32);
697 node->setCanExit(true);
698 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000699 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000700 if (left && right && left.isNumber() && right.isNumber()) {
701 double a = left.asNumber();
702 double b = right.asNumber();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000703 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000704 break;
705 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000706 forNode(node).setType(
707 typeOfDoubleMinMax(
708 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000709 break;
710 default:
711 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000712 break;
713 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000714 break;
715 }
716
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000717 case ArithAbs: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000718 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000719 switch (node->child1().useKind()) {
720 case Int32Use:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000721 if (child && child.isInt32()) {
722 JSValue result = jsNumber(fabs(child.asNumber()));
723 if (result.isInt32()) {
724 setConstant(node, result);
725 break;
726 }
727 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000728 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000729 node->setCanExit(true);
730 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000731 case DoubleRepUse:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000732 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000733 setConstant(node, jsDoubleNumber(child.asNumber()));
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000734 break;
735 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000736 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000737 break;
738 default:
739 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000740 break;
741 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000742 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000743 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000744
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000745 case ArithSqrt: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000746 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000747 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000748 setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000749 break;
750 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000751 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000752 break;
753 }
754
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000755 case ArithFRound: {
756 JSValue child = forNode(node->child1()).value();
757 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000758 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000759 break;
760 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000761 forNode(node).setType(typeOfDoubleFRound(forNode(node->child1()).m_type));
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000762 break;
763 }
764
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000765 case ArithSin: {
766 JSValue child = forNode(node->child1()).value();
767 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000768 setConstant(node, jsDoubleNumber(sin(child.asNumber())));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000769 break;
770 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000771 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000772 break;
773 }
774
775 case ArithCos: {
776 JSValue child = forNode(node->child1()).value();
777 if (child && child.isNumber()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000778 setConstant(node, jsDoubleNumber(cos(child.asNumber())));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000779 break;
780 }
fpizlo@apple.combeef4522014-04-16 22:44:00 +0000781 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000782 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000783 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000784
785 case LogicalNot: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000786 switch (booleanResult(node, forNode(node->child1()))) {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000787 case DefinitelyTrue:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000788 setConstant(node, jsBoolean(false));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000789 break;
790 case DefinitelyFalse:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000791 setConstant(node, jsBoolean(true));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000792 break;
793 default:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000794 switch (node->child1().useKind()) {
795 case BooleanUse:
796 case Int32Use:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000797 case DoubleRepUse:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000798 case UntypedUse:
commit-queue@webkit.org008e8dc2013-10-12 02:21:45 +0000799 case StringUse:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000800 break;
801 case ObjectOrOtherUse:
802 node->setCanExit(true);
803 break;
804 default:
805 RELEASE_ASSERT_NOT_REACHED();
806 break;
807 }
808 forNode(node).setType(SpecBoolean);
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000809 break;
810 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000811 break;
812 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000813
814 case IsUndefined:
815 case IsBoolean:
816 case IsNumber:
817 case IsString:
818 case IsObject:
819 case IsFunction: {
oliver@apple.com67e0f332013-07-25 03:59:00 +0000820 node->setCanExit(
821 node->op() == IsUndefined
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000822 && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic));
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000823 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000824 if (child) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000825 bool constantWasSet = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000826 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000827 case IsUndefined:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000828 setConstant(node, jsBoolean(
oliver@apple.com67e0f332013-07-25 03:59:00 +0000829 child.isCell()
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000830 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
oliver@apple.com67e0f332013-07-25 03:59:00 +0000831 : child.isUndefined()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000832 break;
833 case IsBoolean:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000834 setConstant(node, jsBoolean(child.isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000835 break;
836 case IsNumber:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000837 setConstant(node, jsBoolean(child.isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000838 break;
839 case IsString:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000840 setConstant(node, jsBoolean(isJSString(child)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000841 break;
oliver@apple.come722ad02013-01-09 02:37:29 +0000842 case IsObject:
843 if (child.isNull() || !child.isObject()) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000844 setConstant(node, jsBoolean(child.isNull()));
oliver@apple.come722ad02013-01-09 02:37:29 +0000845 break;
846 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000847 constantWasSet = false;
848 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000849 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000850 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000851 break;
852 }
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000853 if (constantWasSet)
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000854 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000855 }
oliver@apple.come722ad02013-01-09 02:37:29 +0000856
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000857 forNode(node).setType(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000858 break;
859 }
oliver@apple.come722ad02013-01-09 02:37:29 +0000860
861 case TypeOf: {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000862 VM* vm = m_codeBlock->vm();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000863 JSValue child = forNode(node->child1()).value();
864 AbstractValue& abstractChild = forNode(node->child1());
oliver@apple.come722ad02013-01-09 02:37:29 +0000865 if (child) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000866 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000867 setConstant(node, typeString);
868 break;
869 }
870
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000871 if (isFullNumberSpeculation(abstractChild.m_type)) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000872 setConstant(node, vm->smallStrings.numberString());
873 break;
874 }
875
876 if (isStringSpeculation(abstractChild.m_type)) {
877 setConstant(node, vm->smallStrings.stringString());
878 break;
879 }
880
881 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
882 setConstant(node, vm->smallStrings.objectString());
883 break;
884 }
885
886 if (isFunctionSpeculation(abstractChild.m_type)) {
887 setConstant(node, vm->smallStrings.functionString());
888 break;
889 }
890
891 if (isBooleanSpeculation(abstractChild.m_type)) {
892 setConstant(node, vm->smallStrings.booleanString());
893 break;
fpizlo@apple.comcd81b572013-02-11 21:39:35 +0000894 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000895
896 switch (node->child1().useKind()) {
897 case StringUse:
898 case CellUse:
fpizlo@apple.comcd81b572013-02-11 21:39:35 +0000899 node->setCanExit(true);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000900 break;
901 case UntypedUse:
902 break;
903 default:
904 RELEASE_ASSERT_NOT_REACHED();
905 break;
oliver@apple.come722ad02013-01-09 02:37:29 +0000906 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000907 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
oliver@apple.come722ad02013-01-09 02:37:29 +0000908 break;
909 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000910
911 case CompareLess:
912 case CompareLessEq:
913 case CompareGreater:
914 case CompareGreaterEq:
fpizlo@apple.comb03b1402013-02-11 22:23:08 +0000915 case CompareEq:
916 case CompareEqConstant: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000917 JSValue leftConst = forNode(node->child1()).value();
918 JSValue rightConst = forNode(node->child2()).value();
oliver@apple.combd15be82013-07-25 04:03:42 +0000919 if (leftConst && rightConst) {
920 if (leftConst.isNumber() && rightConst.isNumber()) {
921 double a = leftConst.asNumber();
922 double b = rightConst.asNumber();
923 switch (node->op()) {
924 case CompareLess:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000925 setConstant(node, jsBoolean(a < b));
oliver@apple.combd15be82013-07-25 04:03:42 +0000926 break;
927 case CompareLessEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000928 setConstant(node, jsBoolean(a <= b));
oliver@apple.combd15be82013-07-25 04:03:42 +0000929 break;
930 case CompareGreater:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000931 setConstant(node, jsBoolean(a > b));
oliver@apple.combd15be82013-07-25 04:03:42 +0000932 break;
933 case CompareGreaterEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000934 setConstant(node, jsBoolean(a >= b));
oliver@apple.combd15be82013-07-25 04:03:42 +0000935 break;
936 case CompareEq:
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000937 setConstant(node, jsBoolean(a == b));
oliver@apple.combd15be82013-07-25 04:03:42 +0000938 break;
939 default:
940 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000941 break;
942 }
943 break;
944 }
945
946 if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) {
947 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
948 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
949 if (a && b) {
950 setConstant(node, jsBoolean(WTF::equal(a, b)));
oliver@apple.combd15be82013-07-25 04:03:42 +0000951 break;
952 }
953 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000954 }
955
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000956 if (node->op() == CompareEqConstant || node->op() == CompareEq) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000957 SpeculatedType leftType = forNode(node->child1()).m_type;
958 SpeculatedType rightType = forNode(node->child2()).m_type;
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000959 if (!valuesCouldBeEqual(leftType, rightType)) {
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000960 setConstant(node, jsBoolean(false));
961 break;
962 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000963 }
964
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000965 forNode(node).setType(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000966
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000967 // This is overly conservative. But the only thing this prevents is store elimination,
968 // and how likely is it, really, that you'll have redundant stores across a comparison
969 // operation? Comparison operations are typically at the end of basic blocks, so
970 // unless we have global store elimination (super unlikely given how unprofitable that
971 // optimization is to begin with), you aren't going to be wanting to store eliminate
972 // across an equality op.
973 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000974 break;
975 }
976
fpizlo@apple.com312efcd2014-03-10 22:11:35 +0000977 case CompareStrictEq: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000978 Node* leftNode = node->child1().node();
979 Node* rightNode = node->child2().node();
980 JSValue left = forNode(leftNode).value();
981 JSValue right = forNode(rightNode).value();
oliver@apple.combd15be82013-07-25 04:03:42 +0000982 if (left && right) {
oliver@apple.combd15be82013-07-25 04:03:42 +0000983 if (left.isString() && right.isString()) {
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000984 // We need this case because JSValue::strictEqual is otherwise too racy for
985 // string comparisons.
oliver@apple.combd15be82013-07-25 04:03:42 +0000986 const StringImpl* a = asString(left)->tryGetValueImpl();
987 const StringImpl* b = asString(right)->tryGetValueImpl();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +0000988 if (a && b) {
989 setConstant(node, jsBoolean(WTF::equal(a, b)));
oliver@apple.combd15be82013-07-25 04:03:42 +0000990 break;
991 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000992 } else {
993 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
994 break;
oliver@apple.combd15be82013-07-25 04:03:42 +0000995 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000996 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000997
998 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
999 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1000 if (!(leftLUB & rightLUB)) {
1001 setConstant(node, jsBoolean(false));
1002 break;
1003 }
1004
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001005 forNode(node).setType(SpecBoolean);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001006 node->setCanExit(true); // This is overly conservative.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001007 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001008 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001009
1010 case StringCharCodeAt:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001011 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001012 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001013 break;
1014
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +00001015 case StringFromCharCode:
oliver@apple.com67e0f332013-07-25 03:59:00 +00001016 forNode(node).setType(SpecString);
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +00001017 break;
1018
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001019 case StringCharAt:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001020 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001021 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001022 break;
1023
1024 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001025 node->setCanExit(true);
1026 switch (node->arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001027 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +00001028 case Array::Unprofiled:
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001029 case Array::Undecided:
oliver@apple.com5598c182013-01-23 22:25:07 +00001030 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001031 break;
1032 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001033 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001034 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001035 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001036 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001037 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001038 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001039 case Array::String:
oliver@apple.com211b3be2013-07-25 04:03:39 +00001040 if (node->arrayMode().isOutOfBounds()) {
1041 // If the watchpoint was still valid we could totally set this to be
1042 // SpecString | SpecOther. Except that we'd have to be careful. If we
1043 // tested the watchpoint state here then it could change by the time
1044 // we got to the backend. So to do this right, we'd have to get the
1045 // fixup phase to check the watchpoint state and then bake into the
1046 // GetByVal operation the fact that we're using a watchpoint, using
1047 // something like Array::SaneChain (except not quite, because that
1048 // implies an in-bounds access). None of this feels like it's worth it,
oliver@apple.come6427742013-07-25 04:05:12 +00001049 // so we're going with TOP for now. The same thing applies to
1050 // clobbering the world.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001051 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001052 forNode(node).makeHeapTop();
oliver@apple.com211b3be2013-07-25 04:03:39 +00001053 } else
1054 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001055 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001056 case Array::Arguments:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001057 forNode(node).makeHeapTop();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001058 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001059 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001060 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001061 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001062 forNode(node).makeHeapTop();
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001063 } else
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001064 forNode(node).setType(SpecInt32);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001065 break;
1066 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001067 if (node->arrayMode().isOutOfBounds()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001068 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001069 forNode(node).makeHeapTop();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001070 } else if (node->arrayMode().isSaneChain())
fpizlo@apple.combeef4522014-04-16 22:44:00 +00001071 forNode(node).setType(SpecBytecodeDouble);
fpizlo@apple.com94e84e92012-11-11 02:56:12 +00001072 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001073 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001074 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001075 case Array::Contiguous:
1076 case Array::ArrayStorage:
1077 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001078 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001079 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001080 forNode(node).makeHeapTop();
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +00001081 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001082 case Array::Int8Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001083 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001084 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001085 case Array::Int16Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001086 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001087 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001088 case Array::Int32Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001089 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001090 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001091 case Array::Uint8Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001092 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001093 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001094 case Array::Uint8ClampedArray:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001095 forNode(node).setType(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001096 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001097 case Array::Uint16Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001098 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001099 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001100 case Array::Uint32Array:
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001101 if (node->shouldSpeculateInt32())
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001102 forNode(node).setType(SpecInt32);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001103 else if (enableInt52() && node->shouldSpeculateMachineInt())
1104 forNode(node).setType(SpecInt52);
fpizlo@apple.com691ac792012-03-13 22:59:43 +00001105 else
fpizlo@apple.combeef4522014-04-16 22:44:00 +00001106 forNode(node).setType(SpecInt52AsDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001107 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001108 case Array::Float32Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001109 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001110 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001111 case Array::Float64Array:
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001112 forNode(node).setType(SpecFullDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +00001113 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001114 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001115 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001116 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001117 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001118 break;
1119 }
1120
oliver@apple.come050d642013-10-19 00:09:28 +00001121 case PutByValDirect:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001122 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001123 case PutByValAlias: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001124 node->setCanExit(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001125 switch (node->arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001126 case Array::ForceExit:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001127 m_state.setIsValid(false);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001128 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001129 case Array::Generic:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001130 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001131 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001132 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001133 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001134 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001135 break;
1136 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001137 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001138 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001139 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001140 case Array::Contiguous:
1141 case Array::ArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001142 if (node->arrayMode().isOutOfBounds())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001143 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001144 break;
1145 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001146 if (node->arrayMode().mayStoreToHole())
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001147 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001148 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001149 default:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001150 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001151 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001152 break;
1153 }
1154
1155 case ArrayPush:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001156 node->setCanExit(true);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001157 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001158 forNode(node).setType(SpecBytecodeNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001159 break;
1160
1161 case ArrayPop:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001162 node->setCanExit(true);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001163 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001164 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001165 break;
1166
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001167 case RegExpExec:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001168 forNode(node).makeHeapTop();
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001169 break;
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001170
1171 case RegExpTest:
oliver@apple.com67e0f332013-07-25 03:59:00 +00001172 forNode(node).setType(SpecBoolean);
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001173 break;
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001174
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001175 case Jump:
1176 break;
1177
1178 case Branch: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001179 Node* child = node->child1().node();
1180 BooleanResult result = booleanResult(node, forNode(child));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001181 if (result == DefinitelyTrue) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001182 m_state.setBranchDirection(TakeTrue);
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001183 break;
1184 }
1185 if (result == DefinitelyFalse) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001186 m_state.setBranchDirection(TakeFalse);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001187 break;
1188 }
1189 // FIXME: The above handles the trivial cases of sparse conditional
1190 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001191 // We can specialize the source variable's value on each direction of
1192 // the branch.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001193 node->setCanExit(true); // This is overly conservative.
oliver@apple.com55d32d92013-07-25 04:05:03 +00001194 m_state.setBranchDirection(TakeBoth);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001195 break;
1196 }
oliver@apple.com9b7647b2013-07-25 04:03:00 +00001197
1198 case Switch: {
1199 // Nothing to do for now.
1200 // FIXME: Do sparse conditional things.
1201 break;
1202 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001203
1204 case Return:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001205 m_state.setIsValid(false);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001206 break;
1207
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001208 case Throw:
1209 case ThrowReferenceError:
oliver@apple.com55d32d92013-07-25 04:05:03 +00001210 m_state.setIsValid(false);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001211 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001212 break;
1213
1214 case ToPrimitive: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001215 JSValue childConst = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001216 if (childConst && childConst.isNumber()) {
1217 setConstant(node, childConst);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001218 break;
1219 }
1220
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001221 ASSERT(node->child1().useKind() == UntypedUse);
1222
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00001223 if (!forNode(node->child1()).m_type) {
1224 m_state.setIsValid(false);
1225 break;
1226 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001227
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00001228 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString))) {
1229 m_state.setFoundConstants(true);
1230 forNode(node) = forNode(node->child1());
1231 break;
1232 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001233
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001234 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001235
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00001236 forNode(node).setType((SpecHeapTop & ~SpecCell) | SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001237 break;
1238 }
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001239
1240 case ToString: {
1241 switch (node->child1().useKind()) {
1242 case StringObjectUse:
1243 // This also filters that the StringObject has the primordial StringObject
1244 // structure.
oliver@apple.com33913872013-07-25 04:02:13 +00001245 filter(
1246 node->child1(),
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001247 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001248 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1249 break;
1250 case StringOrStringObjectUse:
1251 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1252 break;
1253 case CellUse:
1254 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001255 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001256 break;
1257 default:
1258 RELEASE_ASSERT_NOT_REACHED();
1259 break;
1260 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001261 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001262 break;
1263 }
1264
1265 case NewStringObject: {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001266 ASSERT(node->structure()->classInfo() == StringObject::info());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001267 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001268 break;
1269 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001270
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001271 case NewArray:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001272 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001273 forNode(node).set(
1274 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001275 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
oliver@apple.com55d32d92013-07-25 04:05:03 +00001276 m_state.setHaveStructures(true);
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001277 break;
1278
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001279 case NewArrayBuffer:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001280 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001281 forNode(node).set(
1282 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001283 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
oliver@apple.com55d32d92013-07-25 04:05:03 +00001284 m_state.setHaveStructures(true);
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001285 break;
1286
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001287 case NewArrayWithSize:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001288 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001289 forNode(node).setType(SpecArray);
oliver@apple.com55d32d92013-07-25 04:05:03 +00001290 m_state.setHaveStructures(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001291 break;
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001292
1293 case NewTypedArray:
1294 switch (node->child1().useKind()) {
1295 case Int32Use:
1296 break;
1297 case UntypedUse:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001298 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001299 break;
1300 default:
1301 RELEASE_ASSERT_NOT_REACHED();
1302 break;
1303 }
1304 forNode(node).set(
1305 m_graph,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001306 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
fpizlo@apple.com372fa822013-08-21 19:43:47 +00001307 node->typedArrayType()));
1308 m_state.setHaveStructures(true);
1309 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001310
1311 case NewRegexp:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001312 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001313 m_state.setHaveStructures(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001314 break;
1315
oliver@apple.come2fe4ce2013-07-25 03:59:41 +00001316 case ToThis: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001317 AbstractValue& source = forNode(node->child1());
1318 AbstractValue& destination = forNode(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001319
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001320 if (m_graph.executableFor(node->origin.semantic)->isStrictMode())
fpizlo@apple.com018818d2013-09-13 23:18:19 +00001321 destination.makeHeapTop();
1322 else {
1323 destination = source;
1324 destination.merge(SpecObject);
1325 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001326 break;
1327 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001328
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001329 case CreateThis: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001330 forNode(node).setType(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001331 break;
1332 }
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001333
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001334 case AllocationProfileWatchpoint:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001335 node->setCanExit(true);
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001336 break;
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001337
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001338 case NewObject:
fpizlo@apple.com62203aa2013-12-03 22:24:53 +00001339 ASSERT(node->structure());
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001340 forNode(node).set(m_graph, node->structure());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001341 m_state.setHaveStructures(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001342 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001343
1344 case CreateActivation:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001345 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001346 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001347 m_state.setHaveStructures(true);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001348 break;
fpizlo@apple.com1a724092013-11-28 07:10:10 +00001349
fpizlo@apple.coma4ea0662013-12-02 19:09:15 +00001350 case FunctionReentryWatchpoint:
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001351 case TypedArrayWatchpoint:
fpizlo@apple.com1a724092013-11-28 07:10:10 +00001352 break;
oliver@apple.com83ec76b2013-09-21 00:00:30 +00001353
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001354 case CreateArguments:
fpizlo@apple.come5fd43b2014-01-09 20:41:06 +00001355 forNode(node) = forNode(node->child1());
1356 forNode(node).filter(~SpecEmpty);
1357 forNode(node).merge(SpecArguments);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001358 break;
1359
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001360 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001361 case TearOffArguments:
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001362 // Does nothing that is user-visible.
1363 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001364
1365 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001366 if (isEmptySpeculation(
oliver@apple.com55d32d92013-07-25 04:05:03 +00001367 m_state.variables().operand(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001368 m_graph.argumentsRegisterFor(node->origin.semantic).offset()).m_type))
oliver@apple.com55d32d92013-07-25 04:05:03 +00001369 m_state.setFoundConstants(true);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001370 else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001371 node->setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001372 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001373
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001374 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001375 // We know that this executable does not escape its arguments, so we can optimize
1376 // the arguments a bit. Note that this is not sufficient to force constant folding
1377 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1378 // We perform further optimizations on this later on.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001379 if (node->origin.semantic.inlineCallFrame) {
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001380 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001381 m_graph, jsNumber(node->origin.semantic.inlineCallFrame->arguments.size() - 1));
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001382 } else
1383 forNode(node).setType(SpecInt32);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001384 node->setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001385 !isEmptySpeculation(
oliver@apple.com55d32d92013-07-25 04:05:03 +00001386 m_state.variables().operand(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001387 m_graph.argumentsRegisterFor(node->origin.semantic)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001388 break;
1389
1390 case GetMyArgumentsLengthSafe:
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001391 // This potentially clobbers all structures if the arguments object had a getter
1392 // installed on the length property.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001393 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001394 // We currently make no guarantee about what this returns because it does not
1395 // speculate that the length property is actually a length.
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001396 forNode(node).makeHeapTop();
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001397 break;
1398
1399 case GetMyArgumentByVal:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001400 node->setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001401 // We know that this executable does not escape its arguments, so we can optimize
1402 // the arguments a bit. Note that this ends up being further optimized by the
1403 // ArgumentsSimplificationPhase.
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001404 forNode(node).makeHeapTop();
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001405 break;
1406
1407 case GetMyArgumentByValSafe:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001408 node->setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001409 // This potentially clobbers all structures if the property we're accessing has
1410 // a getter. We don't speculate against this.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001411 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001412 // And the result is unknown.
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001413 forNode(node).makeHeapTop();
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001414 break;
1415
fpizlo@apple.com507dca12013-07-17 23:27:31 +00001416 case NewFunction: {
1417 AbstractValue& value = forNode(node);
1418 value = forNode(node->child1());
1419
1420 if (!(value.m_type & SpecEmpty)) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001421 m_state.setFoundConstants(true);
fpizlo@apple.com507dca12013-07-17 23:27:31 +00001422 break;
1423 }
1424
oliver@apple.com02039462013-07-25 03:59:29 +00001425 value.setType((value.m_type & ~SpecEmpty) | SpecFunction);
fpizlo@apple.com507dca12013-07-17 23:27:31 +00001426 break;
1427 }
1428
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001429 case NewFunctionExpression:
1430 case NewFunctionNoCheck:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001431 forNode(node).set(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001432 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001433 break;
1434
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001435 case GetCallee:
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00001436 case GetGetter:
1437 case GetSetter:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001438 forNode(node).setType(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001439 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001440
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001441 case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
fpizlo@apple.com20d46242012-11-30 21:56:24 +00001442 case GetMyScope:
1443 case SkipTopScope:
oliver@apple.comeca9fbe2013-07-28 18:04:18 +00001444 forNode(node).setType(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001445 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001446
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001447 case SkipScope: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001448 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com49e37d32013-09-11 21:49:47 +00001449 if (child) {
1450 setConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()));
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001451 break;
1452 }
oliver@apple.comeca9fbe2013-07-28 18:04:18 +00001453 forNode(node).setType(SpecObjectOther);
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001454 break;
1455 }
1456
oliver@apple.com58c86752013-07-25 04:02:40 +00001457 case GetClosureRegisters:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001458 forNode(node).clear(); // The result is not a JS value.
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001459 break;
1460
oliver@apple.com58c86752013-07-25 04:02:40 +00001461 case GetClosureVar:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001462 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001463 break;
1464
oliver@apple.com58c86752013-07-25 04:02:40 +00001465 case PutClosureVar:
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001466 clobberCapturedVars(node->origin.semantic);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001467 break;
1468
1469 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001470 case GetByIdFlush:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001471 node->setCanExit(true);
1472 if (!node->prediction()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001473 m_state.setIsValid(false);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001474 break;
1475 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001476 if (isCellSpeculation(node->child1()->prediction())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001477 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001478 GetByIdStatus status = GetByIdStatus::computeFor(
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001479 m_graph.m_vm, structure,
oliver@apple.com90fce822013-07-25 04:00:13 +00001480 m_graph.identifiers()[node->identifierNumber()]);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001481 if (status.isSimple() && status.numVariants() == 1) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001482 // Assert things that we can't handle and that the computeFor() method
1483 // above won't be able to return.
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001484 ASSERT(status[0].structureSet().size() == 1);
1485 ASSERT(!status[0].chain());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001486
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001487 if (status[0].specificValue())
1488 setConstant(node, status[0].specificValue());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001489 else
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001490 forNode(node).makeHeapTop();
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001491 filter(node->child1(), status[0].structureSet());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001492
oliver@apple.com55d32d92013-07-25 04:05:03 +00001493 m_state.setFoundConstants(true);
fpizlo@apple.com2c575332013-11-05 18:53:04 +00001494 m_state.setHaveStructures(true);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001495 break;
1496 }
1497 }
1498 }
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001499 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001500 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001501 break;
1502
1503 case GetArrayLength:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001504 node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001505 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001506 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001507
1508 case CheckExecutable: {
1509 // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
1510 // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
1511 // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
1512 // https://bugs.webkit.org/show_bug.cgi?id=106201
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001513 node->setCanExit(true);
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001514 break;
1515 }
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001516
oliver@apple.com500b53a2013-07-25 04:05:25 +00001517 case CheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001518 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001519 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001520 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
oliver@apple.com33913872013-07-25 04:02:13 +00001521
1522 StructureSet& set = node->structureSet();
1523
1524 if (value.m_currentKnownStructure.isSubsetOf(set)) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001525 m_state.setFoundConstants(true);
oliver@apple.com33913872013-07-25 04:02:13 +00001526 break;
1527 }
1528
oliver@apple.com33913872013-07-25 04:02:13 +00001529 node->setCanExit(true);
oliver@apple.com0402d952013-07-25 04:05:07 +00001530 m_state.setHaveStructures(true);
oliver@apple.com33913872013-07-25 04:02:13 +00001531
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001532 // If this structure check is attempting to prove knowledge already held in
1533 // the futurePossibleStructure set then the constant folding phase should
1534 // turn this into a watchpoint instead.
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001535 if (value.m_futurePossibleStructure.isSubsetOf(set)
oliver@apple.com33913872013-07-25 04:02:13 +00001536 && value.m_futurePossibleStructure.hasSingleton()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001537 m_state.setFoundConstants(true);
oliver@apple.com37bd9382013-07-25 04:02:17 +00001538 filter(value, value.m_futurePossibleStructure.singleton());
oliver@apple.com33913872013-07-25 04:02:13 +00001539 break;
1540 }
1541
oliver@apple.com37bd9382013-07-25 04:02:17 +00001542 filter(value, set);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001543 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001544 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001545
oliver@apple.com500b53a2013-07-25 04:05:25 +00001546 case StructureTransitionWatchpoint: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001547 AbstractValue& value = forNode(node->child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001548
oliver@apple.com37bd9382013-07-25 04:02:17 +00001549 filter(value, node->structure());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001550 m_state.setHaveStructures(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001551 node->setCanExit(true);
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001552 break;
1553 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001554
1555 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001556 case PhantomPutStructure:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001557 if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
oliver@apple.come17632e2013-07-25 04:05:31 +00001558 clobberStructures(clobberLimit);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001559 forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure);
oliver@apple.com55d32d92013-07-25 04:05:03 +00001560 m_state.setHaveStructures(true);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00001561 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001562 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00001563 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00001564 case AllocatePropertyStorage:
1565 case ReallocatePropertyStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001566 forNode(node).clear(); // The result is not a JS value.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001567 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001568 case CheckArray: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001569 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001570 m_state.setFoundConstants(true);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001571 break;
1572 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001573 node->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
1574 switch (node->arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001575 case Array::String:
oliver@apple.com33913872013-07-25 04:02:13 +00001576 filter(node->child1(), SpecString);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001577 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001578 case Array::Int32:
1579 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001580 case Array::Contiguous:
1581 case Array::ArrayStorage:
1582 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001583 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001584 case Array::Arguments:
oliver@apple.com33913872013-07-25 04:02:13 +00001585 filter(node->child1(), SpecArguments);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001586 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001587 case Array::Int8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001588 filter(node->child1(), SpecInt8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001589 break;
1590 case Array::Int16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001591 filter(node->child1(), SpecInt16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001592 break;
1593 case Array::Int32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001594 filter(node->child1(), SpecInt32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001595 break;
1596 case Array::Uint8Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001597 filter(node->child1(), SpecUint8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001598 break;
1599 case Array::Uint8ClampedArray:
oliver@apple.com33913872013-07-25 04:02:13 +00001600 filter(node->child1(), SpecUint8ClampedArray);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001601 break;
1602 case Array::Uint16Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001603 filter(node->child1(), SpecUint16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001604 break;
1605 case Array::Uint32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001606 filter(node->child1(), SpecUint32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001607 break;
1608 case Array::Float32Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001609 filter(node->child1(), SpecFloat32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001610 break;
1611 case Array::Float64Array:
oliver@apple.com33913872013-07-25 04:02:13 +00001612 filter(node->child1(), SpecFloat64Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001613 break;
1614 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001615 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001616 break;
1617 }
oliver@apple.com52be8f82013-07-25 04:04:33 +00001618 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001619 m_state.setHaveStructures(true);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001620 break;
1621 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001622 case Arrayify: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001623 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001624 m_state.setFoundConstants(true);
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00001625 break;
1626 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001627 ASSERT(node->arrayMode().conversion() == Array::Convert
1628 || node->arrayMode().conversion() == Array::RageConvert);
1629 node->setCanExit(true);
oliver@apple.come17632e2013-07-25 04:05:31 +00001630 clobberStructures(clobberLimit);
oliver@apple.com33913872013-07-25 04:02:13 +00001631 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
oliver@apple.com55d32d92013-07-25 04:05:03 +00001632 m_state.setHaveStructures(true);
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001633 break;
1634 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001635 case ArrayifyToStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001636 AbstractValue& value = forNode(node->child1());
1637 StructureSet set = node->structure();
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001638 if (value.m_futurePossibleStructure.isSubsetOf(set)
1639 || value.m_currentKnownStructure.isSubsetOf(set))
oliver@apple.com55d32d92013-07-25 04:05:03 +00001640 m_state.setFoundConstants(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001641 node->setCanExit(true);
oliver@apple.come17632e2013-07-25 04:05:31 +00001642 clobberStructures(clobberLimit);
oliver@apple.com37bd9382013-07-25 04:02:17 +00001643 filter(value, set);
oliver@apple.com55d32d92013-07-25 04:05:03 +00001644 m_state.setHaveStructures(true);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001645 break;
1646 }
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00001647 case GetIndexedPropertyStorage:
1648 case ConstantStoragePointer: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001649 forNode(node).clear();
oliver@apple.com43e511c2011-12-09 08:45:46 +00001650 break;
1651 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001652
1653 case GetTypedArrayByteOffset: {
1654 forNode(node).setType(SpecInt32);
1655 break;
1656 }
1657
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001658 case GetByOffset: {
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001659 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001660 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001661 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001662
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00001663 case GetGetterSetterByOffset: {
1664 forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
1665 break;
1666 }
1667
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001668 case MultiGetByOffset: {
1669 AbstractValue& value = forNode(node->child1());
1670 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1671
1672 if (Structure* structure = value.bestProvenStructure()) {
1673 bool done = false;
1674 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
1675 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
1676 if (!variant.structureSet().contains(structure))
1677 continue;
1678
1679 if (variant.chain())
1680 break;
1681
1682 filter(value, structure);
1683 forNode(node).makeHeapTop();
1684 m_state.setFoundConstants(true);
1685 done = true;
1686 break;
1687 }
1688 if (done)
1689 break;
1690 }
1691
1692 StructureSet set;
1693 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
1694 set.addAll(node->multiGetByOffsetData().variants[i].structureSet());
1695
fpizlo@apple.com43219522014-02-25 02:02:50 +00001696 filter(node->child1(), set);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001697 forNode(node).makeHeapTop();
1698 break;
1699 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001700
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001701 case PutByOffset: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001702 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001703 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00001704
1705 case MultiPutByOffset: {
1706 AbstractValue& value = forNode(node->child1());
1707 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1708
1709 if (Structure* structure = value.bestProvenStructure()) {
1710 bool done = false;
1711 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1712 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1713 if (variant.oldStructure() != structure)
1714 continue;
1715
1716 if (variant.kind() == PutByIdVariant::Replace) {
1717 filter(node->child1(), structure);
1718 m_state.setFoundConstants(true);
1719 m_state.setHaveStructures(true);
1720 done = true;
1721 break;
1722 }
1723
1724 ASSERT(variant.kind() == PutByIdVariant::Transition);
1725 clobberStructures(clobberLimit);
1726 forNode(node->child1()).set(m_graph, variant.newStructure());
1727 m_state.setFoundConstants(true);
1728 m_state.setHaveStructures(true);
1729 done = true;
1730 break;
1731 }
1732 if (done)
1733 break;
1734 }
1735
1736 clobberStructures(clobberLimit);
1737
1738 StructureSet newSet;
1739 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1740 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1741 if (variant.kind() == PutByIdVariant::Replace) {
1742 if (value.m_currentKnownStructure.contains(variant.structure()))
1743 newSet.addAll(variant.structure());
1744 continue;
1745 }
1746 ASSERT(variant.kind() == PutByIdVariant::Transition);
1747 if (value.m_currentKnownStructure.contains(variant.oldStructure()))
1748 newSet.addAll(variant.newStructure());
1749 }
1750
1751 // Use filter(value, set) as a way of setting the structure set. This works because
1752 // we would have already made the set be TOP before this. Filtering top is another
1753 // way of setting.
1754 filter(node->child1(), newSet);
1755 break;
1756 }
1757
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001758 case CheckFunction: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001759 JSValue value = forNode(node->child1()).value();
1760 if (value == node->function()) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001761 m_state.setFoundConstants(true);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001762 ASSERT(value);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001763 break;
1764 }
1765
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001766 node->setCanExit(true); // Lies! We can do better.
oliver@apple.com37bd9382013-07-25 04:02:17 +00001767 filterByValue(node->child1(), node->function());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001768 break;
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001769 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001770
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00001771 case CheckInBounds: {
1772 JSValue left = forNode(node->child1()).value();
1773 JSValue right = forNode(node->child2()).value();
1774 if (left && right && left.isInt32() && right.isInt32()
1775 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
1776 m_state.setFoundConstants(true);
1777 break;
1778 }
1779
1780 node->setCanExit(true);
1781 break;
1782 }
1783
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001784 case PutById:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +00001785 case PutByIdFlush:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001786 case PutByIdDirect:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001787 node->setCanExit(true);
1788 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001789 PutByIdStatus status = PutByIdStatus::computeFor(
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001790 m_graph.m_vm,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001791 m_graph.globalObjectFor(node->origin.semantic),
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001792 structure,
oliver@apple.com90fce822013-07-25 04:00:13 +00001793 m_graph.identifiers()[node->identifierNumber()],
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001794 node->op() == PutByIdDirect);
fpizlo@apple.com43219522014-02-25 02:02:50 +00001795 if (status.isSimple() && status.numVariants() == 1) {
1796 if (status[0].kind() == PutByIdVariant::Replace) {
1797 filter(node->child1(), structure);
1798 m_state.setFoundConstants(true);
1799 m_state.setHaveStructures(true);
1800 break;
1801 }
1802 if (status[0].kind() == PutByIdVariant::Transition) {
1803 clobberStructures(clobberLimit);
1804 forNode(node->child1()).set(m_graph, status[0].newStructure());
1805 m_state.setHaveStructures(true);
1806 m_state.setFoundConstants(true);
1807 break;
1808 }
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001809 }
1810 }
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001811 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001812 break;
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00001813
1814 case In:
1815 // FIXME: We can determine when the property definitely exists based on abstract
1816 // value information.
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001817 clobberWorld(node->origin.semantic, clobberLimit);
oliver@apple.comb3e5acb2013-07-25 04:02:53 +00001818 forNode(node).setType(SpecBoolean);
1819 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001820
1821 case GetGlobalVar:
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001822 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001823 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001824
fpizlo@apple.com86468342013-11-27 02:47:43 +00001825 case VariableWatchpoint:
oliver@apple.com58c86752013-07-25 04:02:40 +00001826 case VarInjectionWatchpoint:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001827 node->setCanExit(true);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001828 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001829
1830 case PutGlobalVar:
fpizlo@apple.com86468342013-11-27 02:47:43 +00001831 case NotifyWrite:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001832 break;
1833
1834 case CheckHasInstance:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001835 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001836 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1837 break;
1838
1839 case InstanceOf:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001840 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001841 // Again, sadly, we don't propagate the fact that we've done InstanceOf
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001842 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001843 break;
1844
1845 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001846 RELEASE_ASSERT(m_graph.m_form == SSA);
1847 // The state of this node would have already been decided.
1848 break;
1849
1850 case Upsilon: {
oliver@apple.com02e7a972013-07-25 04:05:04 +00001851 m_state.createValueForNode(node->phi());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001852 AbstractValue& value = forNode(node->child1());
1853 forNode(node) = value;
1854 forNode(node->phi()) = value;
1855 break;
1856 }
1857
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001858 case Flush:
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +00001859 case PhantomLocal:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001860 break;
1861
1862 case Call:
1863 case Construct:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001864 node->setCanExit(true);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001865 clobberWorld(node->origin.semantic, clobberLimit);
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001866 forNode(node).makeHeapTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001867 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001868
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001869 case ForceOSRExit:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001870 node->setCanExit(true);
oliver@apple.com55d32d92013-07-25 04:05:03 +00001871 m_state.setIsValid(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001872 break;
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001873
1874 case InvalidationPoint:
1875 node->setCanExit(true);
1876 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00001877
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00001878 case CheckWatchdogTimer:
1879 node->setCanExit(true);
1880 break;
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00001881
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00001882 case Breakpoint:
1883 case ProfileWillCall:
1884 case ProfileDidCall:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001885 case Phantom:
fpizlo@apple.com4c96a842014-02-13 22:46:51 +00001886 case HardPhantom:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001887 case Check:
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00001888 case CountExecution:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001889 case CheckTierUpInLoop:
1890 case CheckTierUpAtReturn:
1891 break;
1892
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001893 case StoreBarrier: {
1894 filter(node->child1(), SpecCell);
1895 break;
1896 }
1897
1898 case StoreBarrierWithNullCheck: {
1899 break;
1900 }
1901
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001902 case CheckTierUpAndOSREnter:
1903 case LoopHint:
1904 // We pretend that it can exit because it may want to get all state.
1905 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001906 break;
oliver@apple.com1fc04182013-08-19 19:40:13 +00001907
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001908 case ZombieHint:
oliver@apple.com1fc04182013-08-19 19:40:13 +00001909 case Unreachable:
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001910 case LastNodeType:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001911 case ArithIMul:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001912 case FiatInt52:
oliver@apple.com5598c182013-01-23 22:25:07 +00001913 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001914 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001915 }
1916
oliver@apple.com55d32d92013-07-25 04:05:03 +00001917 return m_state.isValid();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001918}
1919
oliver@apple.com55d32d92013-07-25 04:05:03 +00001920template<typename AbstractStateType>
1921bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001922{
oliver@apple.com55d32d92013-07-25 04:05:03 +00001923 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001924}
1925
oliver@apple.com55d32d92013-07-25 04:05:03 +00001926template<typename AbstractStateType>
1927bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001928{
oliver@apple.com55d32d92013-07-25 04:05:03 +00001929 Node* node = m_state.block()->at(indexInBlock);
oliver@apple.com37bd9382013-07-25 04:02:17 +00001930 if (!startExecuting(node))
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001931 return true;
1932
1933 executeEdges(node);
1934 return executeEffects(indexInBlock, node);
1935}
1936
oliver@apple.com55d32d92013-07-25 04:05:03 +00001937template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +00001938bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
1939{
1940 if (!startExecuting(node))
1941 return true;
1942
1943 executeEdges(node);
1944 return executeEffects(UINT_MAX, node);
1945}
1946
1947template<typename AbstractStateType>
oliver@apple.com55d32d92013-07-25 04:05:03 +00001948void AbstractInterpreter<AbstractStateType>::clobberWorld(
oliver@apple.come17632e2013-07-25 04:05:31 +00001949 const CodeOrigin& codeOrigin, unsigned clobberLimit)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001950{
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001951 clobberCapturedVars(codeOrigin);
oliver@apple.come17632e2013-07-25 04:05:31 +00001952 clobberStructures(clobberLimit);
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001953}
1954
oliver@apple.com55d32d92013-07-25 04:05:03 +00001955template<typename AbstractStateType>
1956void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigin& codeOrigin)
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001957{
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001958 if (codeOrigin.inlineCallFrame) {
1959 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1960 for (size_t i = capturedVars.size(); i--;) {
1961 if (!capturedVars.quickGet(i))
1962 continue;
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001963 m_state.variables().local(i).makeHeapTop();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001964 }
1965 } else {
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001966 for (size_t i = m_codeBlock->m_numVars; i--;) {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00001967 if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001968 m_state.variables().local(i).makeHeapTop();
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001969 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001970 }
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001971
oliver@apple.com55d32d92013-07-25 04:05:03 +00001972 for (size_t i = m_state.variables().numberOfArguments(); i--;) {
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00001973 if (m_codeBlock->isCaptured(virtualRegisterForArgument(i)))
fpizlo@apple.comff779d02013-09-10 21:55:45 +00001974 m_state.variables().argument(i).makeHeapTop();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001975 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001976}
1977
oliver@apple.com55d32d92013-07-25 04:05:03 +00001978template<typename AbstractStateType>
oliver@apple.come17632e2013-07-25 04:05:31 +00001979void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001980{
oliver@apple.com55d32d92013-07-25 04:05:03 +00001981 if (!m_state.haveStructures())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001982 return;
oliver@apple.come17632e2013-07-25 04:05:31 +00001983 if (clobberLimit >= m_state.block()->size())
1984 clobberLimit = m_state.block()->size();
1985 else
1986 clobberLimit++;
1987 ASSERT(clobberLimit <= m_state.block()->size());
1988 for (size_t i = clobberLimit; i--;)
oliver@apple.com55d32d92013-07-25 04:05:03 +00001989 forNode(m_state.block()->at(i)).clobberStructures();
oliver@apple.com96feafa2013-07-25 04:04:57 +00001990 if (m_graph.m_form == SSA) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00001991 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
1992 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
oliver@apple.com96feafa2013-07-25 04:04:57 +00001993 for (; iter != end; ++iter)
1994 forNode(*iter).clobberStructures();
1995 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00001996 for (size_t i = m_state.variables().numberOfArguments(); i--;)
1997 m_state.variables().argument(i).clobberStructures();
1998 for (size_t i = m_state.variables().numberOfLocals(); i--;)
1999 m_state.variables().local(i).clobberStructures();
2000 m_state.setHaveStructures(true);
2001 m_state.setDidClobber(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002002}
2003
oliver@apple.com55d32d92013-07-25 04:05:03 +00002004template<typename AbstractStateType>
2005void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002006{
oliver@apple.com96feafa2013-07-25 04:04:57 +00002007 CommaPrinter comma(" ");
2008 if (m_graph.m_form == SSA) {
oliver@apple.com55d32d92013-07-25 04:05:03 +00002009 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2010 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
oliver@apple.com96feafa2013-07-25 04:04:57 +00002011 for (; iter != end; ++iter) {
2012 Node* node = *iter;
2013 AbstractValue& value = forNode(node);
2014 if (value.isClear())
2015 continue;
2016 out.print(comma, node, ":", value);
2017 }
2018 }
oliver@apple.com55d32d92013-07-25 04:05:03 +00002019 for (size_t i = 0; i < m_state.block()->size(); ++i) {
2020 Node* node = m_state.block()->at(i);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002021 AbstractValue& value = forNode(node);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00002022 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002023 continue;
oliver@apple.com96feafa2013-07-25 04:04:57 +00002024 out.print(comma, node, ":", value);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002025 }
2026}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002027
oliver@apple.com55d32d92013-07-25 04:05:03 +00002028template<typename AbstractStateType>
2029FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2030 AbstractValue& value, const StructureSet& set)
oliver@apple.com33913872013-07-25 04:02:13 +00002031{
2032 if (value.filter(m_graph, set) == FiltrationOK)
2033 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00002034 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00002035 return Contradiction;
2036}
oliver@apple.com55d32d92013-07-25 04:05:03 +00002037
2038template<typename AbstractStateType>
2039FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
2040 AbstractValue& value, ArrayModes arrayModes)
oliver@apple.com33913872013-07-25 04:02:13 +00002041{
2042 if (value.filterArrayModes(arrayModes) == FiltrationOK)
2043 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00002044 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00002045 return Contradiction;
2046}
oliver@apple.com55d32d92013-07-25 04:05:03 +00002047
2048template<typename AbstractStateType>
2049FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2050 AbstractValue& value, SpeculatedType type)
oliver@apple.com33913872013-07-25 04:02:13 +00002051{
2052 if (value.filter(type) == FiltrationOK)
2053 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00002054 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00002055 return Contradiction;
2056}
oliver@apple.com55d32d92013-07-25 04:05:03 +00002057
2058template<typename AbstractStateType>
2059FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
oliver@apple.com37bd9382013-07-25 04:02:17 +00002060 AbstractValue& abstractValue, JSValue concreteValue)
oliver@apple.com33913872013-07-25 04:02:13 +00002061{
2062 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
2063 return FiltrationOK;
oliver@apple.com55d32d92013-07-25 04:05:03 +00002064 m_state.setIsValid(false);
oliver@apple.com33913872013-07-25 04:02:13 +00002065 return Contradiction;
2066}
2067
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00002068} } // namespace JSC::DFG
2069
2070#endif // ENABLE(DFG_JIT)
2071
oliver@apple.com55d32d92013-07-25 04:05:03 +00002072#endif // DFGAbstractInterpreterInlines_h
2073