blob: 5c5b7abf658f03605b9c8653ba77409d0aa001a0 [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
36#define CFA_PROFILING 0
37
38#if CFA_PROFILING
39#define PROFILE(flag) SamplingFlags::ScopedFlag scopedFlag(flag)
40#else
41#define PROFILE(flag) do { } while (false)
42#endif
43
44// Profiling flags
45#define FLAG_FOR_BLOCK_INITIALIZATION 17
46#define FLAG_FOR_BLOCK_END 18
47#define FLAG_FOR_EXECUTION 19
48#define FLAG_FOR_MERGE_TO_SUCCESSORS 20
49#define FLAG_FOR_STRUCTURE_CLOBBERING 21
50
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000051AbstractState::AbstractState(Graph& graph)
52 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000053 , m_graph(graph)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000054 , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000055 , m_block(0)
56{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000057 m_nodes.resize(graph.size());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000058}
59
60AbstractState::~AbstractState() { }
61
62void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
63{
64 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
65
66 ASSERT(!m_block);
67
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000068 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
69 ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
70 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
71
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000072 for (size_t i = 0; i < basicBlock->size(); i++)
73 m_nodes[basicBlock->at(i)].clear();
74
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000075 m_variables = basicBlock->valuesAtHead;
76 m_haveStructures = false;
77 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
78 if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
79 m_haveStructures = true;
80 break;
81 }
82 }
83 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
84 if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
85 m_haveStructures = true;
86 break;
87 }
88 }
89
90 basicBlock->cfaShouldRevisit = false;
91 basicBlock->cfaHasVisited = true;
92 m_block = basicBlock;
93 m_isValid = true;
fpizlo@apple.com3187c922012-05-18 21:47:53 +000094 m_foundConstants = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +000095 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000096}
97
98void AbstractState::initialize(Graph& graph)
99{
100 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
101 BasicBlock* root = graph.m_blocks[0].get();
102 root->cfaShouldRevisit = true;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000103 root->cfaHasVisited = false;
104 root->cfaFoundConstants = false;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000105 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
fpizlo@apple.com4f5361262012-02-16 10:06:28 +0000106 Node& node = graph[root->variablesAtHead.argument(i)];
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000107 ASSERT(node.op() == SetArgument);
fpizlo@apple.com4f5361262012-02-16 10:06:28 +0000108 if (!node.shouldGenerate()) {
109 // The argument is dead. We don't do any checks for such arguments, and so
110 // for the purpose of the analysis, they contain no value.
111 root->valuesAtHead.argument(i).clear();
112 continue;
113 }
114
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000115 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000116 root->valuesAtHead.argument(i).makeTop();
117 continue;
118 }
119
fpizlo@apple.com4f5361262012-02-16 10:06:28 +0000120 PredictedType prediction = node.variableAccessData()->prediction();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000121 if (isInt32Prediction(prediction))
122 root->valuesAtHead.argument(i).set(PredictInt32);
123 else if (isArrayPrediction(prediction))
124 root->valuesAtHead.argument(i).set(PredictArray);
125 else if (isBooleanPrediction(prediction))
126 root->valuesAtHead.argument(i).set(PredictBoolean);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000127 else if (isInt8ArrayPrediction(prediction))
128 root->valuesAtHead.argument(i).set(PredictInt8Array);
129 else if (isInt16ArrayPrediction(prediction))
130 root->valuesAtHead.argument(i).set(PredictInt16Array);
131 else if (isInt32ArrayPrediction(prediction))
132 root->valuesAtHead.argument(i).set(PredictInt32Array);
133 else if (isUint8ArrayPrediction(prediction))
134 root->valuesAtHead.argument(i).set(PredictUint8Array);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000135 else if (isUint8ClampedArrayPrediction(prediction))
136 root->valuesAtHead.argument(i).set(PredictUint8ClampedArray);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000137 else if (isUint16ArrayPrediction(prediction))
138 root->valuesAtHead.argument(i).set(PredictUint16Array);
139 else if (isUint32ArrayPrediction(prediction))
140 root->valuesAtHead.argument(i).set(PredictUint32Array);
141 else if (isFloat32ArrayPrediction(prediction))
142 root->valuesAtHead.argument(i).set(PredictFloat32Array);
143 else if (isFloat64ArrayPrediction(prediction))
144 root->valuesAtHead.argument(i).set(PredictFloat64Array);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000145 else
146 root->valuesAtHead.argument(i).makeTop();
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000147
148 root->valuesAtTail.argument(i).clear();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000149 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000150 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000151 NodeIndex nodeIndex = root->variablesAtHead.local(i);
152 if (nodeIndex != NoNode && graph[nodeIndex].variableAccessData()->isCaptured())
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000153 root->valuesAtHead.local(i).makeTop();
154 else
155 root->valuesAtHead.local(i).clear();
156 root->valuesAtTail.local(i).clear();
157 }
158 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
159 BasicBlock* block = graph.m_blocks[blockIndex].get();
160 if (!block)
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000161 continue;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000162 if (!block->isReachable)
163 continue;
164 block->cfaShouldRevisit = false;
165 block->cfaHasVisited = false;
166 block->cfaFoundConstants = false;
167 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
168 block->valuesAtHead.argument(i).clear();
169 block->valuesAtTail.argument(i).clear();
170 }
171 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
172 block->valuesAtHead.local(i).clear();
173 block->valuesAtTail.local(i).clear();
174 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000175 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000176}
177
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000178bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000179{
180 PROFILE(FLAG_FOR_BLOCK_END);
181 ASSERT(m_block);
182
183 BasicBlock* block = m_block; // Save the block for successor merging.
184
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000185 block->cfaFoundConstants = m_foundConstants;
186
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000187 if (!m_isValid) {
188 reset();
189 return false;
190 }
191
192 bool changed = false;
193
194 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000195 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
196#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000197 dataLog(" Merging state for argument %zu.\n", argument);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000198#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000199 AbstractValue& destination = block->valuesAtTail.argument(argument);
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000200 NodeIndex nodeIndex = block->variablesAtTail.argument(argument);
201 if (nodeIndex != NoNode && m_graph[nodeIndex].variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000202 if (!destination.isTop()) {
203 destination.makeTop();
204 changed = true;
205 }
206 } else
207 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000208 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000209
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000210 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
211#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000212 dataLog(" Merging state for local %zu.\n", local);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000213#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000214 AbstractValue& destination = block->valuesAtTail.local(local);
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000215 NodeIndex nodeIndex = block->variablesAtTail.local(local);
216 if (nodeIndex != NoNode && m_graph[nodeIndex].variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000217 if (!destination.isTop()) {
218 destination.makeTop();
219 changed = true;
220 }
221 } else
222 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000223 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000224 }
225
226 ASSERT(mergeMode != DontMerge || !changed);
227
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000228 BranchDirection branchDirection = m_branchDirection;
229 if (branchDirectionPtr)
230 *branchDirectionPtr = branchDirection;
231
232#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
233 dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection));
234#endif
235
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000236 reset();
237
238 if (mergeMode != MergeToSuccessors)
239 return changed;
240
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000241 return mergeToSuccessors(m_graph, block, branchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000242}
243
244void AbstractState::reset()
245{
246 m_block = 0;
247 m_isValid = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000248 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000249}
250
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000251bool AbstractState::execute(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000252{
253 PROFILE(FLAG_FOR_EXECUTION);
254 ASSERT(m_block);
255 ASSERT(m_isValid);
256
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000257 NodeIndex nodeIndex = m_block->at(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000258 Node& node = m_graph[nodeIndex];
259
260 if (!node.shouldGenerate())
261 return true;
262
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000263 switch (node.op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000264 case JSConstant:
265 case WeakJSConstant: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000266 forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000267 break;
268 }
269
270 case GetLocal: {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000271 if (node.variableAccessData()->isCaptured())
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000272 forNode(nodeIndex).makeTop();
273 else
274 forNode(nodeIndex) = m_variables.operand(node.local());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000275 break;
276 }
277
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000278 case GetLocalUnlinked: {
279 forNode(nodeIndex).makeTop();
280 break;
281 }
282
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000283 case SetLocal: {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000284 if (node.variableAccessData()->isCaptured())
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000285 break;
286
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000287 if (node.variableAccessData()->shouldUseDoubleFormat()) {
288 forNode(node.child1()).filter(PredictNumber);
289 m_variables.operand(node.local()).set(PredictDouble);
290 break;
291 }
292
fpizlo@apple.comaf8940b2012-04-11 00:37:04 +0000293 PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000294 if (isInt32Prediction(predictedType))
295 forNode(node.child1()).filter(PredictInt32);
296 else if (isArrayPrediction(predictedType))
297 forNode(node.child1()).filter(PredictArray);
298 else if (isBooleanPrediction(predictedType))
299 forNode(node.child1()).filter(PredictBoolean);
300
301 m_variables.operand(node.local()) = forNode(node.child1());
302 break;
303 }
304
305 case SetArgument:
306 // Assert that the state of arguments has been set.
307 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
308 break;
309
310 case BitAnd:
311 case BitOr:
312 case BitXor:
313 case BitRShift:
314 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000315 case BitURShift: {
316 JSValue left = forNode(node.child1()).value();
317 JSValue right = forNode(node.child2()).value();
318 if (left && right && left.isInt32() && right.isInt32()) {
319 int32_t a = left.asInt32();
320 int32_t b = right.asInt32();
321 switch (node.op()) {
322 case BitAnd:
323 forNode(nodeIndex).set(JSValue(a & b));
324 break;
325 case BitOr:
326 forNode(nodeIndex).set(JSValue(a | b));
327 break;
328 case BitXor:
329 forNode(nodeIndex).set(JSValue(a ^ b));
330 break;
331 case BitRShift:
332 forNode(nodeIndex).set(JSValue(a >> static_cast<uint32_t>(b)));
333 break;
334 case BitLShift:
335 forNode(nodeIndex).set(JSValue(a << static_cast<uint32_t>(b)));
336 break;
337 case BitURShift:
338 forNode(nodeIndex).set(JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
339 break;
340 default:
341 ASSERT_NOT_REACHED();
342 }
343 m_foundConstants = true;
344 break;
345 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000346 forNode(node.child1()).filter(PredictInt32);
347 forNode(node.child2()).filter(PredictInt32);
348 forNode(nodeIndex).set(PredictInt32);
349 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000350 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000351
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000352 case UInt32ToNumber: {
353 JSValue child = forNode(node.child1()).value();
354 if (child && child.isNumber()) {
355 ASSERT(child.isInt32());
356 forNode(nodeIndex).set(JSValue(child.asUInt32()));
357 m_foundConstants = true;
358 break;
359 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000360 if (!node.canSpeculateInteger())
361 forNode(nodeIndex).set(PredictDouble);
362 else
363 forNode(nodeIndex).set(PredictInt32);
364 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000365 }
366
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000367
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000368 case DoubleAsInt32: {
369 JSValue child = forNode(node.child1()).value();
370 if (child && child.isNumber()) {
371 double asDouble = child.asNumber();
372 int32_t asInt = JSC::toInt32(asDouble);
373 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
374 forNode(nodeIndex).set(JSValue(asInt));
375 m_foundConstants = true;
376 break;
377 }
378 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000379 forNode(node.child1()).filter(PredictNumber);
380 forNode(nodeIndex).set(PredictInt32);
381 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000382 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000383
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000384 case ValueToInt32: {
385 JSValue child = forNode(node.child1()).value();
386 if (child && child.isNumber()) {
387 if (child.isInt32())
388 forNode(nodeIndex).set(child);
389 else
390 forNode(nodeIndex).set(JSValue(JSC::toInt32(child.asDouble())));
391 m_foundConstants = true;
392 break;
393 }
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000394 if (m_graph[node.child1()].shouldSpeculateInteger())
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000395 forNode(node.child1()).filter(PredictInt32);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000396 else if (m_graph[node.child1()].shouldSpeculateNumber())
397 forNode(node.child1()).filter(PredictNumber);
398 else if (m_graph[node.child1()].shouldSpeculateBoolean())
399 forNode(node.child1()).filter(PredictBoolean);
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000400
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000401 forNode(nodeIndex).set(PredictInt32);
402 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000403 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000404
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000405 case Int32ToDouble: {
406 JSValue child = forNode(node.child1()).value();
407 if (child && child.isNumber()) {
408 forNode(nodeIndex).set(JSValue(JSValue::EncodeAsDouble, child.asNumber()));
409 m_foundConstants = true;
410 break;
411 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000412 forNode(node.child1()).filter(PredictNumber);
413 forNode(nodeIndex).set(PredictDouble);
414 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000415 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000416
417 case CheckNumber:
418 forNode(node.child1()).filter(PredictNumber);
419 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000420
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000421 case ValueAdd:
422 case ArithAdd: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000423 JSValue left = forNode(node.child1()).value();
424 JSValue right = forNode(node.child2()).value();
425 if (left && right && left.isNumber() && right.isNumber()) {
426 forNode(nodeIndex).set(JSValue(left.asNumber() + right.asNumber()));
427 m_foundConstants = true;
428 break;
429 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000430 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000431 forNode(node.child1()).filter(PredictInt32);
432 forNode(node.child2()).filter(PredictInt32);
433 forNode(nodeIndex).set(PredictInt32);
434 break;
435 }
436 if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
437 forNode(node.child1()).filter(PredictNumber);
438 forNode(node.child2()).filter(PredictNumber);
439 forNode(nodeIndex).set(PredictDouble);
440 break;
441 }
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000442 if (node.op() == ValueAdd) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000443 clobberStructures(indexInBlock);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000444 forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber);
445 break;
446 }
447 // We don't handle this yet. :-(
448 m_isValid = false;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000449 break;
450 }
451
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000452 case ArithSub: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000453 JSValue left = forNode(node.child1()).value();
454 JSValue right = forNode(node.child2()).value();
455 if (left && right && left.isNumber() && right.isNumber()) {
456 forNode(nodeIndex).set(JSValue(left.asNumber() - right.asNumber()));
457 m_foundConstants = true;
458 break;
459 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000460 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000461 forNode(node.child1()).filter(PredictInt32);
462 forNode(node.child2()).filter(PredictInt32);
463 forNode(nodeIndex).set(PredictInt32);
464 break;
465 }
466 forNode(node.child1()).filter(PredictNumber);
467 forNode(node.child2()).filter(PredictNumber);
468 forNode(nodeIndex).set(PredictDouble);
469 break;
470 }
471
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000472 case ArithNegate: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000473 JSValue child = forNode(node.child1()).value();
474 if (child && child.isNumber()) {
475 forNode(nodeIndex).set(JSValue(-child.asNumber()));
476 m_foundConstants = true;
477 break;
478 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000479 if (m_graph.negateShouldSpeculateInteger(node)) {
480 forNode(node.child1()).filter(PredictInt32);
481 forNode(nodeIndex).set(PredictInt32);
482 break;
483 }
484 forNode(node.child1()).filter(PredictNumber);
485 forNode(nodeIndex).set(PredictDouble);
486 break;
487 }
488
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000489 case ArithMul: {
490 JSValue left = forNode(node.child1()).value();
491 JSValue right = forNode(node.child2()).value();
492 if (left && right && left.isNumber() && right.isNumber()) {
493 forNode(nodeIndex).set(JSValue(left.asNumber() * right.asNumber()));
494 m_foundConstants = true;
495 break;
496 }
497 if (m_graph.mulShouldSpeculateInteger(node)) {
498 forNode(node.child1()).filter(PredictInt32);
499 forNode(node.child2()).filter(PredictInt32);
500 forNode(nodeIndex).set(PredictInt32);
501 break;
502 }
503 forNode(node.child1()).filter(PredictNumber);
504 forNode(node.child2()).filter(PredictNumber);
505 forNode(nodeIndex).set(PredictDouble);
506 break;
507 }
508
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000509 case ArithDiv:
510 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000511 case ArithMax:
512 case ArithMod: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000513 JSValue left = forNode(node.child1()).value();
514 JSValue right = forNode(node.child2()).value();
515 if (left && right && left.isNumber() && right.isNumber()) {
516 double a = left.asNumber();
517 double b = right.asNumber();
518 switch (node.op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000519 case ArithDiv:
520 forNode(nodeIndex).set(JSValue(a / b));
521 break;
522 case ArithMin:
523 forNode(nodeIndex).set(JSValue(a < b ? a : (b <= a ? b : a + b)));
524 break;
525 case ArithMax:
526 forNode(nodeIndex).set(JSValue(a > b ? a : (b >= a ? b : a + b)));
527 break;
528 case ArithMod:
529 forNode(nodeIndex).set(JSValue(fmod(a, b)));
530 break;
531 default:
532 ASSERT_NOT_REACHED();
533 break;
534 }
535 m_foundConstants = true;
536 break;
537 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000538 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) {
539 forNode(node.child1()).filter(PredictInt32);
540 forNode(node.child2()).filter(PredictInt32);
541 forNode(nodeIndex).set(PredictInt32);
542 break;
543 }
544 forNode(node.child1()).filter(PredictNumber);
545 forNode(node.child2()).filter(PredictNumber);
546 forNode(nodeIndex).set(PredictDouble);
547 break;
548 }
549
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000550 case ArithAbs: {
551 JSValue child = forNode(node.child1()).value();
552 if (child && child.isNumber()) {
553 forNode(nodeIndex).set(JSValue(fabs(child.asNumber())));
554 m_foundConstants = true;
555 break;
556 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000557 if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) {
558 forNode(node.child1()).filter(PredictInt32);
559 forNode(nodeIndex).set(PredictInt32);
560 break;
561 }
562 forNode(node.child1()).filter(PredictNumber);
563 forNode(nodeIndex).set(PredictDouble);
564 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000565 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000566
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000567 case ArithSqrt: {
568 JSValue child = forNode(node.child1()).value();
569 if (child && child.isNumber()) {
570 forNode(nodeIndex).set(JSValue(sqrt(child.asNumber())));
571 m_foundConstants = true;
572 break;
573 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000574 forNode(node.child1()).filter(PredictNumber);
575 forNode(nodeIndex).set(PredictDouble);
576 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000577 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000578
579 case LogicalNot: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000580 JSValue childConst = forNode(node.child1()).value();
581 if (childConst) {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000582 forNode(nodeIndex).set(jsBoolean(!childConst.toBoolean()));
583 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000584 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000585 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +0000586 if (isBooleanPrediction(child.prediction()))
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000587 forNode(node.child1()).filter(PredictBoolean);
588 else if (child.shouldSpeculateFinalObjectOrOther())
589 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
590 else if (child.shouldSpeculateArrayOrOther())
591 forNode(node.child1()).filter(PredictArray | PredictOther);
592 else if (child.shouldSpeculateInteger())
593 forNode(node.child1()).filter(PredictInt32);
594 else if (child.shouldSpeculateNumber())
595 forNode(node.child1()).filter(PredictNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000596 forNode(nodeIndex).set(PredictBoolean);
597 break;
598 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000599
600 case IsUndefined:
601 case IsBoolean:
602 case IsNumber:
603 case IsString:
604 case IsObject:
605 case IsFunction: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000606 JSValue child = forNode(node.child1()).value();
607 if (child) {
608 bool foundConstant = true;
609 switch (node.op()) {
610 case IsUndefined:
611 forNode(nodeIndex).set(jsBoolean(
612 child.isCell()
613 ? child.asCell()->structure()->typeInfo().masqueradesAsUndefined()
614 : child.isUndefined()));
615 break;
616 case IsBoolean:
617 forNode(nodeIndex).set(jsBoolean(child.isBoolean()));
618 break;
619 case IsNumber:
620 forNode(nodeIndex).set(jsBoolean(child.isNumber()));
621 break;
622 case IsString:
623 forNode(nodeIndex).set(jsBoolean(isJSString(child)));
624 break;
625 default:
626 break;
627 }
628 if (foundConstant) {
629 m_foundConstants = true;
630 break;
631 }
632 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000633 forNode(nodeIndex).set(PredictBoolean);
634 break;
635 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000636
637 case CompareLess:
638 case CompareLessEq:
639 case CompareGreater:
640 case CompareGreaterEq:
641 case CompareEq: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000642 JSValue leftConst = forNode(node.child1()).value();
643 JSValue rightConst = forNode(node.child2()).value();
644 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
645 double a = leftConst.asNumber();
646 double b = rightConst.asNumber();
647 switch (node.op()) {
648 case CompareLess:
649 forNode(nodeIndex).set(jsBoolean(a < b));
650 break;
651 case CompareLessEq:
652 forNode(nodeIndex).set(jsBoolean(a <= b));
653 break;
654 case CompareGreater:
655 forNode(nodeIndex).set(jsBoolean(a > b));
656 break;
657 case CompareGreaterEq:
658 forNode(nodeIndex).set(jsBoolean(a >= b));
659 break;
660 case CompareEq:
661 forNode(nodeIndex).set(jsBoolean(a == b));
662 break;
663 default:
664 ASSERT_NOT_REACHED();
665 break;
666 }
667 m_foundConstants = true;
668 break;
669 }
670
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000671 forNode(nodeIndex).set(PredictBoolean);
672
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000673 Node& left = m_graph[node.child1()];
674 Node& right = m_graph[node.child2()];
675 PredictedType filter;
676 if (Node::shouldSpeculateInteger(left, right))
677 filter = PredictInt32;
678 else if (Node::shouldSpeculateNumber(left, right))
679 filter = PredictNumber;
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000680 else if (node.op() == CompareEq) {
681 if ((m_graph.isConstant(node.child1().index())
682 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
683 || (m_graph.isConstant(node.child2().index())
684 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
685 // We know that this won't clobber the world. But that's all we know.
686 break;
687 }
688
689 if (Node::shouldSpeculateFinalObject(left, right))
690 filter = PredictFinalObject;
691 else if (Node::shouldSpeculateArray(left, right))
692 filter = PredictArray;
693 else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
694 forNode(node.child1()).filter(PredictFinalObject);
695 forNode(node.child2()).filter(PredictFinalObject | PredictOther);
696 break;
697 } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
698 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
699 forNode(node.child2()).filter(PredictFinalObject);
700 break;
701 } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
702 forNode(node.child1()).filter(PredictFinalObject);
703 forNode(node.child2()).filter(PredictFinalObject | PredictOther);
704 break;
705 } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
706 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
707 forNode(node.child2()).filter(PredictFinalObject);
708 break;
709 } else {
710 filter = PredictTop;
711 clobberStructures(indexInBlock);
712 }
713 } else {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000714 filter = PredictTop;
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000715 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000716 }
717 forNode(node.child1()).filter(filter);
718 forNode(node.child2()).filter(filter);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000719 break;
720 }
721
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000722 case CompareStrictEq: {
723 JSValue left = forNode(node.child1()).value();
724 JSValue right = forNode(node.child2()).value();
725 if (left && right && left.isNumber() && right.isNumber()) {
726 forNode(nodeIndex).set(jsBoolean(left.asNumber() == right.asNumber()));
727 m_foundConstants = true;
728 break;
729 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000730 forNode(nodeIndex).set(PredictBoolean);
731 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000732 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000733
734 case StringCharCodeAt:
735 forNode(node.child1()).filter(PredictString);
736 forNode(node.child2()).filter(PredictInt32);
737 forNode(nodeIndex).set(PredictInt32);
738 break;
739
740 case StringCharAt:
741 forNode(node.child1()).filter(PredictString);
742 forNode(node.child2()).filter(PredictInt32);
743 forNode(nodeIndex).set(PredictString);
744 break;
745
746 case GetByVal: {
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000747 if (!node.prediction() || !m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
748 m_isValid = false;
749 break;
750 }
751 if (!isActionableArrayPrediction(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000752 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000753 forNode(nodeIndex).makeTop();
754 break;
755 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000756 if (m_graph[node.child1()].shouldSpeculateArguments()) {
757 forNode(node.child1()).filter(PredictArguments);
758 forNode(node.child2()).filter(PredictInt32);
759 forNode(nodeIndex).makeTop();
760 break;
761 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000762 if (m_graph[node.child1()].prediction() == PredictString) {
763 forNode(node.child1()).filter(PredictString);
764 forNode(node.child2()).filter(PredictInt32);
765 forNode(nodeIndex).set(PredictString);
766 break;
767 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000768
769 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
770 forNode(node.child1()).filter(PredictInt8Array);
771 forNode(node.child2()).filter(PredictInt32);
772 forNode(nodeIndex).set(PredictInt32);
773 break;
774 }
775 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
776 forNode(node.child1()).filter(PredictInt16Array);
777 forNode(node.child2()).filter(PredictInt32);
778 forNode(nodeIndex).set(PredictInt32);
779 break;
780 }
781 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
782 forNode(node.child1()).filter(PredictInt32Array);
783 forNode(node.child2()).filter(PredictInt32);
784 forNode(nodeIndex).set(PredictInt32);
785 break;
786 }
787 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
788 forNode(node.child1()).filter(PredictUint8Array);
789 forNode(node.child2()).filter(PredictInt32);
790 forNode(nodeIndex).set(PredictInt32);
791 break;
792 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000793 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
794 forNode(node.child1()).filter(PredictUint8ClampedArray);
795 forNode(node.child2()).filter(PredictInt32);
796 forNode(nodeIndex).set(PredictInt32);
797 break;
798 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000799 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
800 forNode(node.child1()).filter(PredictUint16Array);
801 forNode(node.child2()).filter(PredictInt32);
802 forNode(nodeIndex).set(PredictInt32);
803 break;
804 }
805 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
806 forNode(node.child1()).filter(PredictUint32Array);
807 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000808 if (node.shouldSpeculateInteger())
809 forNode(nodeIndex).set(PredictInt32);
810 else
811 forNode(nodeIndex).set(PredictDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000812 break;
813 }
oliver@apple.com07d75732011-12-03 01:47:27 +0000814 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
815 forNode(node.child1()).filter(PredictFloat32Array);
816 forNode(node.child2()).filter(PredictInt32);
817 forNode(nodeIndex).set(PredictDouble);
818 break;
819 }
820 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
821 forNode(node.child1()).filter(PredictFloat64Array);
822 forNode(node.child2()).filter(PredictInt32);
823 forNode(nodeIndex).set(PredictDouble);
824 break;
825 }
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000826 ASSERT(m_graph[node.child1()].shouldSpeculateArray());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000827 forNode(node.child1()).filter(PredictArray);
828 forNode(node.child2()).filter(PredictInt32);
829 forNode(nodeIndex).makeTop();
830 break;
831 }
832
833 case PutByVal:
834 case PutByValAlias: {
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000835 if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
836 m_isValid = false;
837 break;
838 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000839 if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())
840#if USE(JSVALUE32_64)
841 || m_graph[node.child1()].shouldSpeculateArguments()
842#endif
843 ) {
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000844 ASSERT(node.op() == PutByVal);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000845 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000846 forNode(nodeIndex).makeTop();
847 break;
848 }
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000849
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000850 if (m_graph[node.child1()].shouldSpeculateArguments()) {
851 forNode(node.child1()).filter(PredictArguments);
852 forNode(node.child2()).filter(PredictInt32);
853 break;
854 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000855 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
856 forNode(node.child1()).filter(PredictInt8Array);
857 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000858 if (m_graph[node.child3()].shouldSpeculateInteger())
859 forNode(node.child3()).filter(PredictInt32);
860 else
861 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000862 break;
863 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000864 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
865 forNode(node.child1()).filter(PredictInt16Array);
866 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000867 if (m_graph[node.child3()].shouldSpeculateInteger())
868 forNode(node.child3()).filter(PredictInt32);
869 else
870 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000871 break;
872 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000873 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
874 forNode(node.child1()).filter(PredictInt32Array);
875 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000876 if (m_graph[node.child3()].shouldSpeculateInteger())
877 forNode(node.child3()).filter(PredictInt32);
878 else
879 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000880 break;
881 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000882 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
883 forNode(node.child1()).filter(PredictUint8Array);
884 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000885 if (m_graph[node.child3()].shouldSpeculateInteger())
886 forNode(node.child3()).filter(PredictInt32);
887 else
888 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000889 break;
890 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000891 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
892 forNode(node.child1()).filter(PredictUint8ClampedArray);
893 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000894 if (m_graph[node.child3()].shouldSpeculateInteger())
895 forNode(node.child3()).filter(PredictInt32);
896 else
897 forNode(node.child3()).filter(PredictNumber);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000898 break;
899 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000900 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
901 forNode(node.child1()).filter(PredictUint16Array);
902 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000903 if (m_graph[node.child3()].shouldSpeculateInteger())
904 forNode(node.child3()).filter(PredictInt32);
905 else
906 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000907 break;
908 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000909 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
910 forNode(node.child1()).filter(PredictUint32Array);
911 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000912 if (m_graph[node.child3()].shouldSpeculateInteger())
913 forNode(node.child3()).filter(PredictInt32);
914 else
915 forNode(node.child3()).filter(PredictNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000916 break;
917 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000918 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
919 forNode(node.child1()).filter(PredictFloat32Array);
920 forNode(node.child2()).filter(PredictInt32);
921 forNode(node.child3()).filter(PredictNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +0000922 break;
923 }
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000924 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
925 forNode(node.child1()).filter(PredictFloat64Array);
926 forNode(node.child2()).filter(PredictInt32);
927 forNode(node.child3()).filter(PredictNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +0000928 break;
929 }
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000930 ASSERT(m_graph[node.child1()].shouldSpeculateArray());
commit-queue@webkit.org8a040d92011-12-19 20:22:31 +0000931 forNode(node.child1()).filter(PredictArray);
932 forNode(node.child2()).filter(PredictInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000933 break;
934 }
935
936 case ArrayPush:
937 forNode(node.child1()).filter(PredictArray);
938 forNode(nodeIndex).set(PredictNumber);
939 break;
940
941 case ArrayPop:
942 forNode(node.child1()).filter(PredictArray);
943 forNode(nodeIndex).makeTop();
944 break;
945
barraclough@apple.com077fdd42012-03-18 01:08:16 +0000946 case RegExpExec:
947 case RegExpTest:
948 forNode(node.child1()).filter(PredictCell);
949 forNode(node.child2()).filter(PredictCell);
950 forNode(nodeIndex).makeTop();
951 break;
952
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000953 case Jump:
954 break;
955
956 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000957 JSValue value = forNode(node.child1()).value();
958 if (value) {
959 bool booleanValue = value.toBoolean();
960 if (booleanValue)
961 m_branchDirection = TakeTrue;
962 else
963 m_branchDirection = TakeFalse;
964 break;
965 }
966 // FIXME: The above handles the trivial cases of sparse conditional
967 // constant propagation, but we can do better:
968 // 1) If the abstract value does not have a concrete value but describes
969 // something that is known to evaluate true (or false) then we ought
970 // to sparse conditional that.
971 // 2) We can specialize the source variable's value on each direction of
972 // the branch.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000973 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +0000974 if (child.shouldSpeculateBoolean())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000975 forNode(node.child1()).filter(PredictBoolean);
976 else if (child.shouldSpeculateFinalObjectOrOther())
977 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
978 else if (child.shouldSpeculateArrayOrOther())
979 forNode(node.child1()).filter(PredictArray | PredictOther);
980 else if (child.shouldSpeculateInteger())
981 forNode(node.child1()).filter(PredictInt32);
982 else if (child.shouldSpeculateNumber())
983 forNode(node.child1()).filter(PredictNumber);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000984 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000985 break;
986 }
987
988 case Return:
989 case Throw:
990 case ThrowReferenceError:
991 m_isValid = false;
992 break;
993
994 case ToPrimitive: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000995 JSValue childConst = forNode(node.child1()).value();
996 if (childConst && childConst.isNumber()) {
997 forNode(nodeIndex).set(childConst);
998 m_foundConstants = true;
999 break;
1000 }
1001
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001002 Node& child = m_graph[node.child1()];
1003 if (child.shouldSpeculateInteger()) {
1004 forNode(node.child1()).filter(PredictInt32);
1005 forNode(nodeIndex).set(PredictInt32);
1006 break;
1007 }
1008
1009 AbstractValue& source = forNode(node.child1());
1010 AbstractValue& destination = forNode(nodeIndex);
1011
1012 PredictedType type = source.m_type;
1013 if (type & ~(PredictNumber | PredictString | PredictBoolean)) {
1014 type &= (PredictNumber | PredictString | PredictBoolean);
1015 type |= PredictString;
1016 }
1017 destination.set(type);
1018 break;
1019 }
1020
1021 case StrCat:
1022 forNode(nodeIndex).set(PredictString);
1023 break;
1024
1025 case NewArray:
1026 case NewArrayBuffer:
1027 forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
1028 m_haveStructures = true;
1029 break;
1030
1031 case NewRegexp:
1032 forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
1033 m_haveStructures = true;
1034 break;
1035
1036 case ConvertThis: {
1037 Node& child = m_graph[node.child1()];
1038 AbstractValue& source = forNode(node.child1());
1039 AbstractValue& destination = forNode(nodeIndex);
1040
1041 if (isObjectPrediction(source.m_type)) {
1042 // This is the simple case. We already know that the source is an
1043 // object, so there's nothing to do. I don't think this case will
1044 // be hit, but then again, you never know.
1045 destination = source;
1046 break;
1047 }
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001048
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001049 if (isOtherPrediction(child.prediction())) {
1050 source.filter(PredictOther);
1051 destination.set(PredictObjectOther);
1052 break;
1053 }
1054
1055 if (isObjectPrediction(child.prediction())) {
1056 source.filter(PredictObjectMask);
1057 destination = source;
1058 break;
1059 }
1060
1061 destination = source;
1062 destination.merge(PredictObjectOther);
1063 break;
1064 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001065
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001066 case CreateThis: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001067 AbstractValue& source = forNode(node.child1());
1068 AbstractValue& destination = forNode(nodeIndex);
1069
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001070 source.filter(PredictFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001071 destination.set(PredictFinalObject);
1072 break;
1073 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001074
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001075 case NewObject:
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001076 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001077 m_haveStructures = true;
1078 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001079
1080 case CreateActivation:
1081 forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get());
1082 m_haveStructures = true;
1083 break;
1084
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001085 case CreateArguments:
1086 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1087 m_haveStructures = true;
1088 break;
1089
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001090 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001091 case TearOffArguments:
fpizlo@apple.com5e3852d2012-05-24 00:05:21 +00001092 case CheckArgumentsNotCreated:
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001093 // Does nothing that is user-visible.
1094 break;
1095
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001096 case GetMyArgumentsLength:
fpizlo@apple.com9b928722012-05-24 00:18:55 +00001097 if (!m_graph.m_executablesWhoseArgumentsEscaped.contains(
1098 m_graph.executableFor(node.codeOrigin))) {
1099 // We know that this executable does not escape its arguments, so we can optimize
1100 // the arguments a bit. Note that this is not sufficient to force constant folding
1101 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1102 // We perform further optimizations on this later on.
1103 if (node.codeOrigin.inlineCallFrame) {
1104 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
1105 break;
1106 }
1107 forNode(nodeIndex).set(PredictInt32);
1108 break;
1109 }
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001110 // This potentially clobbers all structures if the arguments object had a getter
1111 // installed on the length property.
1112 clobberStructures(indexInBlock);
1113 // We currently make no guarantee about what this returns because it does not
1114 // speculate that the length property is actually a length.
1115 forNode(nodeIndex).makeTop();
1116 break;
1117
1118 case GetMyArgumentByVal:
fpizlo@apple.com9b928722012-05-24 00:18:55 +00001119 if (!m_graph.m_executablesWhoseArgumentsEscaped.contains(
1120 m_graph.executableFor(node.codeOrigin))) {
1121 // We know that this executable does not escape its arguments, so we can optimize
1122 // the arguments a bit. Note that this ends up being further optimized by the
1123 // ArgumentsSimplificationPhase.
1124 forNode(node.child1()).filter(PredictInt32);
1125 forNode(nodeIndex).makeTop();
1126 break;
1127 }
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001128 // This potentially clobbers all structures if the property we're accessing has
1129 // a getter. We don't speculate against this.
1130 clobberStructures(indexInBlock);
1131 // But we do speculate that the index is an integer.
1132 forNode(node.child1()).filter(PredictInt32);
1133 // And the result is unknown.
1134 forNode(nodeIndex).makeTop();
1135 break;
1136
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001137 case NewFunction:
1138 case NewFunctionExpression:
1139 case NewFunctionNoCheck:
1140 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1141 break;
1142
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001143 case GetCallee:
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001144 forNode(nodeIndex).set(PredictFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001145 break;
1146
1147 case GetScopeChain:
1148 forNode(nodeIndex).set(PredictCellOther);
1149 break;
1150
1151 case GetScopedVar:
1152 forNode(nodeIndex).makeTop();
1153 break;
1154
1155 case PutScopedVar:
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001156 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001157 break;
1158
1159 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001160 case GetByIdFlush:
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001161 if (!node.prediction()) {
1162 m_isValid = false;
1163 break;
1164 }
fpizlo@apple.comf6967542011-11-28 23:51:51 +00001165 if (isCellPrediction(m_graph[node.child1()].prediction()))
1166 forNode(node.child1()).filter(PredictCell);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001167 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001168 forNode(nodeIndex).makeTop();
1169 break;
1170
1171 case GetArrayLength:
1172 forNode(node.child1()).filter(PredictArray);
1173 forNode(nodeIndex).set(PredictInt32);
1174 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001175
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001176 case GetArgumentsLength:
1177 forNode(node.child1()).filter(PredictArguments);
1178 forNode(nodeIndex).set(PredictInt32);
1179 break;
1180
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001181 case GetStringLength:
1182 forNode(node.child1()).filter(PredictString);
1183 forNode(nodeIndex).set(PredictInt32);
1184 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001185
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001186 case GetInt8ArrayLength:
1187 forNode(node.child1()).filter(PredictInt8Array);
1188 forNode(nodeIndex).set(PredictInt32);
1189 break;
1190 case GetInt16ArrayLength:
1191 forNode(node.child1()).filter(PredictInt16Array);
1192 forNode(nodeIndex).set(PredictInt32);
1193 break;
1194 case GetInt32ArrayLength:
1195 forNode(node.child1()).filter(PredictInt32Array);
1196 forNode(nodeIndex).set(PredictInt32);
1197 break;
1198 case GetUint8ArrayLength:
1199 forNode(node.child1()).filter(PredictUint8Array);
1200 forNode(nodeIndex).set(PredictInt32);
1201 break;
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001202 case GetUint8ClampedArrayLength:
1203 forNode(node.child1()).filter(PredictUint8ClampedArray);
1204 forNode(nodeIndex).set(PredictInt32);
1205 break;
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001206 case GetUint16ArrayLength:
1207 forNode(node.child1()).filter(PredictUint16Array);
1208 forNode(nodeIndex).set(PredictInt32);
1209 break;
1210 case GetUint32ArrayLength:
1211 forNode(node.child1()).filter(PredictUint32Array);
1212 forNode(nodeIndex).set(PredictInt32);
1213 break;
1214 case GetFloat32ArrayLength:
1215 forNode(node.child1()).filter(PredictFloat32Array);
1216 forNode(nodeIndex).set(PredictInt32);
1217 break;
1218 case GetFloat64ArrayLength:
1219 forNode(node.child1()).filter(PredictFloat64Array);
1220 forNode(nodeIndex).set(PredictInt32);
1221 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001222
1223 case CheckStructure:
1224 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
1225 forNode(node.child1()).filter(node.structureSet());
1226 m_haveStructures = true;
1227 break;
1228
1229 case PutStructure:
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001230 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001231 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1232 m_haveStructures = true;
1233 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001234 case GetPropertyStorage:
1235 forNode(node.child1()).filter(PredictCell);
1236 forNode(nodeIndex).clear(); // The result is not a JS value.
1237 break;
oliver@apple.com43e511c2011-12-09 08:45:46 +00001238 case GetIndexedPropertyStorage: {
1239 PredictedType basePrediction = m_graph[node.child2()].prediction();
1240 if (!(basePrediction & PredictInt32) && basePrediction) {
1241 forNode(nodeIndex).clear();
1242 break;
1243 }
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001244 if (m_graph[node.child1()].shouldSpeculateArguments()) {
1245 ASSERT_NOT_REACHED();
1246 break;
1247 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001248 if (m_graph[node.child1()].prediction() == PredictString) {
1249 forNode(node.child1()).filter(PredictString);
1250 forNode(nodeIndex).clear();
1251 break;
1252 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001253
1254 if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
1255 forNode(node.child1()).filter(PredictInt8Array);
1256 forNode(nodeIndex).clear();
1257 break;
1258 }
1259 if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
1260 forNode(node.child1()).filter(PredictInt16Array);
1261 forNode(nodeIndex).clear();
1262 break;
1263 }
1264 if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
1265 forNode(node.child1()).filter(PredictInt32Array);
1266 forNode(nodeIndex).clear();
1267 break;
1268 }
1269 if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
1270 forNode(node.child1()).filter(PredictUint8Array);
1271 forNode(nodeIndex).clear();
1272 break;
1273 }
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001274 if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
1275 forNode(node.child1()).filter(PredictUint8ClampedArray);
1276 forNode(nodeIndex).clear();
1277 break;
1278 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001279 if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
1280 forNode(node.child1()).filter(PredictUint16Array);
1281 forNode(nodeIndex).set(PredictOther);
1282 break;
1283 }
1284 if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
1285 forNode(node.child1()).filter(PredictUint32Array);
1286 forNode(nodeIndex).clear();
1287 break;
1288 }
1289 if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
1290 forNode(node.child1()).filter(PredictFloat32Array);
1291 forNode(nodeIndex).clear();
1292 break;
1293 }
1294 if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
1295 forNode(node.child1()).filter(PredictFloat64Array);
1296 forNode(nodeIndex).clear();
1297 break;
1298 }
1299 forNode(node.child1()).filter(PredictArray);
1300 forNode(nodeIndex).clear();
1301 break;
1302 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001303 case GetByOffset:
1304 forNode(node.child1()).filter(PredictCell);
1305 forNode(nodeIndex).makeTop();
1306 break;
1307
1308 case PutByOffset:
1309 forNode(node.child1()).filter(PredictCell);
1310 break;
1311
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001312 case CheckFunction:
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001313 forNode(node.child1()).filter(PredictFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001314 // FIXME: Should be able to propagate the fact that we know what the function is.
1315 break;
1316
1317 case PutById:
1318 case PutByIdDirect:
1319 forNode(node.child1()).filter(PredictCell);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001320 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001321 break;
1322
1323 case GetGlobalVar:
1324 forNode(nodeIndex).makeTop();
1325 break;
1326
1327 case PutGlobalVar:
1328 break;
1329
1330 case CheckHasInstance:
1331 forNode(node.child1()).filter(PredictCell);
1332 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1333 break;
1334
1335 case InstanceOf:
1336 // Again, sadly, we don't propagate the fact that we've done InstanceOf
fpizlo@apple.com03c374f2011-11-19 01:00:34 +00001337 if (!(m_graph[node.child1()].prediction() & ~PredictCell) && !(forNode(node.child1()).m_type & ~PredictCell))
1338 forNode(node.child1()).filter(PredictCell);
1339 forNode(node.child3()).filter(PredictCell);
1340 forNode(nodeIndex).set(PredictBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001341 break;
1342
1343 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001344 case Flush:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001345 break;
1346
1347 case Breakpoint:
1348 break;
1349
1350 case Call:
1351 case Construct:
1352 case Resolve:
1353 case ResolveBase:
1354 case ResolveBaseStrictPut:
1355 case ResolveGlobal:
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001356 clobberStructures(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001357 forNode(nodeIndex).makeTop();
1358 break;
1359
1360 case ForceOSRExit:
1361 m_isValid = false;
1362 break;
1363
1364 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001365 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001366 case Nop:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001367 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001368
1369 case LastNodeType:
1370 ASSERT_NOT_REACHED();
1371 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001372 }
1373
1374 return m_isValid;
1375}
1376
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001377inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001378{
1379 PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING);
1380 if (!m_haveStructures)
1381 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001382 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001383 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001384 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i)
1385 m_variables.argument(i).clobberStructures();
1386 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i)
1387 m_variables.local(i).clobberStructures();
1388 m_haveStructures = false;
1389}
1390
1391inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1392{
1393 if (nodeIndex == NoNode)
1394 return false;
1395
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001396 AbstractValue source;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001397
1398 Node& node = m_graph[nodeIndex];
1399 if (!node.refCount())
1400 return false;
1401
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001402#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001403 dataLog(" It's live, node @%u.\n", nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001404#endif
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001405
1406 switch (node.op()) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001407 case Phi:
1408 case SetArgument:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001409 case Flush:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001410 // The block transfers the value from head to tail.
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001411 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001412#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001413 dataLog(" Transfering ");
1414 source.dump(WTF::dataFile());
1415 dataLog(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001416#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001417 break;
1418
1419 case GetLocal:
1420 // The block refines the value with additional speculations.
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001421 source = forNode(nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001422#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001423 dataLog(" Refining to ");
1424 source.dump(WTF::dataFile());
1425 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001426#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001427 break;
1428
1429 case SetLocal:
1430 // The block sets the variable, and potentially refines it, both
1431 // before and after setting it.
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001432 if (node.variableAccessData()->shouldUseDoubleFormat())
1433 source.set(PredictDouble);
1434 else
1435 source = forNode(node.child1());
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001436#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001437 dataLog(" Setting to ");
1438 source.dump(WTF::dataFile());
1439 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001440#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001441 break;
1442
1443 default:
1444 ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001445 break;
1446 }
1447
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001448 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001449 // Abstract execution did not change the output value of the variable, for this
1450 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001451#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001452 dataLog(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001453#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001454 return false;
1455 }
1456
1457 // Abstract execution reached a new conclusion about the speculations reached about
1458 // this variable after execution of this basic block. Update the state, and return
1459 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001460 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001461#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001462 dataLog(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001463#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001464 return true;
1465}
1466
1467inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1468{
1469 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1470 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1471
1472 bool changed = false;
1473
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001474 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1475 AbstractValue& destination = to->valuesAtHead.argument(argument);
fpizlo@apple.com1688cc12012-05-23 07:29:02 +00001476 NodeIndex nodeIndex = from->variablesAtTail.argument(argument);
1477 if (nodeIndex != NoNode && m_graph[nodeIndex].variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001478 if (destination.isTop())
1479 continue;
1480 destination.makeTop();
1481 changed = true;
1482 continue;
1483 }
1484 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1485 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001486
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001487 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1488 AbstractValue& destination = to->valuesAtHead.local(local);
fpizlo@apple.com1688cc12012-05-23 07:29:02 +00001489 NodeIndex nodeIndex = from->variablesAtTail.local(local);
1490 if (nodeIndex != NoNode && m_graph[nodeIndex].variableAccessData()->isCaptured()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001491 if (destination.isTop())
1492 continue;
1493 destination.makeTop();
1494 changed = true;
1495 continue;
1496 }
1497 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1498 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001499
1500 if (!to->cfaHasVisited)
1501 changed = true;
1502
1503 to->cfaShouldRevisit |= changed;
1504
1505 return changed;
1506}
1507
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001508inline bool AbstractState::mergeToSuccessors(
1509 Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001510{
1511 PROFILE(FLAG_FOR_MERGE_TO_SUCCESSORS);
1512
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001513 Node& terminal = graph[basicBlock->last()];
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001514
1515 ASSERT(terminal.isTerminal());
1516
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001517 switch (terminal.op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001518 case Jump: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001519 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001520#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1521 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1522#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001523 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001524 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001525
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001526 case Branch: {
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001527 ASSERT(branchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001528 bool changed = false;
1529#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1530 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1531#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001532 if (branchDirection != TakeFalse)
1533 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001534#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1535 dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1536#endif
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001537 if (branchDirection != TakeTrue)
1538 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001539 return changed;
1540 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001541
1542 case Return:
1543 case Throw:
1544 case ThrowReferenceError:
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001545 ASSERT(branchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001546 return false;
1547
1548 default:
1549 ASSERT_NOT_REACHED();
1550 return false;
1551 }
1552}
1553
1554inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1555{
1556 if (destinationNodeIndex == NoNode)
1557 return false;
1558
1559 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1560
1561 // FIXME: We could do some sparse conditional propagation here!
1562
1563 return destination.merge(source);
1564}
1565
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001566void AbstractState::dump(FILE* out)
1567{
1568 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001569 for (size_t i = 0; i < m_block->size(); ++i) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001570 NodeIndex index = m_block->at(i);
1571 AbstractValue& value = m_nodes[index];
1572 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001573 continue;
1574 if (first)
1575 first = false;
1576 else
1577 fprintf(out, " ");
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001578 fprintf(out, "@%lu:", static_cast<unsigned long>(index));
1579 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001580 }
1581}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001582
1583} } // namespace JSC::DFG
1584
1585#endif // ENABLE(DFG_JIT)
1586