blob: 65395fc9bd36242d471724f1367ca48df9dd009e [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) {
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +000065 if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000066 m_haveStructures = true;
67 break;
68 }
69 }
70 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +000071 if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000072 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);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000109 else if (isBooleanSpeculation(prediction))
110 root->valuesAtHead.argument(i).set(SpecBoolean);
fpizlo@apple.com00528432012-07-20 03:50:02 +0000111 else if (isCellSpeculation(prediction))
112 root->valuesAtHead.argument(i).set(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000113 else
114 root->valuesAtHead.argument(i).makeTop();
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000115
116 root->valuesAtTail.argument(i).clear();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000117 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000118 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000119 NodeIndex nodeIndex = root->variablesAtHead.local(i);
120 if (nodeIndex != NoNode && graph[nodeIndex].variableAccessData()->isCaptured())
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000121 root->valuesAtHead.local(i).makeTop();
122 else
123 root->valuesAtHead.local(i).clear();
124 root->valuesAtTail.local(i).clear();
125 }
126 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
127 BasicBlock* block = graph.m_blocks[blockIndex].get();
128 if (!block)
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000129 continue;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000130 if (!block->isReachable)
131 continue;
132 block->cfaShouldRevisit = false;
133 block->cfaHasVisited = false;
134 block->cfaFoundConstants = false;
135 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
136 block->valuesAtHead.argument(i).clear();
137 block->valuesAtTail.argument(i).clear();
138 }
139 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
140 block->valuesAtHead.local(i).clear();
141 block->valuesAtTail.local(i).clear();
142 }
fpizlo@apple.com0fd7ec92012-08-19 21:59:12 +0000143 if (!block->isOSRTarget)
144 continue;
145 if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
146 continue;
147 for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
148 AbstractValue value;
149 value.setMostSpecific(graph.m_mustHandleValues[i]);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +0000150 int operand = graph.m_mustHandleValues.operandForIndex(i);
151 block->valuesAtHead.operand(operand).merge(value);
152#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
153 dataLog(" Initializing Block #%u, operand r%d, to ", blockIndex, operand);
154 block->valuesAtHead.operand(operand).dump(WTF::dataFile());
155 dataLog("\n");
156#endif
fpizlo@apple.com0fd7ec92012-08-19 21:59:12 +0000157 }
158 block->cfaShouldRevisit = true;
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000159 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000160}
161
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000162bool AbstractState::endBasicBlock(MergeMode mergeMode)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000163{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000164 ASSERT(m_block);
165
166 BasicBlock* block = m_block; // Save the block for successor merging.
167
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000168 block->cfaFoundConstants = m_foundConstants;
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000169 block->cfaDidFinish = m_isValid;
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000170 block->cfaBranchDirection = m_branchDirection;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000171
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000172 if (!m_isValid) {
173 reset();
174 return false;
175 }
176
177 bool changed = false;
178
179 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000180 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
181#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000182 dataLog(" Merging state for argument %zu.\n", argument);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000183#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000184 AbstractValue& destination = block->valuesAtTail.argument(argument);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000185 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000186 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000187
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000188 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
189#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +0000190 dataLog(" Merging state for local %zu.\n", local);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000191#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000192 AbstractValue& destination = block->valuesAtTail.local(local);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000193 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000194 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000195 }
196
197 ASSERT(mergeMode != DontMerge || !changed);
198
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000199#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000200 dataLog(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000201#endif
202
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000203 reset();
204
205 if (mergeMode != MergeToSuccessors)
206 return changed;
207
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000208 return mergeToSuccessors(m_graph, block);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000209}
210
211void AbstractState::reset()
212{
213 m_block = 0;
214 m_isValid = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000215 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000216}
217
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000218AbstractState::BooleanResult AbstractState::booleanResult(Node& node, AbstractValue& value)
219{
220 JSValue childConst = value.value();
221 if (childConst) {
222 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec()))
223 return DefinitelyTrue;
224 return DefinitelyFalse;
225 }
226
227 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
228 if (isCellSpeculation(value.m_type)
229 && value.m_currentKnownStructure.hasSingleton()) {
230 Structure* structure = value.m_currentKnownStructure.singleton();
231 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
232 && structure->typeInfo().type() != StringType)
233 return DefinitelyTrue;
234 }
235
236 return UnknownBooleanResult;
237}
238
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000239bool AbstractState::execute(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000240{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000241 ASSERT(m_block);
242 ASSERT(m_isValid);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000243
244 m_didClobber = false;
245
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +0000246 NodeIndex nodeIndex = m_block->at(indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000247 Node& node = m_graph[nodeIndex];
248
249 if (!node.shouldGenerate())
250 return true;
251
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000252 switch (node.op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000253 case JSConstant:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +0000254 case WeakJSConstant:
255 case PhantomArguments: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000256 forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000257 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000258 break;
259 }
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000260
261 case Identity: {
262 forNode(nodeIndex) = forNode(node.child1());
263 node.setCanExit(false);
264 break;
265 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000266
267 case GetLocal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000268 VariableAccessData* variableAccessData = node.variableAccessData();
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000269 if (variableAccessData->prediction() == SpecNone) {
270 m_isValid = false;
271 node.setCanExit(true);
272 break;
273 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000274 bool canExit = false;
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000275 AbstractValue value = m_variables.operand(variableAccessData->local());
276 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000277 if (value.isClear())
278 canExit |= true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000279 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000280 if (value.value())
281 m_foundConstants = true;
282 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000283 node.setCanExit(canExit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000284 break;
285 }
286
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000287 case GetLocalUnlinked: {
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000288 AbstractValue value = m_variables.operand(node.unlinkedLocal());
289 if (value.value())
290 m_foundConstants = true;
291 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000292 node.setCanExit(false);
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000293 break;
294 }
295
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000296 case SetLocal: {
fpizlo@apple.com00528432012-07-20 03:50:02 +0000297 if (node.variableAccessData()->isCaptured()
298 || m_graph.isCreatedThisArgument(node.local())) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000299 m_variables.operand(node.local()) = forNode(node.child1());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000300 node.setCanExit(false);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000301 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000302 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000303
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000304 if (node.variableAccessData()->shouldUseDoubleFormat()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000305 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000306 m_variables.operand(node.local()).set(SpecDouble);
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000307 break;
308 }
309
fpizlo@apple.com62336162012-06-07 01:35:59 +0000310 SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
311 if (isInt32Speculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000312 speculateInt32Unary(node);
fpizlo@apple.comf24804c2012-08-15 02:48:35 +0000313 else if (isCellSpeculation(predictedType)) {
fpizlo@apple.com00528432012-07-20 03:50:02 +0000314 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
315 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000316 } else if (isBooleanSpeculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000317 speculateBooleanUnary(node);
318 else
319 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000320
321 m_variables.operand(node.local()) = forNode(node.child1());
322 break;
323 }
324
325 case SetArgument:
326 // Assert that the state of arguments has been set.
327 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000328 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000329 break;
330
331 case BitAnd:
332 case BitOr:
333 case BitXor:
334 case BitRShift:
335 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000336 case BitURShift: {
337 JSValue left = forNode(node.child1()).value();
338 JSValue right = forNode(node.child2()).value();
339 if (left && right && left.isInt32() && right.isInt32()) {
340 int32_t a = left.asInt32();
341 int32_t b = right.asInt32();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000342 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000343 switch (node.op()) {
344 case BitAnd:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000345 constantWasSet = trySetConstant(nodeIndex, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000346 break;
347 case BitOr:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000348 constantWasSet = trySetConstant(nodeIndex, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000349 break;
350 case BitXor:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000351 constantWasSet = trySetConstant(nodeIndex, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000352 break;
353 case BitRShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000354 constantWasSet = trySetConstant(nodeIndex, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000355 break;
356 case BitLShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000357 constantWasSet = trySetConstant(nodeIndex, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000358 break;
359 case BitURShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000360 constantWasSet = trySetConstant(nodeIndex, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000361 break;
362 default:
363 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000364 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000365 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000366 if (constantWasSet) {
367 m_foundConstants = true;
368 node.setCanExit(false);
369 break;
370 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000371 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000372 speculateInt32Binary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000373 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000374 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000375 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000376
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000377 case UInt32ToNumber: {
378 JSValue child = forNode(node.child1()).value();
379 if (child && child.isNumber()) {
380 ASSERT(child.isInt32());
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000381 if (trySetConstant(nodeIndex, JSValue(child.asUInt32()))) {
382 m_foundConstants = true;
383 node.setCanExit(false);
384 break;
385 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000386 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000387 if (!node.canSpeculateInteger()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000388 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000389 node.setCanExit(false);
390 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000391 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000392 node.setCanExit(true);
393 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000394 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000395 }
396
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000397
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000398 case DoubleAsInt32: {
399 JSValue child = forNode(node.child1()).value();
400 if (child && child.isNumber()) {
401 double asDouble = child.asNumber();
402 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000403 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
404 && trySetConstant(nodeIndex, JSValue(asInt))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000405 m_foundConstants = true;
406 break;
407 }
408 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000409 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000410 forNode(node.child1()).filter(SpecNumber);
411 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000412 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000413 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000414
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000415 case ValueToInt32: {
416 JSValue child = forNode(node.child1()).value();
417 if (child && child.isNumber()) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000418 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000419 if (child.isInt32())
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000420 constantWasSet = trySetConstant(nodeIndex, child);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000421 else
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000422 constantWasSet = trySetConstant(nodeIndex, JSValue(JSC::toInt32(child.asDouble())));
423 if (constantWasSet) {
424 m_foundConstants = true;
425 node.setCanExit(false);
426 break;
427 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000428 }
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000429 if (m_graph[node.child1()].shouldSpeculateInteger())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000430 speculateInt32Unary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000431 else if (m_graph[node.child1()].shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000432 speculateNumberUnary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000433 else if (m_graph[node.child1()].shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000434 speculateBooleanUnary(node);
435 else
436 node.setCanExit(false);
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000437
fpizlo@apple.com62336162012-06-07 01:35:59 +0000438 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000439 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000440 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000441
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000442 case Int32ToDouble: {
443 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000444 if (child && child.isNumber()
445 && trySetConstant(nodeIndex, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000446 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000447 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000448 break;
449 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000450 speculateNumberUnary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000451 if (isInt32Speculation(forNode(node.child1()).m_type))
452 forNode(nodeIndex).set(SpecDoubleReal);
453 else
454 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000455 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000456 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000457
458 case CheckNumber:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000459 forNode(node.child1()).filter(SpecNumber);
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000460 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000461
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000462 case ValueAdd:
463 case ArithAdd: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000464 JSValue left = forNode(node.child1()).value();
465 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000466 if (left && right && left.isNumber() && right.isNumber()
467 && trySetConstant(nodeIndex, JSValue(left.asNumber() + right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000468 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000469 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000470 break;
471 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000472 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000473 speculateInt32Binary(
474 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000475 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000476 break;
477 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000478 if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000479 speculateNumberBinary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000480 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
481 && isRealNumberSpeculation(forNode(node.child2()).m_type))
482 forNode(nodeIndex).set(SpecDoubleReal);
483 else
484 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000485 break;
486 }
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000487 if (node.op() == ValueAdd) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000488 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000489 forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000490 node.setCanExit(false);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000491 break;
492 }
493 // We don't handle this yet. :-(
494 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000495 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000496 break;
497 }
498
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000499 case ArithSub: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000500 JSValue left = forNode(node.child1()).value();
501 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000502 if (left && right && left.isNumber() && right.isNumber()
503 && trySetConstant(nodeIndex, JSValue(left.asNumber() - right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000504 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000505 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000506 break;
507 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000508 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000509 speculateInt32Binary(
510 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000511 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000512 break;
513 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000514 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000515 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000516 break;
517 }
518
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000519 case ArithNegate: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000520 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000521 if (child && child.isNumber()
522 && trySetConstant(nodeIndex, JSValue(-child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000523 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000524 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000525 break;
526 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000527 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000528 speculateInt32Unary(
529 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000530 forNode(nodeIndex).set(SpecInt32);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000531 break;
532 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000533 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000534 forNode(nodeIndex).set(SpecDouble);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000535 break;
536 }
537
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000538 case ArithMul: {
539 JSValue left = forNode(node.child1()).value();
540 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000541 if (left && right && left.isNumber() && right.isNumber()
542 && trySetConstant(nodeIndex, JSValue(left.asNumber() * right.asNumber()))) {
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000543 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000544 node.setCanExit(false);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000545 break;
546 }
547 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000548 speculateInt32Binary(
549 node,
550 !nodeCanTruncateInteger(node.arithNodeFlags())
551 || !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000552 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000553 break;
554 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000555 speculateNumberBinary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000556 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
557 || isRealNumberSpeculation(forNode(node.child2()).m_type))
558 forNode(nodeIndex).set(SpecDoubleReal);
559 else
560 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000561 break;
562 }
563
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000564 case ArithDiv:
565 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000566 case ArithMax:
567 case ArithMod: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000568 JSValue left = forNode(node.child1()).value();
569 JSValue right = forNode(node.child2()).value();
570 if (left && right && left.isNumber() && right.isNumber()) {
571 double a = left.asNumber();
572 double b = right.asNumber();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000573 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000574 switch (node.op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000575 case ArithDiv:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000576 constantWasSet = trySetConstant(nodeIndex, JSValue(a / b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000577 break;
578 case ArithMin:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000579 constantWasSet = trySetConstant(nodeIndex, JSValue(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000580 break;
581 case ArithMax:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000582 constantWasSet = trySetConstant(nodeIndex, JSValue(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000583 break;
584 case ArithMod:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000585 constantWasSet = trySetConstant(nodeIndex, JSValue(fmod(a, b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000586 break;
587 default:
588 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000589 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000590 break;
591 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000592 if (constantWasSet) {
593 m_foundConstants = true;
594 node.setCanExit(false);
595 break;
596 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000597 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000598 if (Node::shouldSpeculateIntegerForArithmetic(
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000599 m_graph[node.child1()], m_graph[node.child2()])
600 && node.canSpeculateInteger()) {
601 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
fpizlo@apple.com62336162012-06-07 01:35:59 +0000602 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000603 break;
604 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000605 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000606 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000607 break;
608 }
609
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000610 case ArithAbs: {
611 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000612 if (child && child.isNumber()
613 && trySetConstant(nodeIndex, JSValue(fabs(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000614 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000615 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000616 break;
617 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000618 if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000619 && node.canSpeculateInteger()) {
620 speculateInt32Unary(node, true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000621 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000622 break;
623 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000624 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000625 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000626 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000627 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000628
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000629 case ArithSqrt: {
630 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000631 if (child && child.isNumber()
632 && trySetConstant(nodeIndex, JSValue(sqrt(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000633 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000634 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000635 break;
636 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000637 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000638 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000639 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000640 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000641
642 case LogicalNot: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000643 bool didSetConstant = false;
644 switch (booleanResult(node, forNode(node.child1()))) {
645 case DefinitelyTrue:
646 didSetConstant = trySetConstant(nodeIndex, jsBoolean(false));
647 break;
648 case DefinitelyFalse:
649 didSetConstant = trySetConstant(nodeIndex, jsBoolean(true));
650 break;
651 default:
652 break;
653 }
654 if (didSetConstant) {
fpizlo@apple.com152abff2012-06-19 23:10:12 +0000655 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000656 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000657 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000658 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000659 Node& child = m_graph[node.child1()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000660 if (isBooleanSpeculation(child.prediction()))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000661 speculateBooleanUnary(node);
mhahnenberg@apple.comdb8065f2012-09-04 18:46:21 +0000662 else if (child.shouldSpeculateNonStringCellOrOther()) {
663 node.setCanExit(true);
664 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000665 } else if (child.shouldSpeculateInteger())
666 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000667 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000668 speculateNumberUnary(node);
669 else
670 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000671 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000672 break;
673 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000674
675 case IsUndefined:
676 case IsBoolean:
677 case IsNumber:
678 case IsString:
679 case IsObject:
680 case IsFunction: {
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000681 node.setCanExit(node.op() == IsUndefined && m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000682 JSValue child = forNode(node.child1()).value();
683 if (child) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000684 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000685 switch (node.op()) {
686 case IsUndefined:
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000687 if (m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
688 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
689 child.isCell()
690 ? false
691 : child.isUndefined()));
692 } else {
693 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
694 child.isCell()
695 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
696 : child.isUndefined()));
697 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000698 break;
699 case IsBoolean:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000700 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000701 break;
702 case IsNumber:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000703 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000704 break;
705 case IsString:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000706 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000707 break;
708 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000709 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000710 break;
711 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000712 if (constantWasSet) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000713 m_foundConstants = true;
714 break;
715 }
716 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000717 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000718 break;
719 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000720
721 case CompareLess:
722 case CompareLessEq:
723 case CompareGreater:
724 case CompareGreaterEq:
725 case CompareEq: {
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000726 bool constantWasSet = false;
727
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000728 JSValue leftConst = forNode(node.child1()).value();
729 JSValue rightConst = forNode(node.child2()).value();
730 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
731 double a = leftConst.asNumber();
732 double b = rightConst.asNumber();
733 switch (node.op()) {
734 case CompareLess:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000735 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000736 break;
737 case CompareLessEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000738 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a <= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000739 break;
740 case CompareGreater:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000741 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a > b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000742 break;
743 case CompareGreaterEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000744 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a >= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000745 break;
746 case CompareEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000747 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a == b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000748 break;
749 default:
750 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000751 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000752 break;
753 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000754 }
755
756 if (!constantWasSet && node.op() == CompareEq) {
757 SpeculatedType leftType = forNode(node.child1()).m_type;
758 SpeculatedType rightType = forNode(node.child2()).m_type;
759 if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
760 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
761 constantWasSet = trySetConstant(nodeIndex, jsBoolean(false));
762 }
763
764 if (constantWasSet) {
765 m_foundConstants = true;
766 node.setCanExit(false);
767 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000768 }
769
fpizlo@apple.com62336162012-06-07 01:35:59 +0000770 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000771
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000772 Node& left = m_graph[node.child1()];
773 Node& right = m_graph[node.child2()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000774 SpeculatedType filter;
775 SpeculatedTypeChecker checker;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000776 if (Node::shouldSpeculateInteger(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000777 filter = SpecInt32;
778 checker = isInt32Speculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000779 } else if (Node::shouldSpeculateNumber(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000780 filter = SpecNumber;
781 checker = isNumberSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000782 } else if (node.op() == CompareEq) {
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000783 if ((m_graph.isConstant(node.child1().index())
784 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
785 || (m_graph.isConstant(node.child2().index())
786 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000787 // We can exit if we haven't fired the MasqueradesAsUndefind watchpoint yet.
788 node.setCanExit(m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000789 break;
790 }
791
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000792 if (left.shouldSpeculateString() || right.shouldSpeculateString()) {
793 node.setCanExit(false);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000794 break;
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000795 }
796 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCellOrOther()) {
797 node.setCanExit(true);
798 forNode(node.child1()).filter(SpecCell & ~SpecString);
799 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000800 break;
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000801 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000802 if (left.shouldSpeculateNonStringCellOrOther() && right.shouldSpeculateNonStringCell()) {
803 node.setCanExit(true);
804 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
805 forNode(node.child2()).filter(SpecCell & ~SpecString);
806 break;
807 }
808 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCell()) {
809 node.setCanExit(true);
810 forNode(node.child1()).filter(SpecCell & ~SpecString);
811 forNode(node.child2()).filter(SpecCell & ~SpecString);
812 break;
813 }
814
815 filter = SpecTop;
816 checker = isAnySpeculation;
817 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000818 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000819 filter = SpecTop;
820 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000821 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000822 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000823 node.setCanExit(
824 !checker(forNode(node.child1()).m_type)
825 || !checker(forNode(node.child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000826 forNode(node.child1()).filter(filter);
827 forNode(node.child2()).filter(filter);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000828 break;
829 }
830
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000831 case CompareStrictEq: {
832 JSValue left = forNode(node.child1()).value();
833 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000834 if (left && right && left.isNumber() && right.isNumber()
835 && trySetConstant(nodeIndex, jsBoolean(left.asNumber() == right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000836 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000837 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000838 break;
839 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000840 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000841 if (m_graph.isJSConstant(node.child1().index())) {
842 JSValue value = m_graph.valueOfJSConstant(node.child1().index());
843 if (!value.isNumber() && !value.isString()) {
844 node.setCanExit(false);
845 break;
846 }
847 }
848 if (m_graph.isJSConstant(node.child2().index())) {
849 JSValue value = m_graph.valueOfJSConstant(node.child2().index());
850 if (!value.isNumber() && !value.isString()) {
851 node.setCanExit(false);
852 break;
853 }
854 }
855 if (Node::shouldSpeculateInteger(
856 m_graph[node.child1()], m_graph[node.child2()])) {
857 speculateInt32Binary(node);
858 break;
859 }
860 if (Node::shouldSpeculateNumber(
861 m_graph[node.child1()], m_graph[node.child2()])) {
862 speculateNumberBinary(node);
863 break;
864 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000865 Node& leftNode = m_graph[node.child1()];
866 Node& rightNode = m_graph[node.child2()];
867 if (leftNode.shouldSpeculateString() || rightNode.shouldSpeculateString()) {
868 node.setCanExit(false);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000869 break;
870 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000871 if (leftNode.shouldSpeculateNonStringCell() && rightNode.shouldSpeculateNonStringCell()) {
872 node.setCanExit(true);
873 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
874 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000875 break;
876 }
877 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000878 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000879 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000880
881 case StringCharCodeAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000882 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000883 forNode(node.child1()).filter(SpecString);
884 forNode(node.child2()).filter(SpecInt32);
885 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000886 break;
887
888 case StringCharAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000889 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000890 forNode(node.child1()).filter(SpecString);
891 forNode(node.child2()).filter(SpecInt32);
892 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000893 break;
894
895 case GetByVal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000896 node.setCanExit(true);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000897 switch (node.arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +0000898 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +0000899 case Array::Unprofiled:
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000900 case Array::Undecided:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000901 ASSERT_NOT_REACHED();
902 break;
903 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000904 m_isValid = false;
905 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000906 case Array::Generic:
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000907 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000908 forNode(nodeIndex).makeTop();
909 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000910 case Array::String:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000911 forNode(node.child2()).filter(SpecInt32);
912 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000913 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000914 case Array::Arguments:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000915 forNode(node.child2()).filter(SpecInt32);
916 forNode(nodeIndex).makeTop();
917 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000918 case Array::Int32:
919 forNode(node.child2()).filter(SpecInt32);
920 if (node.arrayMode().isOutOfBounds()) {
921 clobberWorld(node.codeOrigin, indexInBlock);
922 forNode(nodeIndex).makeTop();
923 } else
924 forNode(nodeIndex).set(SpecInt32);
925 break;
926 case Array::Double:
927 forNode(node.child2()).filter(SpecInt32);
928 if (node.arrayMode().isOutOfBounds()) {
929 clobberWorld(node.codeOrigin, indexInBlock);
930 forNode(nodeIndex).makeTop();
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000931 } else if (node.arrayMode().isSaneChain())
932 forNode(nodeIndex).set(SpecDouble);
933 else
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000934 forNode(nodeIndex).set(SpecDoubleReal);
935 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000936 case Array::Contiguous:
937 case Array::ArrayStorage:
938 case Array::SlowPutArrayStorage:
fpizlo@apple.com163e4772012-09-04 21:15:02 +0000939 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000940 if (node.arrayMode().isOutOfBounds())
941 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +0000942 forNode(nodeIndex).makeTop();
943 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000944 case Array::Int8Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000945 forNode(node.child2()).filter(SpecInt32);
946 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000947 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000948 case Array::Int16Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000949 forNode(node.child2()).filter(SpecInt32);
950 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000951 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000952 case Array::Int32Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000953 forNode(node.child2()).filter(SpecInt32);
954 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000955 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000956 case Array::Uint8Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000957 forNode(node.child2()).filter(SpecInt32);
958 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000959 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000960 case Array::Uint8ClampedArray:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000961 forNode(node.child2()).filter(SpecInt32);
962 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000963 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000964 case Array::Uint16Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000965 forNode(node.child2()).filter(SpecInt32);
966 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000967 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000968 case Array::Uint32Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000969 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000970 if (node.shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000971 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000972 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000973 forNode(nodeIndex).set(SpecDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000974 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000975 case Array::Float32Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000976 forNode(node.child2()).filter(SpecInt32);
977 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000978 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000979 case Array::Float64Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000980 forNode(node.child2()).filter(SpecInt32);
981 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000982 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000983 default:
984 ASSERT_NOT_REACHED();
985 break;
oliver@apple.com07d75732011-12-03 01:47:27 +0000986 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000987 break;
988 }
989
990 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000991 case PutByValAlias: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000992 node.setCanExit(true);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000993 Edge child1 = m_graph.varArgChild(node, 0);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000994 Edge child2 = m_graph.varArgChild(node, 1);
995 Edge child3 = m_graph.varArgChild(node, 2);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000996 switch (node.arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000997 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000998 m_isValid = false;
999 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001000 case Array::Generic:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001001 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001002 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001003 case Array::Int32:
1004 forNode(child1).filter(SpecCell);
1005 forNode(child2).filter(SpecInt32);
1006 forNode(child3).filter(SpecInt32);
1007 if (node.arrayMode().isOutOfBounds())
1008 clobberWorld(node.codeOrigin, indexInBlock);
1009 break;
1010 case Array::Double:
1011 forNode(child1).filter(SpecCell);
1012 forNode(child2).filter(SpecInt32);
1013 forNode(child3).filter(SpecRealNumber);
1014 if (node.arrayMode().isOutOfBounds())
1015 clobberWorld(node.codeOrigin, indexInBlock);
1016 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001017 case Array::Contiguous:
1018 case Array::ArrayStorage:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001019 forNode(child1).filter(SpecCell);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001020 forNode(child2).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001021 if (node.arrayMode().isOutOfBounds())
1022 clobberWorld(node.codeOrigin, indexInBlock);
1023 break;
1024 case Array::SlowPutArrayStorage:
1025 forNode(child1).filter(SpecCell);
1026 forNode(child2).filter(SpecInt32);
1027 if (node.arrayMode().mayStoreToHole())
1028 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001029 break;
1030 case Array::Arguments:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001031 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001032 forNode(child2).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001033 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001034 case Array::Int8Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001035 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001036 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;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001042 case Array::Int16Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001043 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001044 forNode(child2).filter(SpecInt32);
1045 if (m_graph[child3].shouldSpeculateInteger())
1046 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001047 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001048 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001049 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001050 case Array::Int32Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001051 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001052 forNode(child2).filter(SpecInt32);
1053 if (m_graph[child3].shouldSpeculateInteger())
1054 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001055 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001056 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001057 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001058 case Array::Uint8Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001059 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001060 forNode(child2).filter(SpecInt32);
1061 if (m_graph[child3].shouldSpeculateInteger())
1062 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001063 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001064 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001065 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001066 case Array::Uint8ClampedArray:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001067 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001068 forNode(child2).filter(SpecInt32);
1069 if (m_graph[child3].shouldSpeculateInteger())
1070 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001071 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001072 forNode(child3).filter(SpecNumber);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001073 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001074 case Array::Uint16Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001075 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001076 forNode(child2).filter(SpecInt32);
1077 if (m_graph[child3].shouldSpeculateInteger())
1078 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001079 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001080 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001081 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001082 case Array::Uint32Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001083 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001084 forNode(child2).filter(SpecInt32);
1085 if (m_graph[child3].shouldSpeculateInteger())
1086 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001087 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001088 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001089 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001090 case Array::Float32Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001091 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001092 forNode(child2).filter(SpecInt32);
1093 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001094 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001095 case Array::Float64Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001096 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001097 forNode(child2).filter(SpecInt32);
1098 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001099 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001100 default:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001101 CRASH();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001102 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001103 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001104 break;
1105 }
1106
1107 case ArrayPush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001108 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001109 switch (node.arrayMode().type()) {
1110 case Array::Int32:
1111 forNode(node.child2()).filter(SpecInt32);
1112 break;
1113 case Array::Double:
1114 forNode(node.child2()).filter(SpecRealNumber);
1115 break;
1116 default:
1117 break;
1118 }
fpizlo@apple.come0480cf2012-09-26 02:56:19 +00001119 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001120 forNode(nodeIndex).set(SpecNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001121 break;
1122
1123 case ArrayPop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001124 node.setCanExit(true);
fpizlo@apple.come0480cf2012-09-26 02:56:19 +00001125 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001126 forNode(nodeIndex).makeTop();
1127 break;
1128
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001129 case RegExpExec:
1130 case RegExpTest:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001131 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001132 !isCellSpeculation(forNode(node.child1()).m_type)
1133 || !isCellSpeculation(forNode(node.child2()).m_type));
1134 forNode(node.child1()).filter(SpecCell);
1135 forNode(node.child2()).filter(SpecCell);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001136 forNode(nodeIndex).makeTop();
1137 break;
1138
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001139 case Jump:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001140 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001141 break;
1142
1143 case Branch: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001144 BooleanResult result = booleanResult(node, forNode(node.child1()));
1145 if (result == DefinitelyTrue) {
1146 m_branchDirection = TakeTrue;
1147 node.setCanExit(false);
1148 break;
1149 }
1150 if (result == DefinitelyFalse) {
1151 m_branchDirection = TakeFalse;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001152 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001153 break;
1154 }
1155 // FIXME: The above handles the trivial cases of sparse conditional
1156 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001157 // We can specialize the source variable's value on each direction of
1158 // the branch.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001159 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +00001160 if (child.shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001161 speculateBooleanUnary(node);
mhahnenberg@apple.comc1925152012-09-01 00:38:37 +00001162 else if (child.shouldSpeculateNonStringCellOrOther()) {
1163 node.setCanExit(true);
1164 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001165 } else if (child.shouldSpeculateInteger())
1166 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001167 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001168 speculateNumberUnary(node);
1169 else
1170 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001171 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001172 break;
1173 }
1174
1175 case Return:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001176 m_isValid = false;
1177 node.setCanExit(false);
1178 break;
1179
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001180 case Throw:
1181 case ThrowReferenceError:
1182 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001183 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001184 break;
1185
1186 case ToPrimitive: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001187 JSValue childConst = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +00001188 if (childConst && childConst.isNumber() && trySetConstant(nodeIndex, childConst)) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001189 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001190 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001191 break;
1192 }
1193
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001194 Node& child = m_graph[node.child1()];
1195 if (child.shouldSpeculateInteger()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001196 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001197 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001198 break;
1199 }
1200
1201 AbstractValue& source = forNode(node.child1());
1202 AbstractValue& destination = forNode(nodeIndex);
1203
fpizlo@apple.com62336162012-06-07 01:35:59 +00001204 SpeculatedType type = source.m_type;
1205 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1206 type &= (SpecNumber | SpecString | SpecBoolean);
1207 type |= SpecString;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001208 }
1209 destination.set(type);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001210 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001211 break;
1212 }
1213
1214 case StrCat:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001215 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001216 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001217 break;
1218
1219 case NewArray:
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001220 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001221 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001222 m_haveStructures = true;
1223 break;
1224
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001225 case NewArrayBuffer:
fpizlo@apple.com68677de2012-10-11 19:36:04 +00001226 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001227 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
fpizlo@apple.com68677de2012-10-11 19:36:04 +00001228 m_haveStructures = true;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001229 break;
1230
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001231 case NewArrayWithSize:
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001232 node.setCanExit(true);
1233 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com1bc68482012-10-13 03:56:09 +00001234 forNode(nodeIndex).set(SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001235 m_haveStructures = true;
1236 break;
1237
1238 case NewRegexp:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001239 node.setCanExit(false);
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001240 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001241 m_haveStructures = true;
1242 break;
1243
1244 case ConvertThis: {
1245 Node& child = m_graph[node.child1()];
1246 AbstractValue& source = forNode(node.child1());
1247 AbstractValue& destination = forNode(nodeIndex);
1248
fpizlo@apple.com62336162012-06-07 01:35:59 +00001249 if (isObjectSpeculation(source.m_type)) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001250 // This is the simple case. We already know that the source is an
1251 // object, so there's nothing to do. I don't think this case will
1252 // be hit, but then again, you never know.
1253 destination = source;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001254 node.setCanExit(false);
fpizlo@apple.com5d271712012-11-16 06:19:54 +00001255 m_foundConstants = true; // Tell the constant folder to turn this into Identity.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001256 break;
1257 }
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001258
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001259 node.setCanExit(true);
1260
fpizlo@apple.com62336162012-06-07 01:35:59 +00001261 if (isOtherSpeculation(child.prediction())) {
1262 source.filter(SpecOther);
1263 destination.set(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001264 break;
1265 }
1266
fpizlo@apple.com62336162012-06-07 01:35:59 +00001267 if (isObjectSpeculation(child.prediction())) {
1268 source.filter(SpecObjectMask);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001269 destination = source;
1270 break;
1271 }
1272
1273 destination = source;
fpizlo@apple.com62336162012-06-07 01:35:59 +00001274 destination.merge(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001275 break;
1276 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001277
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001278 case CreateThis: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001279 AbstractValue& source = forNode(node.child1());
1280 AbstractValue& destination = forNode(nodeIndex);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001281
fpizlo@apple.com62336162012-06-07 01:35:59 +00001282 node.setCanExit(!isCellSpeculation(source.m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001283
fpizlo@apple.com62336162012-06-07 01:35:59 +00001284 source.filter(SpecFunction);
1285 destination.set(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001286 break;
1287 }
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001288
1289 case InheritorIDWatchpoint:
1290 node.setCanExit(true);
1291 break;
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001292
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001293 case NewObject:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001294 node.setCanExit(false);
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001295 forNode(nodeIndex).set(node.structure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001296 m_haveStructures = true;
1297 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001298
1299 case CreateActivation:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001300 node.setCanExit(false);
ggaren@apple.com70aed692012-09-01 00:46:58 +00001301 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->activationStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001302 m_haveStructures = true;
1303 break;
1304
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001305 case CreateArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001306 node.setCanExit(false);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001307 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1308 m_haveStructures = true;
1309 break;
1310
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001311 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001312 case TearOffArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001313 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001314 // Does nothing that is user-visible.
1315 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001316
1317 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001318 if (isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001319 m_variables.operand(
fpizlo@apple.comb80bc2a32012-06-02 22:58:48 +00001320 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
1321 node.setCanExit(false);
1322 m_foundConstants = true;
1323 } else
1324 node.setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001325 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001326
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001327 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001328 // We know that this executable does not escape its arguments, so we can optimize
1329 // the arguments a bit. Note that this is not sufficient to force constant folding
1330 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1331 // We perform further optimizations on this later on.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001332 if (node.codeOrigin.inlineCallFrame)
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001333 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001334 else
fpizlo@apple.com62336162012-06-07 01:35:59 +00001335 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001336 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001337 !isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001338 m_variables.operand(
1339 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001340 break;
1341
1342 case GetMyArgumentsLengthSafe:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001343 node.setCanExit(false);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001344 // This potentially clobbers all structures if the arguments object had a getter
1345 // installed on the length property.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001346 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001347 // We currently make no guarantee about what this returns because it does not
1348 // speculate that the length property is actually a length.
1349 forNode(nodeIndex).makeTop();
1350 break;
1351
1352 case GetMyArgumentByVal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001353 node.setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001354 // We know that this executable does not escape its arguments, so we can optimize
1355 // the arguments a bit. Note that this ends up being further optimized by the
1356 // ArgumentsSimplificationPhase.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001357 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001358 forNode(nodeIndex).makeTop();
1359 break;
1360
1361 case GetMyArgumentByValSafe:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001362 node.setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001363 // This potentially clobbers all structures if the property we're accessing has
1364 // a getter. We don't speculate against this.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001365 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001366 // But we do speculate that the index is an integer.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001367 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001368 // And the result is unknown.
1369 forNode(nodeIndex).makeTop();
1370 break;
1371
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001372 case NewFunction:
1373 case NewFunctionExpression:
1374 case NewFunctionNoCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001375 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001376 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1377 break;
1378
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001379 case GetCallee:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001380 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001381 forNode(nodeIndex).set(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001382 break;
1383
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001384 case GetScope:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001385 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001386 forNode(nodeIndex).set(SpecCellOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001387 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001388
1389 case GetScopeRegisters:
1390 node.setCanExit(false);
1391 forNode(node.child1()).filter(SpecCell);
1392 forNode(nodeIndex).clear(); // The result is not a JS value.
1393 break;
1394
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001395 case GetScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001396 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001397 forNode(nodeIndex).makeTop();
1398 break;
1399
1400 case PutScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001401 node.setCanExit(false);
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001402 clobberCapturedVars(node.codeOrigin);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001403 break;
1404
1405 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001406 case GetByIdFlush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001407 node.setCanExit(true);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001408 if (!node.prediction()) {
1409 m_isValid = false;
1410 break;
1411 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001412 if (isCellSpeculation(m_graph[node.child1()].prediction()))
1413 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001414 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001415 forNode(nodeIndex).makeTop();
1416 break;
1417
1418 case GetArrayLength:
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001419 node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
1420 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001421 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001422
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001423 case CheckStructure:
1424 case ForwardCheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001425 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001426 AbstractValue& value = forNode(node.child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001427 // If this structure check is attempting to prove knowledge already held in
1428 // the futurePossibleStructure set then the constant folding phase should
1429 // turn this into a watchpoint instead.
1430 StructureSet& set = node.structureSet();
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001431 if (value.m_futurePossibleStructure.isSubsetOf(set)
1432 || value.m_currentKnownStructure.isSubsetOf(set))
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001433 m_foundConstants = true;
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001434 node.setCanExit(
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001435 !value.m_currentKnownStructure.isSubsetOf(set)
fpizlo@apple.com62336162012-06-07 01:35:59 +00001436 || !isCellSpeculation(value.m_type));
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001437 value.filter(set);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001438 m_haveStructures = true;
1439 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001440 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001441
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001442 case StructureTransitionWatchpoint:
1443 case ForwardStructureTransitionWatchpoint: {
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001444 AbstractValue& value = forNode(node.child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001445
1446 // It's only valid to issue a structure transition watchpoint if we already
1447 // know that the watchpoint covers a superset of the structures known to
1448 // belong to the set of future structures that this value may have.
1449 // Currently, we only issue singleton watchpoints (that check one structure)
1450 // and our futurePossibleStructure set can only contain zero, one, or an
1451 // infinity of structures.
1452 ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node.structure())));
1453
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00001454 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 +00001455 value.filter(node.structure());
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001456 m_haveStructures = true;
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001457 node.setCanExit(true);
1458 break;
1459 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001460
1461 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001462 case PhantomPutStructure:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001463 node.setCanExit(false);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00001464 if (!forNode(node.child1()).m_currentKnownStructure.isClear()) {
1465 clobberStructures(indexInBlock);
1466 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1467 m_haveStructures = true;
1468 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001469 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00001470 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00001471 case AllocatePropertyStorage:
1472 case ReallocatePropertyStorage:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001473 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001474 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001475 forNode(nodeIndex).clear(); // The result is not a JS value.
1476 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001477 case CheckArray: {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001478 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001479 m_foundConstants = true;
1480 node.setCanExit(false);
1481 break;
1482 }
1483 node.setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001484 switch (node.arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001485 case Array::String:
1486 forNode(node.child1()).filter(SpecString);
1487 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001488 case Array::Int32:
1489 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001490 case Array::Contiguous:
1491 case Array::ArrayStorage:
1492 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001493 forNode(node.child1()).filter(SpecCell);
1494 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001495 case Array::Arguments:
1496 forNode(node.child1()).filter(SpecArguments);
1497 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001498 case Array::Int8Array:
1499 forNode(node.child1()).filter(SpecInt8Array);
1500 break;
1501 case Array::Int16Array:
1502 forNode(node.child1()).filter(SpecInt16Array);
1503 break;
1504 case Array::Int32Array:
1505 forNode(node.child1()).filter(SpecInt32Array);
1506 break;
1507 case Array::Uint8Array:
1508 forNode(node.child1()).filter(SpecUint8Array);
1509 break;
1510 case Array::Uint8ClampedArray:
1511 forNode(node.child1()).filter(SpecUint8ClampedArray);
1512 break;
1513 case Array::Uint16Array:
1514 forNode(node.child1()).filter(SpecUint16Array);
1515 break;
1516 case Array::Uint32Array:
1517 forNode(node.child1()).filter(SpecUint32Array);
1518 break;
1519 case Array::Float32Array:
1520 forNode(node.child1()).filter(SpecFloat32Array);
1521 break;
1522 case Array::Float64Array:
1523 forNode(node.child1()).filter(SpecFloat64Array);
1524 break;
1525 default:
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001526 ASSERT_NOT_REACHED();
1527 break;
1528 }
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001529 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.comf08803e2012-10-26 01:57:07 +00001530 m_haveStructures = true;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001531 break;
1532 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001533 case Arrayify: {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001534 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00001535 m_foundConstants = true;
1536 node.setCanExit(false);
1537 break;
1538 }
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001539 ASSERT(node.arrayMode().conversion() == Array::Convert);
1540 node.setCanExit(true);
1541 forNode(node.child1()).filter(SpecCell);
1542 if (node.child2())
1543 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001544 clobberStructures(indexInBlock);
1545 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
1546 m_haveStructures = true;
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001547 break;
1548 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001549 case ArrayifyToStructure: {
1550 AbstractValue& value = forNode(node.child1());
1551 StructureSet set = node.structure();
1552 if (value.m_futurePossibleStructure.isSubsetOf(set)
1553 || value.m_currentKnownStructure.isSubsetOf(set))
1554 m_foundConstants = true;
1555 node.setCanExit(true);
1556 clobberStructures(indexInBlock);
1557 value.filter(set);
1558 m_haveStructures = true;
1559 break;
1560 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001561 case GetIndexedPropertyStorage: {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001562 switch (node.arrayMode().type()) {
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001563 case Array::String:
1564 // Strings are weird - we may spec fail if the string was a rope. That is of course
1565 // stupid, and we should fix that, but for now let's at least be honest about it.
1566 node.setCanExit(true);
1567 break;
1568 default:
1569 node.setCanExit(false);
1570 break;
1571 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001572 forNode(nodeIndex).clear();
1573 break;
1574 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001575 case GetByOffset:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001576 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001577 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001578 forNode(nodeIndex).makeTop();
1579 break;
1580
1581 case PutByOffset:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001582 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001583 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001584 break;
1585
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001586 case CheckFunction: {
1587 JSValue value = forNode(node.child1()).value();
1588 if (value == node.function()) {
1589 m_foundConstants = true;
1590 ASSERT(value);
1591 node.setCanExit(false);
1592 break;
1593 }
1594
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001595 node.setCanExit(true); // Lies! We can do better.
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001596 if (!forNode(node.child1()).filterByValue(node.function())) {
1597 m_isValid = false;
1598 break;
1599 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001600 break;
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001601 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001602
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001603 case PutById:
1604 case PutByIdDirect:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001605 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001606 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001607 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001608 break;
1609
1610 case GetGlobalVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001611 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001612 forNode(nodeIndex).makeTop();
1613 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001614
1615 case GlobalVarWatchpoint:
1616 node.setCanExit(true);
1617 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001618
1619 case PutGlobalVar:
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001620 case PutGlobalVarCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001621 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001622 break;
1623
1624 case CheckHasInstance:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001625 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001626 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001627 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1628 break;
1629
1630 case InstanceOf:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001631 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001632 // Again, sadly, we don't propagate the fact that we've done InstanceOf
fpizlo@apple.com62336162012-06-07 01:35:59 +00001633 if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
1634 forNode(node.child1()).filter(SpecCell);
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001635 forNode(node.child2()).filter(SpecCell);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001636 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001637 break;
1638
1639 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001640 case Flush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001641 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001642 break;
1643
1644 case Breakpoint:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001645 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001646 break;
1647
1648 case Call:
1649 case Construct:
1650 case Resolve:
1651 case ResolveBase:
1652 case ResolveBaseStrictPut:
1653 case ResolveGlobal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001654 node.setCanExit(true);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001655 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001656 forNode(nodeIndex).makeTop();
1657 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001658
1659 case GarbageValue:
1660 clobberWorld(node.codeOrigin, indexInBlock);
1661 forNode(nodeIndex).makeTop();
1662 break;
1663
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001664 case ForceOSRExit:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001665 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001666 m_isValid = false;
1667 break;
1668
1669 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001670 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001671 case Nop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001672 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001673 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001674
1675 case LastNodeType:
1676 ASSERT_NOT_REACHED();
1677 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001678 }
1679
1680 return m_isValid;
1681}
1682
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001683inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1684{
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001685 clobberCapturedVars(codeOrigin);
1686 clobberStructures(indexInBlock);
1687}
1688
1689inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin)
1690{
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001691 if (codeOrigin.inlineCallFrame) {
1692 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1693 for (size_t i = capturedVars.size(); i--;) {
1694 if (!capturedVars.quickGet(i))
1695 continue;
1696 m_variables.local(i).makeTop();
1697 }
1698 } else {
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001699 for (size_t i = m_codeBlock->m_numVars; i--;) {
1700 if (m_codeBlock->isCaptured(i))
1701 m_variables.local(i).makeTop();
1702 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001703 }
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001704
1705 for (size_t i = m_variables.numberOfArguments(); i--;) {
1706 if (m_codeBlock->isCaptured(argumentToOperand(i)))
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001707 m_variables.argument(i).makeTop();
1708 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001709}
1710
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001711inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001712{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001713 if (!m_haveStructures)
1714 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001715 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001716 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001717 for (size_t i = m_variables.numberOfArguments(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001718 m_variables.argument(i).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001719 for (size_t i = m_variables.numberOfLocals(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001720 m_variables.local(i).clobberStructures();
1721 m_haveStructures = false;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001722 m_didClobber = true;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001723}
1724
1725inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1726{
1727 if (nodeIndex == NoNode)
1728 return false;
1729
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001730 AbstractValue source;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001731
1732 Node& node = m_graph[nodeIndex];
1733 if (!node.refCount())
1734 return false;
1735
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001736#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001737 dataLog(" It's live, node @%u.\n", nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001738#endif
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001739
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001740 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001741 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001742#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001743 dataLog(" Transfering ");
1744 source.dump(WTF::dataFile());
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001745 dataLog(" from last access due to captured variable.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001746#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001747 } else {
1748 switch (node.op()) {
1749 case Phi:
1750 case SetArgument:
1751 case Flush:
1752 // The block transfers the value from head to tail.
1753 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001754#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001755 dataLog(" Transfering ");
1756 source.dump(WTF::dataFile());
1757 dataLog(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001758#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001759 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001760
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001761 case GetLocal:
1762 // The block refines the value with additional speculations.
1763 source = forNode(nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001764#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001765 dataLog(" Refining to ");
1766 source.dump(WTF::dataFile());
1767 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001768#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001769 break;
1770
1771 case SetLocal:
1772 // The block sets the variable, and potentially refines it, both
1773 // before and after setting it.
1774 if (node.variableAccessData()->shouldUseDoubleFormat()) {
1775 // FIXME: This unnecessarily loses precision.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001776 source.set(SpecDouble);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001777 } else
1778 source = forNode(node.child1());
1779#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1780 dataLog(" Setting to ");
1781 source.dump(WTF::dataFile());
1782 dataLog("\n");
1783#endif
1784 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001785
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001786 default:
1787 ASSERT_NOT_REACHED();
1788 break;
1789 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001790 }
1791
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001792 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001793 // Abstract execution did not change the output value of the variable, for this
1794 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001795#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001796 dataLog(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001797#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001798 return false;
1799 }
1800
1801 // Abstract execution reached a new conclusion about the speculations reached about
1802 // this variable after execution of this basic block. Update the state, and return
1803 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001804 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001805#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001806 dataLog(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001807#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001808 return true;
1809}
1810
1811inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1812{
1813 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1814 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1815
1816 bool changed = false;
1817
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001818 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1819 AbstractValue& destination = to->valuesAtHead.argument(argument);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001820 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1821 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001822
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001823 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1824 AbstractValue& destination = to->valuesAtHead.local(local);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001825 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1826 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001827
1828 if (!to->cfaHasVisited)
1829 changed = true;
1830
1831 to->cfaShouldRevisit |= changed;
1832
1833 return changed;
1834}
1835
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001836inline bool AbstractState::mergeToSuccessors(
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001837 Graph& graph, BasicBlock* basicBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001838{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001839 Node& terminal = graph[basicBlock->last()];
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001840
1841 ASSERT(terminal.isTerminal());
1842
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001843 switch (terminal.op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001844 case Jump: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001845 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001846#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1847 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1848#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001849 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001850 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001851
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001852 case Branch: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001853 ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001854 bool changed = false;
1855#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1856 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1857#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001858 if (basicBlock->cfaBranchDirection != TakeFalse)
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001859 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001860#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1861 dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1862#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001863 if (basicBlock->cfaBranchDirection != TakeTrue)
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001864 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001865 return changed;
1866 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001867
1868 case Return:
1869 case Throw:
1870 case ThrowReferenceError:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001871 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001872 return false;
1873
1874 default:
1875 ASSERT_NOT_REACHED();
1876 return false;
1877 }
1878}
1879
1880inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1881{
1882 if (destinationNodeIndex == NoNode)
1883 return false;
1884
1885 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1886
1887 // FIXME: We could do some sparse conditional propagation here!
1888
1889 return destination.merge(source);
1890}
1891
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001892void AbstractState::dump(FILE* out)
1893{
1894 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001895 for (size_t i = 0; i < m_block->size(); ++i) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001896 NodeIndex index = m_block->at(i);
1897 AbstractValue& value = m_nodes[index];
1898 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001899 continue;
1900 if (first)
1901 first = false;
1902 else
1903 fprintf(out, " ");
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001904 fprintf(out, "@%lu:", static_cast<unsigned long>(index));
1905 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001906 }
1907}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001908
1909} } // namespace JSC::DFG
1910
1911#endif // ENABLE(DFG_JIT)
1912