blob: 01996f1320103ec6e642b8b158e925ceb1cc03f4 [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
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +000055 // This is usually a no-op, but it is possible that the graph has grown since the
56 // abstract state was last used.
57 m_nodes.resize(m_graph.size());
58
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000059 for (size_t i = 0; i < basicBlock->size(); i++)
60 m_nodes[basicBlock->at(i)].clear();
61
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000062 m_variables = basicBlock->valuesAtHead;
63 m_haveStructures = false;
64 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
65 if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
66 m_haveStructures = true;
67 break;
68 }
69 }
70 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
71 if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
72 m_haveStructures = true;
73 break;
74 }
75 }
76
77 basicBlock->cfaShouldRevisit = false;
78 basicBlock->cfaHasVisited = true;
79 m_block = basicBlock;
80 m_isValid = true;
fpizlo@apple.com3187c922012-05-18 21:47:53 +000081 m_foundConstants = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +000082 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000083}
84
85void AbstractState::initialize(Graph& graph)
86{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000087 BasicBlock* root = graph.m_blocks[0].get();
88 root->cfaShouldRevisit = true;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000089 root->cfaHasVisited = false;
90 root->cfaFoundConstants = false;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000091 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
fpizlo@apple.com4f5361262012-02-16 10:06:28 +000092 Node& node = graph[root->variablesAtHead.argument(i)];
fpizlo@apple.comd7897b12012-03-12 23:15:45 +000093 ASSERT(node.op() == SetArgument);
fpizlo@apple.com4f5361262012-02-16 10:06:28 +000094 if (!node.shouldGenerate()) {
95 // The argument is dead. We don't do any checks for such arguments, and so
96 // for the purpose of the analysis, they contain no value.
97 root->valuesAtHead.argument(i).clear();
98 continue;
99 }
100
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000101 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000102 root->valuesAtHead.argument(i).makeTop();
103 continue;
104 }
105
fpizlo@apple.com62336162012-06-07 01:35:59 +0000106 SpeculatedType prediction = node.variableAccessData()->prediction();
107 if (isInt32Speculation(prediction))
108 root->valuesAtHead.argument(i).set(SpecInt32);
109 else if (isArraySpeculation(prediction))
110 root->valuesAtHead.argument(i).set(SpecArray);
111 else if (isBooleanSpeculation(prediction))
112 root->valuesAtHead.argument(i).set(SpecBoolean);
113 else if (isInt8ArraySpeculation(prediction))
114 root->valuesAtHead.argument(i).set(SpecInt8Array);
115 else if (isInt16ArraySpeculation(prediction))
116 root->valuesAtHead.argument(i).set(SpecInt16Array);
117 else if (isInt32ArraySpeculation(prediction))
118 root->valuesAtHead.argument(i).set(SpecInt32Array);
119 else if (isUint8ArraySpeculation(prediction))
120 root->valuesAtHead.argument(i).set(SpecUint8Array);
121 else if (isUint8ClampedArraySpeculation(prediction))
122 root->valuesAtHead.argument(i).set(SpecUint8ClampedArray);
123 else if (isUint16ArraySpeculation(prediction))
124 root->valuesAtHead.argument(i).set(SpecUint16Array);
125 else if (isUint32ArraySpeculation(prediction))
126 root->valuesAtHead.argument(i).set(SpecUint32Array);
127 else if (isFloat32ArraySpeculation(prediction))
128 root->valuesAtHead.argument(i).set(SpecFloat32Array);
129 else if (isFloat64ArraySpeculation(prediction))
130 root->valuesAtHead.argument(i).set(SpecFloat64Array);
fpizlo@apple.com00528432012-07-20 03:50:02 +0000131 else if (isCellSpeculation(prediction))
132 root->valuesAtHead.argument(i).set(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000133 else
134 root->valuesAtHead.argument(i).makeTop();
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000135
136 root->valuesAtTail.argument(i).clear();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000137 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000138 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000139 NodeIndex nodeIndex = root->variablesAtHead.local(i);
140 if (nodeIndex != NoNode && graph[nodeIndex].variableAccessData()->isCaptured())
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000141 root->valuesAtHead.local(i).makeTop();
142 else
143 root->valuesAtHead.local(i).clear();
144 root->valuesAtTail.local(i).clear();
145 }
146 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
147 BasicBlock* block = graph.m_blocks[blockIndex].get();
148 if (!block)
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000149 continue;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000150 if (!block->isReachable)
151 continue;
152 block->cfaShouldRevisit = false;
153 block->cfaHasVisited = false;
154 block->cfaFoundConstants = false;
155 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
156 block->valuesAtHead.argument(i).clear();
157 block->valuesAtTail.argument(i).clear();
158 }
159 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
160 block->valuesAtHead.local(i).clear();
161 block->valuesAtTail.local(i).clear();
162 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000163 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000164}
165
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000166bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000167{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000168 ASSERT(m_block);
169
170 BasicBlock* block = m_block; // Save the block for successor merging.
171
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000172 block->cfaFoundConstants = m_foundConstants;
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000173 block->cfaDidFinish = m_isValid;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000174
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000175 if (!m_isValid) {
176 reset();
177 return false;
178 }
179
180 bool changed = false;
181
182 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000183 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
184#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000185 dataLog(" Merging state for argument %zu.\n", argument);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000186#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000187 AbstractValue& destination = block->valuesAtTail.argument(argument);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000188 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000189 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000190
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000191 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
192#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000193 dataLog(" Merging state for local %zu.\n", local);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000194#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000195 AbstractValue& destination = block->valuesAtTail.local(local);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000196 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000197 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000198 }
199
200 ASSERT(mergeMode != DontMerge || !changed);
201
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000202 BranchDirection branchDirection = m_branchDirection;
203 if (branchDirectionPtr)
204 *branchDirectionPtr = branchDirection;
205
206#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
207 dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection));
208#endif
209
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000210 reset();
211
212 if (mergeMode != MergeToSuccessors)
213 return changed;
214
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000215 return mergeToSuccessors(m_graph, block, branchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000216}
217
218void AbstractState::reset()
219{
220 m_block = 0;
221 m_isValid = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000222 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000223}
224
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000225bool AbstractState::execute(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000226{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000227 ASSERT(m_block);
228 ASSERT(m_isValid);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000229
230 m_didClobber = false;
231
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000232 NodeIndex nodeIndex = m_block->at(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000233 Node& node = m_graph[nodeIndex];
234
235 if (!node.shouldGenerate())
236 return true;
237
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000238 switch (node.op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000239 case JSConstant:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +0000240 case WeakJSConstant:
241 case PhantomArguments: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000242 forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000243 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000244 break;
245 }
246
247 case GetLocal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000248 VariableAccessData* variableAccessData = node.variableAccessData();
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000249 if (variableAccessData->prediction() == SpecNone) {
250 m_isValid = false;
251 node.setCanExit(true);
252 break;
253 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000254 bool canExit = false;
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000255 AbstractValue value = m_variables.operand(variableAccessData->local());
256 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000257 if (value.isClear())
258 canExit |= true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000259 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000260 if (value.value())
261 m_foundConstants = true;
262 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000263 node.setCanExit(canExit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000264 break;
265 }
266
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000267 case GetLocalUnlinked: {
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000268 AbstractValue value = m_variables.operand(node.unlinkedLocal());
269 if (value.value())
270 m_foundConstants = true;
271 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000272 node.setCanExit(false);
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000273 break;
274 }
275
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000276 case SetLocal: {
fpizlo@apple.com00528432012-07-20 03:50:02 +0000277 if (node.variableAccessData()->isCaptured()
278 || m_graph.isCreatedThisArgument(node.local())) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000279 m_variables.operand(node.local()) = forNode(node.child1());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000280 node.setCanExit(false);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000281 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000282 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000283
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000284 if (node.variableAccessData()->shouldUseDoubleFormat()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000285 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000286 m_variables.operand(node.local()).set(SpecDouble);
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000287 break;
288 }
289
fpizlo@apple.com62336162012-06-07 01:35:59 +0000290 SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
291 if (isInt32Speculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000292 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000293 else if (isArraySpeculation(predictedType)) {
294 node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
295 forNode(node.child1()).filter(SpecArray);
fpizlo@apple.com00528432012-07-20 03:50:02 +0000296 } else if (isCellSpeculation(predictedType)) {
297 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
298 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000299 } else if (isBooleanSpeculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000300 speculateBooleanUnary(node);
301 else
302 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000303
304 m_variables.operand(node.local()) = forNode(node.child1());
305 break;
306 }
307
308 case SetArgument:
309 // Assert that the state of arguments has been set.
310 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000311 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000312 break;
313
314 case BitAnd:
315 case BitOr:
316 case BitXor:
317 case BitRShift:
318 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000319 case BitURShift: {
320 JSValue left = forNode(node.child1()).value();
321 JSValue right = forNode(node.child2()).value();
322 if (left && right && left.isInt32() && right.isInt32()) {
323 int32_t a = left.asInt32();
324 int32_t b = right.asInt32();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000325 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000326 switch (node.op()) {
327 case BitAnd:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000328 constantWasSet = trySetConstant(nodeIndex, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000329 break;
330 case BitOr:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000331 constantWasSet = trySetConstant(nodeIndex, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000332 break;
333 case BitXor:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000334 constantWasSet = trySetConstant(nodeIndex, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000335 break;
336 case BitRShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000337 constantWasSet = trySetConstant(nodeIndex, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000338 break;
339 case BitLShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000340 constantWasSet = trySetConstant(nodeIndex, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000341 break;
342 case BitURShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000343 constantWasSet = trySetConstant(nodeIndex, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000344 break;
345 default:
346 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000347 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000348 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000349 if (constantWasSet) {
350 m_foundConstants = true;
351 node.setCanExit(false);
352 break;
353 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000354 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000355 speculateInt32Binary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000356 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000357 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000358 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000359
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000360 case UInt32ToNumber: {
361 JSValue child = forNode(node.child1()).value();
362 if (child && child.isNumber()) {
363 ASSERT(child.isInt32());
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000364 if (trySetConstant(nodeIndex, JSValue(child.asUInt32()))) {
365 m_foundConstants = true;
366 node.setCanExit(false);
367 break;
368 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000369 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000370 if (!node.canSpeculateInteger()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000371 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000372 node.setCanExit(false);
373 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000374 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000375 node.setCanExit(true);
376 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000377 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000378 }
379
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000380
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000381 case DoubleAsInt32: {
382 JSValue child = forNode(node.child1()).value();
383 if (child && child.isNumber()) {
384 double asDouble = child.asNumber();
385 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000386 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
387 && trySetConstant(nodeIndex, JSValue(asInt))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000388 m_foundConstants = true;
389 break;
390 }
391 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000392 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000393 forNode(node.child1()).filter(SpecNumber);
394 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000395 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000396 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000397
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000398 case ValueToInt32: {
399 JSValue child = forNode(node.child1()).value();
400 if (child && child.isNumber()) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000401 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000402 if (child.isInt32())
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000403 constantWasSet = trySetConstant(nodeIndex, child);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000404 else
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000405 constantWasSet = trySetConstant(nodeIndex, JSValue(JSC::toInt32(child.asDouble())));
406 if (constantWasSet) {
407 m_foundConstants = true;
408 node.setCanExit(false);
409 break;
410 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000411 }
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000412 if (m_graph[node.child1()].shouldSpeculateInteger())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000413 speculateInt32Unary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000414 else if (m_graph[node.child1()].shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000415 speculateNumberUnary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000416 else if (m_graph[node.child1()].shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000417 speculateBooleanUnary(node);
418 else
419 node.setCanExit(false);
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000420
fpizlo@apple.com62336162012-06-07 01:35:59 +0000421 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000422 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000423 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000424
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000425 case Int32ToDouble: {
426 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000427 if (child && child.isNumber()
428 && trySetConstant(nodeIndex, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000429 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000430 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000431 break;
432 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000433 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000434 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000435 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000436 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000437
438 case CheckNumber:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000439 forNode(node.child1()).filter(SpecNumber);
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000440 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000441
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000442 case ValueAdd:
443 case ArithAdd: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000444 JSValue left = forNode(node.child1()).value();
445 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000446 if (left && right && left.isNumber() && right.isNumber()
447 && trySetConstant(nodeIndex, JSValue(left.asNumber() + right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000448 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000449 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000450 break;
451 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000452 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000453 speculateInt32Binary(
454 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000455 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000456 break;
457 }
458 if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000459 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000460 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000461 break;
462 }
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000463 if (node.op() == ValueAdd) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000464 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000465 forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000466 node.setCanExit(false);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000467 break;
468 }
469 // We don't handle this yet. :-(
470 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000471 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000472 break;
473 }
474
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000475 case ArithSub: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000476 JSValue left = forNode(node.child1()).value();
477 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000478 if (left && right && left.isNumber() && right.isNumber()
479 && trySetConstant(nodeIndex, JSValue(left.asNumber() - right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000480 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000481 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000482 break;
483 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000484 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000485 speculateInt32Binary(
486 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000487 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000488 break;
489 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000490 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000491 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000492 break;
493 }
494
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000495 case ArithNegate: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000496 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000497 if (child && child.isNumber()
498 && trySetConstant(nodeIndex, JSValue(-child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000499 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000500 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000501 break;
502 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000503 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000504 speculateInt32Unary(
505 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000506 forNode(nodeIndex).set(SpecInt32);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000507 break;
508 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000509 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000510 forNode(nodeIndex).set(SpecDouble);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000511 break;
512 }
513
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000514 case ArithMul: {
515 JSValue left = forNode(node.child1()).value();
516 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000517 if (left && right && left.isNumber() && right.isNumber()
518 && trySetConstant(nodeIndex, JSValue(left.asNumber() * right.asNumber()))) {
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000519 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000520 node.setCanExit(false);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000521 break;
522 }
523 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000524 speculateInt32Binary(
525 node,
526 !nodeCanTruncateInteger(node.arithNodeFlags())
527 || !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000528 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000529 break;
530 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000531 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000532 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000533 break;
534 }
535
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000536 case ArithDiv:
537 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000538 case ArithMax:
539 case ArithMod: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000540 JSValue left = forNode(node.child1()).value();
541 JSValue right = forNode(node.child2()).value();
542 if (left && right && left.isNumber() && right.isNumber()) {
543 double a = left.asNumber();
544 double b = right.asNumber();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000545 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000546 switch (node.op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000547 case ArithDiv:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000548 constantWasSet = trySetConstant(nodeIndex, JSValue(a / b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000549 break;
550 case ArithMin:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000551 constantWasSet = trySetConstant(nodeIndex, JSValue(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000552 break;
553 case ArithMax:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000554 constantWasSet = trySetConstant(nodeIndex, JSValue(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000555 break;
556 case ArithMod:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000557 constantWasSet = trySetConstant(nodeIndex, JSValue(fmod(a, b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000558 break;
559 default:
560 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000561 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000562 break;
563 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000564 if (constantWasSet) {
565 m_foundConstants = true;
566 node.setCanExit(false);
567 break;
568 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000569 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000570 if (Node::shouldSpeculateInteger(
571 m_graph[node.child1()], m_graph[node.child2()])
572 && node.canSpeculateInteger()) {
573 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
fpizlo@apple.com62336162012-06-07 01:35:59 +0000574 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000575 break;
576 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000577 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000578 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000579 break;
580 }
581
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000582 case ArithAbs: {
583 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000584 if (child && child.isNumber()
585 && trySetConstant(nodeIndex, JSValue(fabs(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000586 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000587 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000588 break;
589 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000590 if (m_graph[node.child1()].shouldSpeculateInteger()
591 && node.canSpeculateInteger()) {
592 speculateInt32Unary(node, true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000593 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000594 break;
595 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000596 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000597 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000598 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000599 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000600
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000601 case ArithSqrt: {
602 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000603 if (child && child.isNumber()
604 && trySetConstant(nodeIndex, JSValue(sqrt(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000605 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000606 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000607 break;
608 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000609 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000610 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000611 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000612 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000613
614 case LogicalNot: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000615 JSValue childConst = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000616 if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean()))) {
fpizlo@apple.com152abff2012-06-19 23:10:12 +0000617 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000618 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000619 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000620 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000621 Node& child = m_graph[node.child1()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000622 if (isBooleanSpeculation(child.prediction()))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000623 speculateBooleanUnary(node);
624 else if (child.shouldSpeculateFinalObjectOrOther()) {
625 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000626 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
627 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000628 } else if (child.shouldSpeculateArrayOrOther()) {
629 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000630 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
631 forNode(node.child1()).filter(SpecArray | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000632 } else if (child.shouldSpeculateInteger())
633 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000634 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000635 speculateNumberUnary(node);
636 else
637 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000638 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000639 break;
640 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000641
642 case IsUndefined:
643 case IsBoolean:
644 case IsNumber:
645 case IsString:
646 case IsObject:
647 case IsFunction: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000648 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000649 JSValue child = forNode(node.child1()).value();
650 if (child) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000651 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000652 switch (node.op()) {
653 case IsUndefined:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000654 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000655 child.isCell()
656 ? child.asCell()->structure()->typeInfo().masqueradesAsUndefined()
657 : child.isUndefined()));
658 break;
659 case IsBoolean:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000660 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000661 break;
662 case IsNumber:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000663 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000664 break;
665 case IsString:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000666 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000667 break;
668 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000669 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000670 break;
671 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000672 if (constantWasSet) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000673 m_foundConstants = true;
674 break;
675 }
676 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000677 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000678 break;
679 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000680
681 case CompareLess:
682 case CompareLessEq:
683 case CompareGreater:
684 case CompareGreaterEq:
685 case CompareEq: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000686 JSValue leftConst = forNode(node.child1()).value();
687 JSValue rightConst = forNode(node.child2()).value();
688 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
689 double a = leftConst.asNumber();
690 double b = rightConst.asNumber();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000691 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000692 switch (node.op()) {
693 case CompareLess:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000694 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000695 break;
696 case CompareLessEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000697 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a <= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000698 break;
699 case CompareGreater:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000700 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a > b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000701 break;
702 case CompareGreaterEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000703 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a >= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000704 break;
705 case CompareEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000706 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a == b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000707 break;
708 default:
709 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000710 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000711 break;
712 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000713 if (constantWasSet) {
714 m_foundConstants = true;
715 node.setCanExit(false);
716 break;
717 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000718 }
719
fpizlo@apple.com62336162012-06-07 01:35:59 +0000720 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000721
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000722 Node& left = m_graph[node.child1()];
723 Node& right = m_graph[node.child2()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000724 SpeculatedType filter;
725 SpeculatedTypeChecker checker;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000726 if (Node::shouldSpeculateInteger(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000727 filter = SpecInt32;
728 checker = isInt32Speculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000729 } else if (Node::shouldSpeculateNumber(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000730 filter = SpecNumber;
731 checker = isNumberSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000732 } else if (node.op() == CompareEq) {
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000733 if ((m_graph.isConstant(node.child1().index())
734 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
735 || (m_graph.isConstant(node.child2().index())
736 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
737 // We know that this won't clobber the world. But that's all we know.
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000738 node.setCanExit(false);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000739 break;
740 }
741
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000742 if (Node::shouldSpeculateFinalObject(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000743 filter = SpecFinalObject;
744 checker = isFinalObjectSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000745 } else if (Node::shouldSpeculateArray(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000746 filter = SpecArray;
747 checker = isArraySpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000748 } else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
749 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000750 !isFinalObjectSpeculation(forNode(node.child1()).m_type)
751 || !isFinalObjectOrOtherSpeculation(forNode(node.child2()).m_type));
752 forNode(node.child1()).filter(SpecFinalObject);
753 forNode(node.child2()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000754 break;
755 } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000756 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000757 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type)
758 || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
759 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
760 forNode(node.child2()).filter(SpecFinalObject);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000761 break;
762 } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000763 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000764 !isArraySpeculation(forNode(node.child1()).m_type)
765 || !isArrayOrOtherSpeculation(forNode(node.child2()).m_type));
766 forNode(node.child1()).filter(SpecArray);
767 forNode(node.child2()).filter(SpecArray | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000768 break;
769 } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000770 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000771 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type)
772 || !isArraySpeculation(forNode(node.child2()).m_type));
773 forNode(node.child1()).filter(SpecArray | SpecOther);
774 forNode(node.child2()).filter(SpecArray);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000775 break;
776 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000777 filter = SpecTop;
778 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000779 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000780 }
781 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000782 filter = SpecTop;
783 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000784 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000785 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000786 node.setCanExit(
787 !checker(forNode(node.child1()).m_type)
788 || !checker(forNode(node.child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000789 forNode(node.child1()).filter(filter);
790 forNode(node.child2()).filter(filter);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000791 break;
792 }
793
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000794 case CompareStrictEq: {
795 JSValue left = forNode(node.child1()).value();
796 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000797 if (left && right && left.isNumber() && right.isNumber()
798 && trySetConstant(nodeIndex, jsBoolean(left.asNumber() == right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000799 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000800 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000801 break;
802 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000803 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000804 if (m_graph.isJSConstant(node.child1().index())) {
805 JSValue value = m_graph.valueOfJSConstant(node.child1().index());
806 if (!value.isNumber() && !value.isString()) {
807 node.setCanExit(false);
808 break;
809 }
810 }
811 if (m_graph.isJSConstant(node.child2().index())) {
812 JSValue value = m_graph.valueOfJSConstant(node.child2().index());
813 if (!value.isNumber() && !value.isString()) {
814 node.setCanExit(false);
815 break;
816 }
817 }
818 if (Node::shouldSpeculateInteger(
819 m_graph[node.child1()], m_graph[node.child2()])) {
820 speculateInt32Binary(node);
821 break;
822 }
823 if (Node::shouldSpeculateNumber(
824 m_graph[node.child1()], m_graph[node.child2()])) {
825 speculateNumberBinary(node);
826 break;
827 }
828 if (Node::shouldSpeculateFinalObject(
829 m_graph[node.child1()], m_graph[node.child2()])) {
830 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000831 !isFinalObjectSpeculation(forNode(node.child1()).m_type)
832 || !isFinalObjectSpeculation(forNode(node.child2()).m_type));
833 forNode(node.child1()).filter(SpecFinalObject);
834 forNode(node.child2()).filter(SpecFinalObject);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000835 break;
836 }
837 if (Node::shouldSpeculateArray(
838 m_graph[node.child1()], m_graph[node.child2()])) {
839 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +0000840 !isArraySpeculation(forNode(node.child1()).m_type)
841 || !isArraySpeculation(forNode(node.child2()).m_type));
842 forNode(node.child1()).filter(SpecArray);
843 forNode(node.child2()).filter(SpecArray);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000844 break;
845 }
846 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000847 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000848 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000849
850 case StringCharCodeAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000851 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000852 forNode(node.child1()).filter(SpecString);
853 forNode(node.child2()).filter(SpecInt32);
854 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000855 break;
856
857 case StringCharAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000858 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000859 forNode(node.child1()).filter(SpecString);
860 forNode(node.child2()).filter(SpecInt32);
861 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000862 break;
863
864 case GetByVal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000865 node.setCanExit(true);
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000866 if (!node.prediction() || !m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
867 m_isValid = false;
868 break;
869 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000870 if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000871 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000872 forNode(nodeIndex).makeTop();
873 break;
874 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000875 if (m_graph[node.child1()].shouldSpeculateArguments()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000876 forNode(node.child1()).filter(SpecArguments);
877 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000878 forNode(nodeIndex).makeTop();
879 break;
880 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000881 if (m_graph[node.child1()].prediction() == SpecString) {
882 forNode(node.child1()).filter(SpecString);
883 forNode(node.child2()).filter(SpecInt32);
884 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000885 break;
886 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000887
888 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000889 forNode(node.child1()).filter(SpecInt8Array);
890 forNode(node.child2()).filter(SpecInt32);
891 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000892 break;
893 }
894 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000895 forNode(node.child1()).filter(SpecInt16Array);
896 forNode(node.child2()).filter(SpecInt32);
897 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000898 break;
899 }
900 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000901 forNode(node.child1()).filter(SpecInt32Array);
902 forNode(node.child2()).filter(SpecInt32);
903 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000904 break;
905 }
906 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000907 forNode(node.child1()).filter(SpecUint8Array);
908 forNode(node.child2()).filter(SpecInt32);
909 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000910 break;
911 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000912 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000913 forNode(node.child1()).filter(SpecUint8ClampedArray);
914 forNode(node.child2()).filter(SpecInt32);
915 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000916 break;
917 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000918 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000919 forNode(node.child1()).filter(SpecUint16Array);
920 forNode(node.child2()).filter(SpecInt32);
921 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000922 break;
923 }
924 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000925 forNode(node.child1()).filter(SpecUint32Array);
926 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000927 if (node.shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000928 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000929 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000930 forNode(nodeIndex).set(SpecDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000931 break;
932 }
oliver@apple.com07d75732011-12-03 01:47:27 +0000933 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000934 forNode(node.child1()).filter(SpecFloat32Array);
935 forNode(node.child2()).filter(SpecInt32);
936 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000937 break;
938 }
939 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000940 forNode(node.child1()).filter(SpecFloat64Array);
941 forNode(node.child2()).filter(SpecInt32);
942 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000943 break;
944 }
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000945 ASSERT(m_graph[node.child1()].shouldSpeculateArray());
fpizlo@apple.com62336162012-06-07 01:35:59 +0000946 forNode(node.child1()).filter(SpecArray);
947 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000948 forNode(nodeIndex).makeTop();
949 break;
950 }
951
952 case PutByVal:
953 case PutByValAlias: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000954 node.setCanExit(true);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000955
956 Edge child1 = m_graph.varArgChild(node, 0);
957 Edge child2 = m_graph.varArgChild(node, 1);
958 Edge child3 = m_graph.varArgChild(node, 2);
959
960 if (!m_graph[child1].prediction() || !m_graph[child2].prediction()) {
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000961 m_isValid = false;
962 break;
963 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000964 if (!m_graph[child2].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[child1].prediction())
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000965#if USE(JSVALUE32_64)
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000966 || m_graph[child1].shouldSpeculateArguments()
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000967#endif
968 ) {
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000969 ASSERT(node.op() == PutByVal);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000970 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000971 forNode(nodeIndex).makeTop();
972 break;
973 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000974
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000975 if (m_graph[child1].shouldSpeculateArguments()) {
976 forNode(child1).filter(SpecArguments);
977 forNode(child2).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000978 break;
979 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000980 if (m_graph[child1].shouldSpeculateInt8Array()) {
981 forNode(child1).filter(SpecInt8Array);
982 forNode(child2).filter(SpecInt32);
983 if (m_graph[child3].shouldSpeculateInteger())
984 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000985 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000986 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000987 break;
988 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000989 if (m_graph[child1].shouldSpeculateInt16Array()) {
990 forNode(child1).filter(SpecInt16Array);
991 forNode(child2).filter(SpecInt32);
992 if (m_graph[child3].shouldSpeculateInteger())
993 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000994 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000995 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000996 break;
997 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000998 if (m_graph[child1].shouldSpeculateInt32Array()) {
999 forNode(child1).filter(SpecInt32Array);
1000 forNode(child2).filter(SpecInt32);
1001 if (m_graph[child3].shouldSpeculateInteger())
1002 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001003 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001004 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001005 break;
1006 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001007 if (m_graph[child1].shouldSpeculateUint8Array()) {
1008 forNode(child1).filter(SpecUint8Array);
1009 forNode(child2).filter(SpecInt32);
1010 if (m_graph[child3].shouldSpeculateInteger())
1011 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001012 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001013 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001014 break;
1015 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001016 if (m_graph[child1].shouldSpeculateUint8ClampedArray()) {
1017 forNode(child1).filter(SpecUint8ClampedArray);
1018 forNode(child2).filter(SpecInt32);
1019 if (m_graph[child3].shouldSpeculateInteger())
1020 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001021 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001022 forNode(child3).filter(SpecNumber);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001023 break;
1024 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001025 if (m_graph[child1].shouldSpeculateUint16Array()) {
1026 forNode(child1).filter(SpecUint16Array);
1027 forNode(child2).filter(SpecInt32);
1028 if (m_graph[child3].shouldSpeculateInteger())
1029 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001030 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001031 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001032 break;
1033 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001034 if (m_graph[child1].shouldSpeculateUint32Array()) {
1035 forNode(child1).filter(SpecUint32Array);
1036 forNode(child2).filter(SpecInt32);
1037 if (m_graph[child3].shouldSpeculateInteger())
1038 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001039 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001040 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001041 break;
1042 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001043 if (m_graph[child1].shouldSpeculateFloat32Array()) {
1044 forNode(child1).filter(SpecFloat32Array);
1045 forNode(child2).filter(SpecInt32);
1046 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001047 break;
1048 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001049 if (m_graph[child1].shouldSpeculateFloat64Array()) {
1050 forNode(child1).filter(SpecFloat64Array);
1051 forNode(child2).filter(SpecInt32);
1052 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001053 break;
1054 }
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001055 ASSERT(m_graph[child1].shouldSpeculateArray());
1056 forNode(child1).filter(SpecArray);
1057 forNode(child2).filter(SpecInt32);
fpizlo@apple.coma4754892012-06-02 00:22:31 +00001058 if (node.op() == PutByVal)
1059 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001060 break;
1061 }
1062
1063 case ArrayPush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001064 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001065 forNode(node.child1()).filter(SpecArray);
1066 forNode(nodeIndex).set(SpecNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001067 break;
1068
1069 case ArrayPop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001070 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001071 forNode(node.child1()).filter(SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001072 forNode(nodeIndex).makeTop();
1073 break;
1074
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001075 case RegExpExec:
1076 case RegExpTest:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001077 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001078 !isCellSpeculation(forNode(node.child1()).m_type)
1079 || !isCellSpeculation(forNode(node.child2()).m_type));
1080 forNode(node.child1()).filter(SpecCell);
1081 forNode(node.child2()).filter(SpecCell);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001082 forNode(nodeIndex).makeTop();
1083 break;
1084
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001085 case Jump:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001086 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001087 break;
1088
1089 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001090 JSValue value = forNode(node.child1()).value();
1091 if (value) {
1092 bool booleanValue = value.toBoolean();
1093 if (booleanValue)
1094 m_branchDirection = TakeTrue;
1095 else
1096 m_branchDirection = TakeFalse;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001097 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001098 break;
1099 }
1100 // FIXME: The above handles the trivial cases of sparse conditional
1101 // constant propagation, but we can do better:
1102 // 1) If the abstract value does not have a concrete value but describes
1103 // something that is known to evaluate true (or false) then we ought
1104 // to sparse conditional that.
1105 // 2) We can specialize the source variable's value on each direction of
1106 // the branch.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001107 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +00001108 if (child.shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001109 speculateBooleanUnary(node);
1110 else if (child.shouldSpeculateFinalObjectOrOther()) {
1111 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001112 !isFinalObjectOrOtherSpeculation(forNode(node.child1()).m_type));
1113 forNode(node.child1()).filter(SpecFinalObject | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001114 } else if (child.shouldSpeculateArrayOrOther()) {
1115 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001116 !isArrayOrOtherSpeculation(forNode(node.child1()).m_type));
1117 forNode(node.child1()).filter(SpecArray | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001118 } else if (child.shouldSpeculateInteger())
1119 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001120 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001121 speculateNumberUnary(node);
1122 else
1123 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001124 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001125 break;
1126 }
1127
1128 case Return:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001129 m_isValid = false;
1130 node.setCanExit(false);
1131 break;
1132
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001133 case Throw:
1134 case ThrowReferenceError:
1135 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001136 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001137 break;
1138
1139 case ToPrimitive: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001140 JSValue childConst = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +00001141 if (childConst && childConst.isNumber() && trySetConstant(nodeIndex, childConst)) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001142 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001143 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001144 break;
1145 }
1146
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001147 Node& child = m_graph[node.child1()];
1148 if (child.shouldSpeculateInteger()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001149 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001150 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001151 break;
1152 }
1153
1154 AbstractValue& source = forNode(node.child1());
1155 AbstractValue& destination = forNode(nodeIndex);
1156
fpizlo@apple.com62336162012-06-07 01:35:59 +00001157 SpeculatedType type = source.m_type;
1158 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1159 type &= (SpecNumber | SpecString | SpecBoolean);
1160 type |= SpecString;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001161 }
1162 destination.set(type);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001163 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001164 break;
1165 }
1166
1167 case StrCat:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001168 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001169 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001170 break;
1171
1172 case NewArray:
1173 case NewArrayBuffer:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001174 node.setCanExit(false);
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001175 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
1176 m_haveStructures = true;
1177 break;
1178
1179 case NewArrayWithSize:
1180 speculateInt32Unary(node);
1181 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001182 m_haveStructures = true;
1183 break;
1184
1185 case NewRegexp:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001186 node.setCanExit(false);
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001187 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001188 m_haveStructures = true;
1189 break;
1190
1191 case ConvertThis: {
1192 Node& child = m_graph[node.child1()];
1193 AbstractValue& source = forNode(node.child1());
1194 AbstractValue& destination = forNode(nodeIndex);
1195
fpizlo@apple.com62336162012-06-07 01:35:59 +00001196 if (isObjectSpeculation(source.m_type)) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001197 // This is the simple case. We already know that the source is an
1198 // object, so there's nothing to do. I don't think this case will
1199 // be hit, but then again, you never know.
1200 destination = source;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001201 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001202 break;
1203 }
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001204
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001205 node.setCanExit(true);
1206
fpizlo@apple.com62336162012-06-07 01:35:59 +00001207 if (isOtherSpeculation(child.prediction())) {
1208 source.filter(SpecOther);
1209 destination.set(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001210 break;
1211 }
1212
fpizlo@apple.com62336162012-06-07 01:35:59 +00001213 if (isObjectSpeculation(child.prediction())) {
1214 source.filter(SpecObjectMask);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001215 destination = source;
1216 break;
1217 }
1218
1219 destination = source;
fpizlo@apple.com62336162012-06-07 01:35:59 +00001220 destination.merge(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001221 break;
1222 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001223
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001224 case CreateThis: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001225 AbstractValue& source = forNode(node.child1());
1226 AbstractValue& destination = forNode(nodeIndex);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001227
fpizlo@apple.com62336162012-06-07 01:35:59 +00001228 node.setCanExit(!isCellSpeculation(source.m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001229
fpizlo@apple.com62336162012-06-07 01:35:59 +00001230 source.filter(SpecFunction);
1231 destination.set(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001232 break;
1233 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001234
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001235 case NewObject:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001236 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001237 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001238 m_haveStructures = true;
1239 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001240
1241 case CreateActivation:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001242 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001243 forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get());
1244 m_haveStructures = true;
1245 break;
1246
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001247 case CreateArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001248 node.setCanExit(false);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001249 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1250 m_haveStructures = true;
1251 break;
1252
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001253 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001254 case TearOffArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001255 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001256 // Does nothing that is user-visible.
1257 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001258
1259 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001260 if (isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001261 m_variables.operand(
fpizlo@apple.comb80bc2a32012-06-02 22:58:48 +00001262 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
1263 node.setCanExit(false);
1264 m_foundConstants = true;
1265 } else
1266 node.setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001267 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001268
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001269 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001270 // We know that this executable does not escape its arguments, so we can optimize
1271 // the arguments a bit. Note that this is not sufficient to force constant folding
1272 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1273 // We perform further optimizations on this later on.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001274 if (node.codeOrigin.inlineCallFrame)
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001275 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001276 else
fpizlo@apple.com62336162012-06-07 01:35:59 +00001277 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001278 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001279 !isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001280 m_variables.operand(
1281 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001282 break;
1283
1284 case GetMyArgumentsLengthSafe:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001285 node.setCanExit(false);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001286 // This potentially clobbers all structures if the arguments object had a getter
1287 // installed on the length property.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001288 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001289 // We currently make no guarantee about what this returns because it does not
1290 // speculate that the length property is actually a length.
1291 forNode(nodeIndex).makeTop();
1292 break;
1293
1294 case GetMyArgumentByVal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001295 node.setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001296 // We know that this executable does not escape its arguments, so we can optimize
1297 // the arguments a bit. Note that this ends up being further optimized by the
1298 // ArgumentsSimplificationPhase.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001299 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001300 forNode(nodeIndex).makeTop();
1301 break;
1302
1303 case GetMyArgumentByValSafe:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001304 node.setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001305 // This potentially clobbers all structures if the property we're accessing has
1306 // a getter. We don't speculate against this.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001307 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001308 // But we do speculate that the index is an integer.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001309 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001310 // And the result is unknown.
1311 forNode(nodeIndex).makeTop();
1312 break;
1313
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001314 case NewFunction:
1315 case NewFunctionExpression:
1316 case NewFunctionNoCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001317 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001318 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1319 break;
1320
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001321 case GetCallee:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001322 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001323 forNode(nodeIndex).set(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001324 break;
1325
1326 case GetScopeChain:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001327 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001328 forNode(nodeIndex).set(SpecCellOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001329 break;
1330
1331 case GetScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001332 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001333 forNode(nodeIndex).makeTop();
1334 break;
1335
1336 case PutScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001337 node.setCanExit(false);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001338 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001339 break;
1340
1341 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001342 case GetByIdFlush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001343 node.setCanExit(true);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001344 if (!node.prediction()) {
1345 m_isValid = false;
1346 break;
1347 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001348 if (isCellSpeculation(m_graph[node.child1()].prediction()))
1349 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001350 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001351 forNode(nodeIndex).makeTop();
1352 break;
1353
1354 case GetArrayLength:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001355 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001356 forNode(node.child1()).filter(SpecArray);
1357 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001358 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001359
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001360 case GetArgumentsLength:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001361 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001362 forNode(node.child1()).filter(SpecArguments);
1363 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001364 break;
1365
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001366 case GetStringLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001367 node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
1368 forNode(node.child1()).filter(SpecString);
1369 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001370 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001371
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001372 case GetInt8ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001373 node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
1374 forNode(node.child1()).filter(SpecInt8Array);
1375 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001376 break;
1377 case GetInt16ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001378 node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
1379 forNode(node.child1()).filter(SpecInt16Array);
1380 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001381 break;
1382 case GetInt32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001383 node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
1384 forNode(node.child1()).filter(SpecInt32Array);
1385 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001386 break;
1387 case GetUint8ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001388 node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
1389 forNode(node.child1()).filter(SpecUint8Array);
1390 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001391 break;
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001392 case GetUint8ClampedArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001393 node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
1394 forNode(node.child1()).filter(SpecUint8ClampedArray);
1395 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001396 break;
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001397 case GetUint16ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001398 node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
1399 forNode(node.child1()).filter(SpecUint16Array);
1400 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001401 break;
1402 case GetUint32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001403 node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
1404 forNode(node.child1()).filter(SpecUint32Array);
1405 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001406 break;
1407 case GetFloat32ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001408 node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
1409 forNode(node.child1()).filter(SpecFloat32Array);
1410 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001411 break;
1412 case GetFloat64ArrayLength:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001413 node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
1414 forNode(node.child1()).filter(SpecFloat64Array);
1415 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001416 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001417
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001418 case CheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001419 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001420 AbstractValue& value = forNode(node.child1());
1421 node.setCanExit(
1422 !value.m_structure.isSubsetOf(node.structureSet())
fpizlo@apple.com62336162012-06-07 01:35:59 +00001423 || !isCellSpeculation(value.m_type));
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001424 value.filter(node.structureSet());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001425 m_haveStructures = true;
1426 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001427 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001428
1429 case StructureTransitionWatchpoint: {
1430 // FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
1431 AbstractValue& value = forNode(node.child1());
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00001432 ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001433 value.filter(node.structure());
1434 node.setCanExit(true);
1435 break;
1436 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001437
1438 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001439 case PhantomPutStructure:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001440 node.setCanExit(false);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001441 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001442 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1443 m_haveStructures = true;
1444 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001445 case GetPropertyStorage:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00001446 case AllocatePropertyStorage:
1447 case ReallocatePropertyStorage:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001448 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001449 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001450 forNode(nodeIndex).clear(); // The result is not a JS value.
1451 break;
oliver@apple.com43e511c2011-12-09 08:45:46 +00001452 case GetIndexedPropertyStorage: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001453 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 +00001454 SpeculatedType basePrediction = m_graph[node.child2()].prediction();
1455 if (!(basePrediction & SpecInt32) && basePrediction) {
oliver@apple.com43e511c2011-12-09 08:45:46 +00001456 forNode(nodeIndex).clear();
1457 break;
1458 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001459 if (m_graph[node.child1()].shouldSpeculateArguments()) {
1460 ASSERT_NOT_REACHED();
1461 break;
1462 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001463 if (m_graph[node.child1()].prediction() == SpecString) {
1464 forNode(node.child1()).filter(SpecString);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001465 forNode(nodeIndex).clear();
1466 break;
1467 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001468
1469 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001470 forNode(node.child1()).filter(SpecInt8Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001471 forNode(nodeIndex).clear();
1472 break;
1473 }
1474 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001475 forNode(node.child1()).filter(SpecInt16Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001476 forNode(nodeIndex).clear();
1477 break;
1478 }
1479 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001480 forNode(node.child1()).filter(SpecInt32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001481 forNode(nodeIndex).clear();
1482 break;
1483 }
1484 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001485 forNode(node.child1()).filter(SpecUint8Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001486 forNode(nodeIndex).clear();
1487 break;
1488 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001489 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001490 forNode(node.child1()).filter(SpecUint8ClampedArray);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001491 forNode(nodeIndex).clear();
1492 break;
1493 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001494 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001495 forNode(node.child1()).filter(SpecUint16Array);
1496 forNode(nodeIndex).set(SpecOther);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001497 break;
1498 }
1499 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001500 forNode(node.child1()).filter(SpecUint32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001501 forNode(nodeIndex).clear();
1502 break;
1503 }
1504 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001505 forNode(node.child1()).filter(SpecFloat32Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001506 forNode(nodeIndex).clear();
1507 break;
1508 }
1509 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +00001510 forNode(node.child1()).filter(SpecFloat64Array);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001511 forNode(nodeIndex).clear();
1512 break;
1513 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001514 forNode(node.child1()).filter(SpecArray);
oliver@apple.com43e511c2011-12-09 08:45:46 +00001515 forNode(nodeIndex).clear();
1516 break;
1517 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001518 case GetByOffset:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001519 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001520 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001521 forNode(nodeIndex).makeTop();
1522 break;
1523
1524 case PutByOffset:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001525 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001526 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001527 break;
1528
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001529 case CheckFunction:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001530 node.setCanExit(true); // Lies! We can do better.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001531 forNode(node.child1()).filter(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001532 // FIXME: Should be able to propagate the fact that we know what the function is.
1533 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001534
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001535 case PutById:
1536 case PutByIdDirect:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001537 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001538 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001539 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001540 break;
1541
1542 case GetGlobalVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001543 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001544 forNode(nodeIndex).makeTop();
1545 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001546
1547 case GlobalVarWatchpoint:
1548 node.setCanExit(true);
1549 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001550
1551 case PutGlobalVar:
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001552 case PutGlobalVarCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001553 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001554 break;
1555
1556 case CheckHasInstance:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001557 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001558 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001559 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1560 break;
1561
1562 case InstanceOf:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001563 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001564 // Again, sadly, we don't propagate the fact that we've done InstanceOf
fpizlo@apple.com62336162012-06-07 01:35:59 +00001565 if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
1566 forNode(node.child1()).filter(SpecCell);
1567 forNode(node.child3()).filter(SpecCell);
1568 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001569 break;
1570
1571 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001572 case Flush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001573 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001574 break;
1575
1576 case Breakpoint:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001577 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001578 break;
1579
1580 case Call:
1581 case Construct:
1582 case Resolve:
1583 case ResolveBase:
1584 case ResolveBaseStrictPut:
1585 case ResolveGlobal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001586 node.setCanExit(true);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001587 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001588 forNode(nodeIndex).makeTop();
1589 break;
1590
1591 case ForceOSRExit:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001592 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001593 m_isValid = false;
1594 break;
1595
1596 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001597 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001598 case Nop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001599 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001600 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001601
1602 case LastNodeType:
1603 ASSERT_NOT_REACHED();
1604 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001605 }
1606
1607 return m_isValid;
1608}
1609
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001610inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1611{
1612 if (codeOrigin.inlineCallFrame) {
1613 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1614 for (size_t i = capturedVars.size(); i--;) {
1615 if (!capturedVars.quickGet(i))
1616 continue;
1617 m_variables.local(i).makeTop();
1618 }
1619 } else {
1620 for (size_t i = m_codeBlock->m_numCapturedVars; i--;)
1621 m_variables.local(i).makeTop();
1622 }
1623 if (m_codeBlock->argumentsAreCaptured()) {
1624 for (size_t i = m_variables.numberOfArguments(); i--;)
1625 m_variables.argument(i).makeTop();
1626 }
1627 clobberStructures(indexInBlock);
1628}
1629
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001630inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001631{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001632 if (!m_haveStructures)
1633 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001634 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001635 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001636 for (size_t i = m_variables.numberOfArguments(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001637 m_variables.argument(i).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001638 for (size_t i = m_variables.numberOfLocals(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001639 m_variables.local(i).clobberStructures();
1640 m_haveStructures = false;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001641 m_didClobber = true;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001642}
1643
1644inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1645{
1646 if (nodeIndex == NoNode)
1647 return false;
1648
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001649 AbstractValue source;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001650
1651 Node& node = m_graph[nodeIndex];
1652 if (!node.refCount())
1653 return false;
1654
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001655#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001656 dataLog(" It's live, node @%u.\n", nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001657#endif
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001658
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001659 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001660 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001661#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001662 dataLog(" Transfering ");
1663 source.dump(WTF::dataFile());
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001664 dataLog(" from last access due to captured variable.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001665#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001666 } else {
1667 switch (node.op()) {
1668 case Phi:
1669 case SetArgument:
1670 case Flush:
1671 // The block transfers the value from head to tail.
1672 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001673#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001674 dataLog(" Transfering ");
1675 source.dump(WTF::dataFile());
1676 dataLog(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001677#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001678 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001679
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001680 case GetLocal:
1681 // The block refines the value with additional speculations.
1682 source = forNode(nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001683#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001684 dataLog(" Refining to ");
1685 source.dump(WTF::dataFile());
1686 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001687#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001688 break;
1689
1690 case SetLocal:
1691 // The block sets the variable, and potentially refines it, both
1692 // before and after setting it.
1693 if (node.variableAccessData()->shouldUseDoubleFormat()) {
1694 // FIXME: This unnecessarily loses precision.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001695 source.set(SpecDouble);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001696 } else
1697 source = forNode(node.child1());
1698#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1699 dataLog(" Setting to ");
1700 source.dump(WTF::dataFile());
1701 dataLog("\n");
1702#endif
1703 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001704
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001705 default:
1706 ASSERT_NOT_REACHED();
1707 break;
1708 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001709 }
1710
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001711 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001712 // Abstract execution did not change the output value of the variable, for this
1713 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001714#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001715 dataLog(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001716#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001717 return false;
1718 }
1719
1720 // Abstract execution reached a new conclusion about the speculations reached about
1721 // this variable after execution of this basic block. Update the state, and return
1722 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001723 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001724#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001725 dataLog(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001726#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001727 return true;
1728}
1729
1730inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1731{
1732 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1733 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1734
1735 bool changed = false;
1736
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001737 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1738 AbstractValue& destination = to->valuesAtHead.argument(argument);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001739 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1740 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001741
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001742 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1743 AbstractValue& destination = to->valuesAtHead.local(local);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001744 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1745 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001746
1747 if (!to->cfaHasVisited)
1748 changed = true;
1749
1750 to->cfaShouldRevisit |= changed;
1751
1752 return changed;
1753}
1754
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001755inline bool AbstractState::mergeToSuccessors(
1756 Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001757{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001758 Node& terminal = graph[basicBlock->last()];
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001759
1760 ASSERT(terminal.isTerminal());
1761
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001762 switch (terminal.op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001763 case Jump: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001764 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001765#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1766 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1767#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001768 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001769 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001770
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001771 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001772 ASSERT(branchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001773 bool changed = false;
1774#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1775 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1776#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001777 if (branchDirection != TakeFalse)
1778 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001779#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1780 dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1781#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001782 if (branchDirection != TakeTrue)
1783 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001784 return changed;
1785 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001786
1787 case Return:
1788 case Throw:
1789 case ThrowReferenceError:
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001790 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001791 return false;
1792
1793 default:
1794 ASSERT_NOT_REACHED();
1795 return false;
1796 }
1797}
1798
1799inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1800{
1801 if (destinationNodeIndex == NoNode)
1802 return false;
1803
1804 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1805
1806 // FIXME: We could do some sparse conditional propagation here!
1807
1808 return destination.merge(source);
1809}
1810
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001811void AbstractState::dump(FILE* out)
1812{
1813 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001814 for (size_t i = 0; i < m_block->size(); ++i) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001815 NodeIndex index = m_block->at(i);
1816 AbstractValue& value = m_nodes[index];
1817 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001818 continue;
1819 if (first)
1820 first = false;
1821 else
1822 fprintf(out, " ");
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001823 fprintf(out, "@%lu:", static_cast<unsigned long>(index));
1824 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001825 }
1826}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001827
1828} } // namespace JSC::DFG
1829
1830#endif // ENABLE(DFG_JIT)
1831