blob: 418612080af5eb307768882704c44bb3c132144f [file] [log] [blame]
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001/*
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00002 * Copyright (C) 2011, 2012 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
26#include "config.h"
27#include "DFGAbstractState.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "CodeBlock.h"
32#include "DFGBasicBlock.h"
33
34namespace JSC { namespace DFG {
35
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000036AbstractState::AbstractState(Graph& graph)
37 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000038 , m_graph(graph)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000039 , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000040 , m_block(0)
41{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000042 m_nodes.resize(graph.size());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000043}
44
45AbstractState::~AbstractState() { }
46
47void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
48{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000049 ASSERT(!m_block);
50
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000051 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
52 ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
53 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
54
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000055 for (size_t i = 0; i < basicBlock->size(); i++)
56 m_nodes[basicBlock->at(i)].clear();
57
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000058 m_variables = basicBlock->valuesAtHead;
59 m_haveStructures = false;
60 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
61 if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
62 m_haveStructures = true;
63 break;
64 }
65 }
66 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
67 if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
68 m_haveStructures = true;
69 break;
70 }
71 }
72
73 basicBlock->cfaShouldRevisit = false;
74 basicBlock->cfaHasVisited = true;
75 m_block = basicBlock;
76 m_isValid = true;
fpizlo@apple.com3187c922012-05-18 21:47:53 +000077 m_foundConstants = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +000078 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000079}
80
81void AbstractState::initialize(Graph& graph)
82{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000083 BasicBlock* root = graph.m_blocks[0].get();
84 root->cfaShouldRevisit = true;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000085 root->cfaHasVisited = false;
86 root->cfaFoundConstants = false;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000087 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
fpizlo@apple.com4f5361262012-02-16 10:06:28 +000088 Node& node = graph[root->variablesAtHead.argument(i)];
fpizlo@apple.comd7897b12012-03-12 23:15:45 +000089 ASSERT(node.op() == SetArgument);
fpizlo@apple.com4f5361262012-02-16 10:06:28 +000090 if (!node.shouldGenerate()) {
91 // The argument is dead. We don't do any checks for such arguments, and so
92 // for the purpose of the analysis, they contain no value.
93 root->valuesAtHead.argument(i).clear();
94 continue;
95 }
96
fpizlo@apple.com1688cc12012-05-23 07:29:02 +000097 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +000098 root->valuesAtHead.argument(i).makeTop();
99 continue;
100 }
101
fpizlo@apple.com62336162012-06-07 01:35:59 +0000102 SpeculatedType prediction = node.variableAccessData()->prediction();
103 if (isInt32Speculation(prediction))
104 root->valuesAtHead.argument(i).set(SpecInt32);
105 else if (isArraySpeculation(prediction))
106 root->valuesAtHead.argument(i).set(SpecArray);
107 else if (isBooleanSpeculation(prediction))
108 root->valuesAtHead.argument(i).set(SpecBoolean);
109 else if (isInt8ArraySpeculation(prediction))
110 root->valuesAtHead.argument(i).set(SpecInt8Array);
111 else if (isInt16ArraySpeculation(prediction))
112 root->valuesAtHead.argument(i).set(SpecInt16Array);
113 else if (isInt32ArraySpeculation(prediction))
114 root->valuesAtHead.argument(i).set(SpecInt32Array);
115 else if (isUint8ArraySpeculation(prediction))
116 root->valuesAtHead.argument(i).set(SpecUint8Array);
117 else if (isUint8ClampedArraySpeculation(prediction))
118 root->valuesAtHead.argument(i).set(SpecUint8ClampedArray);
119 else if (isUint16ArraySpeculation(prediction))
120 root->valuesAtHead.argument(i).set(SpecUint16Array);
121 else if (isUint32ArraySpeculation(prediction))
122 root->valuesAtHead.argument(i).set(SpecUint32Array);
123 else if (isFloat32ArraySpeculation(prediction))
124 root->valuesAtHead.argument(i).set(SpecFloat32Array);
125 else if (isFloat64ArraySpeculation(prediction))
126 root->valuesAtHead.argument(i).set(SpecFloat64Array);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000127 else
128 root->valuesAtHead.argument(i).makeTop();
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000129
130 root->valuesAtTail.argument(i).clear();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000131 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000132 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000133 NodeIndex nodeIndex = root->variablesAtHead.local(i);
134 if (nodeIndex != NoNode && graph[nodeIndex].variableAccessData()->isCaptured())
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000135 root->valuesAtHead.local(i).makeTop();
136 else
137 root->valuesAtHead.local(i).clear();
138 root->valuesAtTail.local(i).clear();
139 }
140 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
141 BasicBlock* block = graph.m_blocks[blockIndex].get();
142 if (!block)
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000143 continue;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000144 if (!block->isReachable)
145 continue;
146 block->cfaShouldRevisit = false;
147 block->cfaHasVisited = false;
148 block->cfaFoundConstants = false;
149 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
150 block->valuesAtHead.argument(i).clear();
151 block->valuesAtTail.argument(i).clear();
152 }
153 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
154 block->valuesAtHead.local(i).clear();
155 block->valuesAtTail.local(i).clear();
156 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000157 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000158}
159
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000160bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000161{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000162 ASSERT(m_block);
163
164 BasicBlock* block = m_block; // Save the block for successor merging.
165
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000166 block->cfaFoundConstants = m_foundConstants;
167
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000168 if (!m_isValid) {
169 reset();
170 return false;
171 }
172
173 bool changed = false;
174
175 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000176 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
177#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000178 dataLog(" Merging state for argument %zu.\n", argument);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000179#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000180 AbstractValue& destination = block->valuesAtTail.argument(argument);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000181 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000182 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000183
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000184 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
185#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000186 dataLog(" Merging state for local %zu.\n", local);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000187#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000188 AbstractValue& destination = block->valuesAtTail.local(local);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000189 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000190 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000191 }
192
193 ASSERT(mergeMode != DontMerge || !changed);
194
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000195 BranchDirection branchDirection = m_branchDirection;
196 if (branchDirectionPtr)
197 *branchDirectionPtr = branchDirection;
198
199#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
200 dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection));
201#endif
202
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000203 reset();
204
205 if (mergeMode != MergeToSuccessors)
206 return changed;
207
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000208 return mergeToSuccessors(m_graph, block, branchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000209}
210
211void AbstractState::reset()
212{
213 m_block = 0;
214 m_isValid = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000215 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000216}
217
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000218bool AbstractState::execute(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000219{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000220 ASSERT(m_block);
221 ASSERT(m_isValid);
222
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000223 NodeIndex nodeIndex = m_block->at(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000224 Node& node = m_graph[nodeIndex];
225
226 if (!node.shouldGenerate())
227 return true;
228
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000229 switch (node.op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000230 case JSConstant:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +0000231 case WeakJSConstant:
232 case PhantomArguments: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000233 forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000234 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000235 break;
236 }
237
238 case GetLocal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000239 VariableAccessData* variableAccessData = node.variableAccessData();
240 bool canExit = false;
fpizlo@apple.com62336162012-06-07 01:35:59 +0000241 canExit |= variableAccessData->prediction() == SpecNone;
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000242 AbstractValue value = m_variables.operand(variableAccessData->local());
243 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000244 if (value.isClear())
245 canExit |= true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000246 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000247 if (value.value())
248 m_foundConstants = true;
249 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000250 node.setCanExit(canExit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000251 break;
252 }
253
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000254 case GetLocalUnlinked: {
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000255 AbstractValue value = m_variables.operand(node.unlinkedLocal());
256 if (value.value())
257 m_foundConstants = true;
258 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000259 node.setCanExit(false);
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000260 break;
261 }
262
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000263 case SetLocal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000264 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000265 m_variables.operand(node.local()) = forNode(node.child1());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000266 node.setCanExit(false);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000267 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000268 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000269
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000270 if (node.variableAccessData()->shouldUseDoubleFormat()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000271 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000272 m_variables.operand(node.local()).set(SpecDouble);
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000273 break;
274 }
275
fpizlo@apple.com62336162012-06-07 01:35:59 +0000276 SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
277 if (isInt32Speculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000278 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000279 else if (isArraySpeculation(predictedType)) {
280 node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
281 forNode(node.child1()).filter(SpecArray);
282 } else if (isBooleanSpeculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000283 speculateBooleanUnary(node);
284 else
285 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000286
287 m_variables.operand(node.local()) = forNode(node.child1());
288 break;
289 }
290
291 case SetArgument:
292 // Assert that the state of arguments has been set.
293 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000294 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000295 break;
296
297 case BitAnd:
298 case BitOr:
299 case BitXor:
300 case BitRShift:
301 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000302 case BitURShift: {
303 JSValue left = forNode(node.child1()).value();
304 JSValue right = forNode(node.child2()).value();
305 if (left && right && left.isInt32() && right.isInt32()) {
306 int32_t a = left.asInt32();
307 int32_t b = right.asInt32();
308 switch (node.op()) {
309 case BitAnd:
310 forNode(nodeIndex).set(JSValue(a & b));
311 break;
312 case BitOr:
313 forNode(nodeIndex).set(JSValue(a | b));
314 break;
315 case BitXor:
316 forNode(nodeIndex).set(JSValue(a ^ b));
317 break;
318 case BitRShift:
319 forNode(nodeIndex).set(JSValue(a >> static_cast<uint32_t>(b)));
320 break;
321 case BitLShift:
322 forNode(nodeIndex).set(JSValue(a << static_cast<uint32_t>(b)));
323 break;
324 case BitURShift:
325 forNode(nodeIndex).set(JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
326 break;
327 default:
328 ASSERT_NOT_REACHED();
329 }
330 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000331 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000332 break;
333 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000334 speculateInt32Binary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000335 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000336 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000337 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000338
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000339 case UInt32ToNumber: {
340 JSValue child = forNode(node.child1()).value();
341 if (child && child.isNumber()) {
342 ASSERT(child.isInt32());
343 forNode(nodeIndex).set(JSValue(child.asUInt32()));
344 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000345 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000346 break;
347 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000348 if (!node.canSpeculateInteger()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000349 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000350 node.setCanExit(false);
351 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000352 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000353 node.setCanExit(true);
354 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000355 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000356 }
357
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000358
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000359 case DoubleAsInt32: {
360 JSValue child = forNode(node.child1()).value();
361 if (child && child.isNumber()) {
362 double asDouble = child.asNumber();
363 int32_t asInt = JSC::toInt32(asDouble);
364 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
365 forNode(nodeIndex).set(JSValue(asInt));
366 m_foundConstants = true;
367 break;
368 }
369 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000370 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000371 forNode(node.child1()).filter(SpecNumber);
372 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000373 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000374 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000375
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000376 case ValueToInt32: {
377 JSValue child = forNode(node.child1()).value();
378 if (child && child.isNumber()) {
379 if (child.isInt32())
380 forNode(nodeIndex).set(child);
381 else
382 forNode(nodeIndex).set(JSValue(JSC::toInt32(child.asDouble())));
383 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000384 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000385 break;
386 }
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000387 if (m_graph[node.child1()].shouldSpeculateInteger())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000388 speculateInt32Unary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000389 else if (m_graph[node.child1()].shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000390 speculateNumberUnary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000391 else if (m_graph[node.child1()].shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000392 speculateBooleanUnary(node);
393 else
394 node.setCanExit(false);
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000395
fpizlo@apple.com62336162012-06-07 01:35:59 +0000396 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000397 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000398 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000399
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000400 case Int32ToDouble: {
401 JSValue child = forNode(node.child1()).value();
402 if (child && child.isNumber()) {
403 forNode(nodeIndex).set(JSValue(JSValue::EncodeAsDouble, child.asNumber()));
404 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000405 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000406 break;
407 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000408 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000409 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000410 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000411 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000412
413 case CheckNumber:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000414 forNode(node.child1()).filter(SpecNumber);
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000415 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000416
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000417 case ValueAdd:
418 case ArithAdd: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000419 JSValue left = forNode(node.child1()).value();
420 JSValue right = forNode(node.child2()).value();
421 if (left && right && left.isNumber() && right.isNumber()) {
422 forNode(nodeIndex).set(JSValue(left.asNumber() + right.asNumber()));
423 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000424 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000425 break;
426 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000427 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000428 speculateInt32Binary(
429 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000430 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000431 break;
432 }
433 if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000434 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000435 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000436 break;
437 }
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000438 if (node.op() == ValueAdd) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000439 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000440 forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000441 node.setCanExit(false);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000442 break;
443 }
444 // We don't handle this yet. :-(
445 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000446 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000447 break;
448 }
449
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000450 case ArithSub: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000451 JSValue left = forNode(node.child1()).value();
452 JSValue right = forNode(node.child2()).value();
453 if (left && right && left.isNumber() && right.isNumber()) {
454 forNode(nodeIndex).set(JSValue(left.asNumber() - right.asNumber()));
455 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000456 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000457 break;
458 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000459 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000460 speculateInt32Binary(
461 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000462 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000463 break;
464 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000465 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000466 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000467 break;
468 }
469
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000470 case ArithNegate: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000471 JSValue child = forNode(node.child1()).value();
472 if (child && child.isNumber()) {
473 forNode(nodeIndex).set(JSValue(-child.asNumber()));
474 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000475 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000476 break;
477 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000478 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000479 speculateInt32Unary(
480 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000481 forNode(nodeIndex).set(SpecInt32);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000482 break;
483 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000484 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000485 forNode(nodeIndex).set(SpecDouble);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000486 break;
487 }
488
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000489 case ArithMul: {
490 JSValue left = forNode(node.child1()).value();
491 JSValue right = forNode(node.child2()).value();
492 if (left && right && left.isNumber() && right.isNumber()) {
493 forNode(nodeIndex).set(JSValue(left.asNumber() * right.asNumber()));
494 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000495 node.setCanExit(false);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000496 break;
497 }
498 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000499 speculateInt32Binary(
500 node,
501 !nodeCanTruncateInteger(node.arithNodeFlags())
502 || !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000503 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000504 break;
505 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000506 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000507 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000508 break;
509 }
510
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000511 case ArithDiv:
512 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000513 case ArithMax:
514 case ArithMod: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000515 JSValue left = forNode(node.child1()).value();
516 JSValue right = forNode(node.child2()).value();
517 if (left && right && left.isNumber() && right.isNumber()) {
518 double a = left.asNumber();
519 double b = right.asNumber();
520 switch (node.op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000521 case ArithDiv:
522 forNode(nodeIndex).set(JSValue(a / b));
523 break;
524 case ArithMin:
525 forNode(nodeIndex).set(JSValue(a < b ? a : (b <= a ? b : a + b)));
526 break;
527 case ArithMax:
528 forNode(nodeIndex).set(JSValue(a > b ? a : (b >= a ? b : a + b)));
529 break;
530 case ArithMod:
531 forNode(nodeIndex).set(JSValue(fmod(a, b)));
532 break;
533 default:
534 ASSERT_NOT_REACHED();
535 break;
536 }
537 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000538 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000539 break;
540 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000541 if (Node::shouldSpeculateInteger(
542 m_graph[node.child1()], m_graph[node.child2()])
543 && node.canSpeculateInteger()) {
544 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
fpizlo@apple.com62336162012-06-07 01:35:59 +0000545 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000546 break;
547 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000548 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000549 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000550 break;
551 }
552
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000553 case ArithAbs: {
554 JSValue child = forNode(node.child1()).value();
555 if (child && child.isNumber()) {
556 forNode(nodeIndex).set(JSValue(fabs(child.asNumber())));
557 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000558 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000559 break;
560 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000561 if (m_graph[node.child1()].shouldSpeculateInteger()
562 && node.canSpeculateInteger()) {
563 speculateInt32Unary(node, true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000564 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000565 break;
566 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000567 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000568 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000569 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000570 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000571
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000572 case ArithSqrt: {
573 JSValue child = forNode(node.child1()).value();
574 if (child && child.isNumber()) {
575 forNode(nodeIndex).set(JSValue(sqrt(child.asNumber())));
576 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000577 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000578 break;
579 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000580 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000581 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000582 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000583 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000584
585 case LogicalNot: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000586 JSValue childConst = forNode(node.child1()).value();
587 if (childConst) {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000588 forNode(nodeIndex).set(jsBoolean(!childConst.toBoolean()));
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000589 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000590 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000591 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000592 Node& child = m_graph[node.child1()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000593 if (isBooleanSpeculation(child.prediction()))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000594 speculateBooleanUnary(node);
595 else if (child.shouldSpeculateFinalObjectOrOther()) {
596 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000597 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
598 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000599 } else if (child.shouldSpeculateArrayOrOther()) {
600 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000601 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
602 forNode(node.child1()).filter(SpecArray | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000603 } else if (child.shouldSpeculateInteger())
604 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000605 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000606 speculateNumberUnary(node);
607 else
608 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000609 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000610 break;
611 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000612
613 case IsUndefined:
614 case IsBoolean:
615 case IsNumber:
616 case IsString:
617 case IsObject:
618 case IsFunction: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000619 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000620 JSValue child = forNode(node.child1()).value();
621 if (child) {
622 bool foundConstant = true;
623 switch (node.op()) {
624 case IsUndefined:
625 forNode(nodeIndex).set(jsBoolean(
626 child.isCell()
627 ? child.asCell()->structure()->typeInfo().masqueradesAsUndefined()
628 : child.isUndefined()));
629 break;
630 case IsBoolean:
631 forNode(nodeIndex).set(jsBoolean(child.isBoolean()));
632 break;
633 case IsNumber:
634 forNode(nodeIndex).set(jsBoolean(child.isNumber()));
635 break;
636 case IsString:
637 forNode(nodeIndex).set(jsBoolean(isJSString(child)));
638 break;
639 default:
640 break;
641 }
642 if (foundConstant) {
643 m_foundConstants = true;
644 break;
645 }
646 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000647 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000648 break;
649 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000650
651 case CompareLess:
652 case CompareLessEq:
653 case CompareGreater:
654 case CompareGreaterEq:
655 case CompareEq: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000656 JSValue leftConst = forNode(node.child1()).value();
657 JSValue rightConst = forNode(node.child2()).value();
658 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
659 double a = leftConst.asNumber();
660 double b = rightConst.asNumber();
661 switch (node.op()) {
662 case CompareLess:
663 forNode(nodeIndex).set(jsBoolean(a < b));
664 break;
665 case CompareLessEq:
666 forNode(nodeIndex).set(jsBoolean(a <= b));
667 break;
668 case CompareGreater:
669 forNode(nodeIndex).set(jsBoolean(a > b));
670 break;
671 case CompareGreaterEq:
672 forNode(nodeIndex).set(jsBoolean(a >= b));
673 break;
674 case CompareEq:
675 forNode(nodeIndex).set(jsBoolean(a == b));
676 break;
677 default:
678 ASSERT_NOT_REACHED();
679 break;
680 }
681 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000682 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000683 break;
684 }
685
fpizlo@apple.com62336162012-06-07 01:35:59 +0000686 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000687
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000688 Node& left = m_graph[node.child1()];
689 Node& right = m_graph[node.child2()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000690 SpeculatedType filter;
691 SpeculatedTypeChecker checker;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000692 if (Node::shouldSpeculateInteger(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000693 filter = SpecInt32;
694 checker = isInt32Speculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000695 } else if (Node::shouldSpeculateNumber(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000696 filter = SpecNumber;
697 checker = isNumberSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000698 } else if (node.op() == CompareEq) {
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000699 if ((m_graph.isConstant(node.child1().index())
700 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
701 || (m_graph.isConstant(node.child2().index())
702 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
703 // We know that this won't clobber the world. But that's all we know.
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000704 node.setCanExit(false);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000705 break;
706 }
707
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000708 if (Node::shouldSpeculateFinalObject(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000709 filter = SpecFinalObject;
710 checker = isFinalObjectSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000711 } else if (Node::shouldSpeculateArray(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000712 filter = SpecArray;
713 checker = isArraySpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000714 } else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
715 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000716 !isFinalObjectSpeculation(forNode(node.child1()).m_type)
717 || !isFinalObjectOrOtherSpeculation(forNode(node.child2()).m_type));
718 forNode(node.child1()).filter(SpecFinalObject);
719 forNode(node.child2()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000720 break;
721 } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000722 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000723 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type)
724 || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
725 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
726 forNode(node.child2()).filter(SpecFinalObject);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000727 break;
728 } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000729 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000730 !isArraySpeculation(forNode(node.child1()).m_type)
731 || !isArrayOrOtherSpeculation(forNode(node.child2()).m_type));
732 forNode(node.child1()).filter(SpecArray);
733 forNode(node.child2()).filter(SpecArray | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000734 break;
735 } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000736 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000737 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type)
738 || !isArraySpeculation(forNode(node.child2()).m_type));
739 forNode(node.child1()).filter(SpecArray | SpecOther);
740 forNode(node.child2()).filter(SpecArray);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000741 break;
742 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000743 filter = SpecTop;
744 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000745 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000746 }
747 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000748 filter = SpecTop;
749 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000750 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000751 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000752 node.setCanExit(
753 !checker(forNode(node.child1()).m_type)
754 || !checker(forNode(node.child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000755 forNode(node.child1()).filter(filter);
756 forNode(node.child2()).filter(filter);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000757 break;
758 }
759
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000760 case CompareStrictEq: {
761 JSValue left = forNode(node.child1()).value();
762 JSValue right = forNode(node.child2()).value();
763 if (left && right && left.isNumber() && right.isNumber()) {
764 forNode(nodeIndex).set(jsBoolean(left.asNumber() == right.asNumber()));
765 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000766 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000767 break;
768 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000769 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000770 if (m_graph.isJSConstant(node.child1().index())) {
771 JSValue value = m_graph.valueOfJSConstant(node.child1().index());
772 if (!value.isNumber() && !value.isString()) {
773 node.setCanExit(false);
774 break;
775 }
776 }
777 if (m_graph.isJSConstant(node.child2().index())) {
778 JSValue value = m_graph.valueOfJSConstant(node.child2().index());
779 if (!value.isNumber() && !value.isString()) {
780 node.setCanExit(false);
781 break;
782 }
783 }
784 if (Node::shouldSpeculateInteger(
785 m_graph[node.child1()], m_graph[node.child2()])) {
786 speculateInt32Binary(node);
787 break;
788 }
789 if (Node::shouldSpeculateNumber(
790 m_graph[node.child1()], m_graph[node.child2()])) {
791 speculateNumberBinary(node);
792 break;
793 }
794 if (Node::shouldSpeculateFinalObject(
795 m_graph[node.child1()], m_graph[node.child2()])) {
796 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000797 !isFinalObjectSpeculation(forNode(node.child1()).m_type)
798 || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
799 forNode(node.child1()).filter(SpecFinalObject);
800 forNode(node.child2()).filter(SpecFinalObject);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000801 break;
802 }
803 if (Node::shouldSpeculateArray(
804 m_graph[node.child1()], m_graph[node.child2()])) {
805 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000806 !isArraySpeculation(forNode(node.child1()).m_type)
807 || !isArraySpeculation(forNode(node.child2()).m_type));
808 forNode(node.child1()).filter(SpecArray);
809 forNode(node.child2()).filter(SpecArray);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000810 break;
811 }
812 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000813 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000814 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000815
816 case StringCharCodeAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000817 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000818 forNode(node.child1()).filter(SpecString);
819 forNode(node.child2()).filter(SpecInt32);
820 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000821 break;
822
823 case StringCharAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000824 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000825 forNode(node.child1()).filter(SpecString);
826 forNode(node.child2()).filter(SpecInt32);
827 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000828 break;
829
830 case GetByVal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000831 node.setCanExit(true);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000832 if (!node.prediction() || !m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
833 m_isValid = false;
834 break;
835 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000836 if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000837 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000838 forNode(nodeIndex).makeTop();
839 break;
840 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000841 if (m_graph[node.child1()].shouldSpeculateArguments()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000842 forNode(node.child1()).filter(SpecArguments);
843 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000844 forNode(nodeIndex).makeTop();
845 break;
846 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000847 if (m_graph[node.child1()].prediction() == SpecString) {
848 forNode(node.child1()).filter(SpecString);
849 forNode(node.child2()).filter(SpecInt32);
850 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000851 break;
852 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000853
854 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000855 forNode(node.child1()).filter(SpecInt8Array);
856 forNode(node.child2()).filter(SpecInt32);
857 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000858 break;
859 }
860 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000861 forNode(node.child1()).filter(SpecInt16Array);
862 forNode(node.child2()).filter(SpecInt32);
863 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000864 break;
865 }
866 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000867 forNode(node.child1()).filter(SpecInt32Array);
868 forNode(node.child2()).filter(SpecInt32);
869 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000870 break;
871 }
872 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000873 forNode(node.child1()).filter(SpecUint8Array);
874 forNode(node.child2()).filter(SpecInt32);
875 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000876 break;
877 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000878 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000879 forNode(node.child1()).filter(SpecUint8ClampedArray);
880 forNode(node.child2()).filter(SpecInt32);
881 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000882 break;
883 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000884 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000885 forNode(node.child1()).filter(SpecUint16Array);
886 forNode(node.child2()).filter(SpecInt32);
887 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000888 break;
889 }
890 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000891 forNode(node.child1()).filter(SpecUint32Array);
892 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000893 if (node.shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000894 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000895 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000896 forNode(nodeIndex).set(SpecDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000897 break;
898 }
oliver@apple.com07d75732011-12-03 01:47:27 +0000899 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000900 forNode(node.child1()).filter(SpecFloat32Array);
901 forNode(node.child2()).filter(SpecInt32);
902 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000903 break;
904 }
905 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000906 forNode(node.child1()).filter(SpecFloat64Array);
907 forNode(node.child2()).filter(SpecInt32);
908 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000909 break;
910 }
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000911 ASSERT(m_graph[node.child1()].shouldSpeculateArray());
fpizlo@apple.com62336162012-06-07 01:35:59 +0000912 forNode(node.child1()).filter(SpecArray);
913 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000914 forNode(nodeIndex).makeTop();
915 break;
916 }
917
918 case PutByVal:
919 case PutByValAlias: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000920 node.setCanExit(true);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000921 if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
922 m_isValid = false;
923 break;
924 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000925 if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[node.child1()].prediction())
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000926#if USE(JSVALUE32_64)
927 || m_graph[node.child1()].shouldSpeculateArguments()
928#endif
929 ) {
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000930 ASSERT(node.op() == PutByVal);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000931 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000932 forNode(nodeIndex).makeTop();
933 break;
934 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000935
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000936 if (m_graph[node.child1()].shouldSpeculateArguments()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000937 forNode(node.child1()).filter(SpecArguments);
938 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000939 break;
940 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000941 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000942 forNode(node.child1()).filter(SpecInt8Array);
943 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000944 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000945 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000946 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000947 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000948 break;
949 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000950 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000951 forNode(node.child1()).filter(SpecInt16Array);
952 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000953 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000954 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000955 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000956 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000957 break;
958 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000959 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000960 forNode(node.child1()).filter(SpecInt32Array);
961 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000962 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000963 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000964 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000965 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000966 break;
967 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000968 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000969 forNode(node.child1()).filter(SpecUint8Array);
970 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000971 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000972 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000973 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000974 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000975 break;
976 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000977 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000978 forNode(node.child1()).filter(SpecUint8ClampedArray);
979 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000980 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000981 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000982 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000983 forNode(node.child3()).filter(SpecNumber);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000984 break;
985 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000986 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000987 forNode(node.child1()).filter(SpecUint16Array);
988 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000989 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000990 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000991 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000992 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000993 break;
994 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000995 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000996 forNode(node.child1()).filter(SpecUint32Array);
997 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000998 if (m_graph[node.child3()].shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000999 forNode(node.child3()).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001000 else
fpizlo@apple.com62336162012-06-07 01:35:59 +00001001 forNode(node.child3()).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001002 break;
1003 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +00001004 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001005 forNode(node.child1()).filter(SpecFloat32Array);
1006 forNode(node.child2()).filter(SpecInt32);
1007 forNode(node.child3()).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001008 break;
1009 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +00001010 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001011 forNode(node.child1()).filter(SpecFloat64Array);
1012 forNode(node.child2()).filter(SpecInt32);
1013 forNode(node.child3()).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001014 break;
1015 }
fpizlo@apple.com6306b5652011-12-23 05:47:17 +00001016 ASSERT(m_graph[node.child1()].shouldSpeculateArray());
fpizlo@apple.com62336162012-06-07 01:35:59 +00001017 forNode(node.child1()).filter(SpecArray);
1018 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.coma4754892012-06-02 00:22:31 +00001019 if (node.op() == PutByVal)
1020 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001021 break;
1022 }
1023
1024 case ArrayPush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001025 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001026 forNode(node.child1()).filter(SpecArray);
1027 forNode(nodeIndex).set(SpecNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001028 break;
1029
1030 case ArrayPop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001031 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001032 forNode(node.child1()).filter(SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001033 forNode(nodeIndex).makeTop();
1034 break;
1035
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001036 case RegExpExec:
1037 case RegExpTest:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001038 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001039 !isCellSpeculation(forNode(node.child1()).m_type)
1040 || !isCellSpeculation(forNode(node.child2()).m_type));
1041 forNode(node.child1()).filter(SpecCell);
1042 forNode(node.child2()).filter(SpecCell);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001043 forNode(nodeIndex).makeTop();
1044 break;
1045
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001046 case Jump:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001047 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001048 break;
1049
1050 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001051 JSValue value = forNode(node.child1()).value();
1052 if (value) {
1053 bool booleanValue = value.toBoolean();
1054 if (booleanValue)
1055 m_branchDirection = TakeTrue;
1056 else
1057 m_branchDirection = TakeFalse;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001058 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001059 break;
1060 }
1061 // FIXME: The above handles the trivial cases of sparse conditional
1062 // constant propagation, but we can do better:
1063 // 1) If the abstract value does not have a concrete value but describes
1064 // something that is known to evaluate true (or false) then we ought
1065 // to sparse conditional that.
1066 // 2) We can specialize the source variable's value on each direction of
1067 // the branch.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001068 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +00001069 if (child.shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001070 speculateBooleanUnary(node);
1071 else if (child.shouldSpeculateFinalObjectOrOther()) {
1072 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001073 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
1074 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001075 } else if (child.shouldSpeculateArrayOrOther()) {
1076 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001077 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
1078 forNode(node.child1()).filter(SpecArray | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001079 } else if (child.shouldSpeculateInteger())
1080 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001081 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001082 speculateNumberUnary(node);
1083 else
1084 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001085 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001086 break;
1087 }
1088
1089 case Return:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001090 m_isValid = false;
1091 node.setCanExit(false);
1092 break;
1093
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001094 case Throw:
1095 case ThrowReferenceError:
1096 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001097 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001098 break;
1099
1100 case ToPrimitive: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001101 JSValue childConst = forNode(node.child1()).value();
1102 if (childConst && childConst.isNumber()) {
1103 forNode(nodeIndex).set(childConst);
1104 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001105 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001106 break;
1107 }
1108
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001109 Node& child = m_graph[node.child1()];
1110 if (child.shouldSpeculateInteger()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001111 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001112 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001113 break;
1114 }
1115
1116 AbstractValue& source = forNode(node.child1());
1117 AbstractValue& destination = forNode(nodeIndex);
1118
fpizlo@apple.com62336162012-06-07 01:35:59 +00001119 SpeculatedType type = source.m_type;
1120 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1121 type &= (SpecNumber | SpecString | SpecBoolean);
1122 type |= SpecString;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001123 }
1124 destination.set(type);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001125 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001126 break;
1127 }
1128
1129 case StrCat:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001130 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001131 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001132 break;
1133
1134 case NewArray:
1135 case NewArrayBuffer:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001136 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001137 forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
1138 m_haveStructures = true;
1139 break;
1140
1141 case NewRegexp:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001142 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001143 forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
1144 m_haveStructures = true;
1145 break;
1146
1147 case ConvertThis: {
1148 Node& child = m_graph[node.child1()];
1149 AbstractValue& source = forNode(node.child1());
1150 AbstractValue& destination = forNode(nodeIndex);
1151
fpizlo@apple.com62336162012-06-07 01:35:59 +00001152 if (isObjectSpeculation(source.m_type)) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001153 // This is the simple case. We already know that the source is an
1154 // object, so there's nothing to do. I don't think this case will
1155 // be hit, but then again, you never know.
1156 destination = source;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001157 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001158 break;
1159 }
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001160
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001161 node.setCanExit(true);
1162
fpizlo@apple.com62336162012-06-07 01:35:59 +00001163 if (isOtherSpeculation(child.prediction())) {
1164 source.filter(SpecOther);
1165 destination.set(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001166 break;
1167 }
1168
fpizlo@apple.com62336162012-06-07 01:35:59 +00001169 if (isObjectSpeculation(child.prediction())) {
1170 source.filter(SpecObjectMask);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001171 destination = source;
1172 break;
1173 }
1174
1175 destination = source;
fpizlo@apple.com62336162012-06-07 01:35:59 +00001176 destination.merge(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001177 break;
1178 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001179
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001180 case CreateThis: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001181 AbstractValue& source = forNode(node.child1());
1182 AbstractValue& destination = forNode(nodeIndex);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001183
fpizlo@apple.com62336162012-06-07 01:35:59 +00001184 node.setCanExit(!isCellSpeculation(source.m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001185
fpizlo@apple.com62336162012-06-07 01:35:59 +00001186 source.filter(SpecFunction);
1187 destination.set(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001188 break;
1189 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001190
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001191 case NewObject:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001192 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001193 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001194 m_haveStructures = true;
1195 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001196
1197 case CreateActivation:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001198 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001199 forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get());
1200 m_haveStructures = true;
1201 break;
1202
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001203 case CreateArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001204 node.setCanExit(false);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001205 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1206 m_haveStructures = true;
1207 break;
1208
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001209 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001210 case TearOffArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001211 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001212 // Does nothing that is user-visible.
1213 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001214
1215 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001216 if (isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001217 m_variables.operand(
fpizlo@apple.comb80bc2a32012-06-02 22:58:48 +00001218 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
1219 node.setCanExit(false);
1220 m_foundConstants = true;
1221 } else
1222 node.setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001223 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001224
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001225 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001226 // We know that this executable does not escape its arguments, so we can optimize
1227 // the arguments a bit. Note that this is not sufficient to force constant folding
1228 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1229 // We perform further optimizations on this later on.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001230 if (node.codeOrigin.inlineCallFrame)
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001231 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001232 else
fpizlo@apple.com62336162012-06-07 01:35:59 +00001233 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001234 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001235 !isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001236 m_variables.operand(
1237 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001238 break;
1239
1240 case GetMyArgumentsLengthSafe:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001241 node.setCanExit(false);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001242 // This potentially clobbers all structures if the arguments object had a getter
1243 // installed on the length property.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001244 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001245 // We currently make no guarantee about what this returns because it does not
1246 // speculate that the length property is actually a length.
1247 forNode(nodeIndex).makeTop();
1248 break;
1249
1250 case GetMyArgumentByVal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001251 node.setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001252 // We know that this executable does not escape its arguments, so we can optimize
1253 // the arguments a bit. Note that this ends up being further optimized by the
1254 // ArgumentsSimplificationPhase.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001255 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001256 forNode(nodeIndex).makeTop();
1257 break;
1258
1259 case GetMyArgumentByValSafe:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001260 node.setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001261 // This potentially clobbers all structures if the property we're accessing has
1262 // a getter. We don't speculate against this.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001263 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001264 // But we do speculate that the index is an integer.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001265 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001266 // And the result is unknown.
1267 forNode(nodeIndex).makeTop();
1268 break;
1269
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001270 case NewFunction:
1271 case NewFunctionExpression:
1272 case NewFunctionNoCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001273 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001274 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1275 break;
1276
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001277 case GetCallee:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001278 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001279 forNode(nodeIndex).set(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001280 break;
1281
1282 case GetScopeChain:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001283 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001284 forNode(nodeIndex).set(SpecCellOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001285 break;
1286
1287 case GetScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001288 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001289 forNode(nodeIndex).makeTop();
1290 break;
1291
1292 case PutScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001293 node.setCanExit(false);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001294 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001295 break;
1296
1297 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001298 case GetByIdFlush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001299 node.setCanExit(true);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001300 if (!node.prediction()) {
1301 m_isValid = false;
1302 break;
1303 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001304 if (isCellSpeculation(m_graph[node.child1()].prediction()))
1305 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001306 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001307 forNode(nodeIndex).makeTop();
1308 break;
1309
1310 case GetArrayLength:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001311 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001312 forNode(node.child1()).filter(SpecArray);
1313 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001314 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001315
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001316 case GetArgumentsLength:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001317 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001318 forNode(node.child1()).filter(SpecArguments);
1319 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001320 break;
1321
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001322 case GetStringLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001323 node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
1324 forNode(node.child1()).filter(SpecString);
1325 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001326 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001327
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001328 case GetInt8ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001329 node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
1330 forNode(node.child1()).filter(SpecInt8Array);
1331 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001332 break;
1333 case GetInt16ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001334 node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
1335 forNode(node.child1()).filter(SpecInt16Array);
1336 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001337 break;
1338 case GetInt32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001339 node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
1340 forNode(node.child1()).filter(SpecInt32Array);
1341 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001342 break;
1343 case GetUint8ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001344 node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
1345 forNode(node.child1()).filter(SpecUint8Array);
1346 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001347 break;
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001348 case GetUint8ClampedArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001349 node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
1350 forNode(node.child1()).filter(SpecUint8ClampedArray);
1351 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001352 break;
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001353 case GetUint16ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001354 node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
1355 forNode(node.child1()).filter(SpecUint16Array);
1356 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001357 break;
1358 case GetUint32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001359 node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
1360 forNode(node.child1()).filter(SpecUint32Array);
1361 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001362 break;
1363 case GetFloat32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001364 node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
1365 forNode(node.child1()).filter(SpecFloat32Array);
1366 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001367 break;
1368 case GetFloat64ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001369 node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
1370 forNode(node.child1()).filter(SpecFloat64Array);
1371 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001372 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001373
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001374 case CheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001375 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001376 AbstractValue& value = forNode(node.child1());
1377 node.setCanExit(
1378 !value.m_structure.isSubsetOf(node.structureSet())
fpizlo@apple.com62336162012-06-07 01:35:59 +00001379 || !isCellSpeculation(value.m_type));
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001380 value.filter(node.structureSet());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001381 m_haveStructures = true;
1382 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001383 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001384
1385 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001386 case PhantomPutStructure:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001387 node.setCanExit(false);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001388 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001389 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1390 m_haveStructures = true;
1391 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001392 case GetPropertyStorage:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001393 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001394 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001395 forNode(nodeIndex).clear(); // The result is not a JS value.
1396 break;
oliver@apple.com43e511c2011-12-09 08:45:46 +00001397 case GetIndexedPropertyStorage: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001398 node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001399 SpeculatedType basePrediction = m_graph[node.child2()].prediction();
1400 if (!(basePrediction & SpecInt32) && basePrediction) {
oliver@apple.com43e511c2011-12-09 08:45:46 +00001401 forNode(nodeIndex).clear();
1402 break;
1403 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001404 if (m_graph[node.child1()].shouldSpeculateArguments()) {
1405 ASSERT_NOT_REACHED();
1406 break;
1407 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001408 if (m_graph[node.child1()].prediction() == SpecString) {
1409 forNode(node.child1()).filter(SpecString);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001410 forNode(nodeIndex).clear();
1411 break;
1412 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001413
1414 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001415 forNode(node.child1()).filter(SpecInt8Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001416 forNode(nodeIndex).clear();
1417 break;
1418 }
1419 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001420 forNode(node.child1()).filter(SpecInt16Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001421 forNode(nodeIndex).clear();
1422 break;
1423 }
1424 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001425 forNode(node.child1()).filter(SpecInt32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001426 forNode(nodeIndex).clear();
1427 break;
1428 }
1429 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001430 forNode(node.child1()).filter(SpecUint8Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001431 forNode(nodeIndex).clear();
1432 break;
1433 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001434 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001435 forNode(node.child1()).filter(SpecUint8ClampedArray);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001436 forNode(nodeIndex).clear();
1437 break;
1438 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001439 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001440 forNode(node.child1()).filter(SpecUint16Array);
1441 forNode(nodeIndex).set(SpecOther);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001442 break;
1443 }
1444 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001445 forNode(node.child1()).filter(SpecUint32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001446 forNode(nodeIndex).clear();
1447 break;
1448 }
1449 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001450 forNode(node.child1()).filter(SpecFloat32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001451 forNode(nodeIndex).clear();
1452 break;
1453 }
1454 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001455 forNode(node.child1()).filter(SpecFloat64Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001456 forNode(nodeIndex).clear();
1457 break;
1458 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001459 forNode(node.child1()).filter(SpecArray);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001460 forNode(nodeIndex).clear();
1461 break;
1462 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001463 case GetByOffset:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001464 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001465 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001466 forNode(nodeIndex).makeTop();
1467 break;
1468
1469 case PutByOffset:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001470 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001471 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001472 break;
1473
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001474 case CheckFunction:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001475 node.setCanExit(true); // Lies! We can do better.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001476 forNode(node.child1()).filter(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001477 // FIXME: Should be able to propagate the fact that we know what the function is.
1478 break;
1479
1480 case PutById:
1481 case PutByIdDirect:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001482 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001483 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001484 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001485 break;
1486
1487 case GetGlobalVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001488 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001489 forNode(nodeIndex).makeTop();
1490 break;
1491
1492 case PutGlobalVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001493 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001494 break;
1495
1496 case CheckHasInstance:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001497 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001498 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001499 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1500 break;
1501
1502 case InstanceOf:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001503 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001504 // Again, sadly, we don't propagate the fact that we've done InstanceOf
fpizlo@apple.com62336162012-06-07 01:35:59 +00001505 if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
1506 forNode(node.child1()).filter(SpecCell);
1507 forNode(node.child3()).filter(SpecCell);
1508 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001509 break;
1510
1511 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001512 case Flush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001513 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001514 break;
1515
1516 case Breakpoint:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001517 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001518 break;
1519
1520 case Call:
1521 case Construct:
1522 case Resolve:
1523 case ResolveBase:
1524 case ResolveBaseStrictPut:
1525 case ResolveGlobal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001526 node.setCanExit(true);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001527 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001528 forNode(nodeIndex).makeTop();
1529 break;
1530
1531 case ForceOSRExit:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001532 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001533 m_isValid = false;
1534 break;
1535
1536 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001537 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001538 case Nop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001539 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001540 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001541
1542 case LastNodeType:
1543 ASSERT_NOT_REACHED();
1544 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001545 }
1546
1547 return m_isValid;
1548}
1549
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001550inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1551{
1552 if (codeOrigin.inlineCallFrame) {
1553 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1554 for (size_t i = capturedVars.size(); i--;) {
1555 if (!capturedVars.quickGet(i))
1556 continue;
1557 m_variables.local(i).makeTop();
1558 }
1559 } else {
1560 for (size_t i = m_codeBlock->m_numCapturedVars; i--;)
1561 m_variables.local(i).makeTop();
1562 }
1563 if (m_codeBlock->argumentsAreCaptured()) {
1564 for (size_t i = m_variables.numberOfArguments(); i--;)
1565 m_variables.argument(i).makeTop();
1566 }
1567 clobberStructures(indexInBlock);
1568}
1569
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001570inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001571{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001572 if (!m_haveStructures)
1573 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001574 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001575 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001576 for (size_t i = m_variables.numberOfArguments(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001577 m_variables.argument(i).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001578 for (size_t i = m_variables.numberOfLocals(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001579 m_variables.local(i).clobberStructures();
1580 m_haveStructures = false;
1581}
1582
1583inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1584{
1585 if (nodeIndex == NoNode)
1586 return false;
1587
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001588 AbstractValue source;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001589
1590 Node& node = m_graph[nodeIndex];
1591 if (!node.refCount())
1592 return false;
1593
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001594#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001595 dataLog(" It's live, node @%u.\n", nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001596#endif
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001597
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001598 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001599 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001600#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001601 dataLog(" Transfering ");
1602 source.dump(WTF::dataFile());
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001603 dataLog(" from last access due to captured variable.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001604#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001605 } else {
1606 switch (node.op()) {
1607 case Phi:
1608 case SetArgument:
1609 case Flush:
1610 // The block transfers the value from head to tail.
1611 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001612#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001613 dataLog(" Transfering ");
1614 source.dump(WTF::dataFile());
1615 dataLog(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001616#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001617 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001618
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001619 case GetLocal:
1620 // The block refines the value with additional speculations.
1621 source = forNode(nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001622#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001623 dataLog(" Refining to ");
1624 source.dump(WTF::dataFile());
1625 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001626#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001627 break;
1628
1629 case SetLocal:
1630 // The block sets the variable, and potentially refines it, both
1631 // before and after setting it.
1632 if (node.variableAccessData()->shouldUseDoubleFormat()) {
1633 // FIXME: This unnecessarily loses precision.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001634 source.set(SpecDouble);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001635 } else
1636 source = forNode(node.child1());
1637#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1638 dataLog(" Setting to ");
1639 source.dump(WTF::dataFile());
1640 dataLog("\n");
1641#endif
1642 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001643
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001644 default:
1645 ASSERT_NOT_REACHED();
1646 break;
1647 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001648 }
1649
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001650 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001651 // Abstract execution did not change the output value of the variable, for this
1652 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001653#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001654 dataLog(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001655#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001656 return false;
1657 }
1658
1659 // Abstract execution reached a new conclusion about the speculations reached about
1660 // this variable after execution of this basic block. Update the state, and return
1661 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001662 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001663#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001664 dataLog(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001665#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001666 return true;
1667}
1668
1669inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1670{
1671 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1672 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1673
1674 bool changed = false;
1675
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001676 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1677 AbstractValue& destination = to->valuesAtHead.argument(argument);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001678 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1679 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001680
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001681 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1682 AbstractValue& destination = to->valuesAtHead.local(local);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001683 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1684 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001685
1686 if (!to->cfaHasVisited)
1687 changed = true;
1688
1689 to->cfaShouldRevisit |= changed;
1690
1691 return changed;
1692}
1693
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001694inline bool AbstractState::mergeToSuccessors(
1695 Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001696{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001697 Node& terminal = graph[basicBlock->last()];
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001698
1699 ASSERT(terminal.isTerminal());
1700
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001701 switch (terminal.op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001702 case Jump: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001703 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001704#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1705 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1706#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001707 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001708 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001709
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001710 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001711 ASSERT(branchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001712 bool changed = false;
1713#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1714 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1715#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001716 if (branchDirection != TakeFalse)
1717 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001718#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1719 dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1720#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001721 if (branchDirection != TakeTrue)
1722 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001723 return changed;
1724 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001725
1726 case Return:
1727 case Throw:
1728 case ThrowReferenceError:
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001729 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001730 return false;
1731
1732 default:
1733 ASSERT_NOT_REACHED();
1734 return false;
1735 }
1736}
1737
1738inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1739{
1740 if (destinationNodeIndex == NoNode)
1741 return false;
1742
1743 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1744
1745 // FIXME: We could do some sparse conditional propagation here!
1746
1747 return destination.merge(source);
1748}
1749
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001750void AbstractState::dump(FILE* out)
1751{
1752 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001753 for (size_t i = 0; i < m_block->size(); ++i) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001754 NodeIndex index = m_block->at(i);
1755 AbstractValue& value = m_nodes[index];
1756 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001757 continue;
1758 if (first)
1759 first = false;
1760 else
1761 fprintf(out, " ");
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001762 fprintf(out, "@%lu:", static_cast<unsigned long>(index));
1763 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001764 }
1765}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001766
1767} } // namespace JSC::DFG
1768
1769#endif // ENABLE(DFG_JIT)
1770