blob: d0ab9e104b134759fc6e1a79f9601ab3cadd0c79 [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 }
260
261 case GetLocal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000262 VariableAccessData* variableAccessData = node.variableAccessData();
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000263 if (variableAccessData->prediction() == SpecNone) {
264 m_isValid = false;
265 node.setCanExit(true);
266 break;
267 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000268 bool canExit = false;
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000269 AbstractValue value = m_variables.operand(variableAccessData->local());
270 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000271 if (value.isClear())
272 canExit |= true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000273 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000274 if (value.value())
275 m_foundConstants = true;
276 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000277 node.setCanExit(canExit);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000278 break;
279 }
280
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000281 case GetLocalUnlinked: {
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000282 AbstractValue value = m_variables.operand(node.unlinkedLocal());
283 if (value.value())
284 m_foundConstants = true;
285 forNode(nodeIndex) = value;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000286 node.setCanExit(false);
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000287 break;
288 }
289
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000290 case SetLocal: {
fpizlo@apple.com00528432012-07-20 03:50:02 +0000291 if (node.variableAccessData()->isCaptured()
292 || m_graph.isCreatedThisArgument(node.local())) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000293 m_variables.operand(node.local()) = forNode(node.child1());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000294 node.setCanExit(false);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000295 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000296 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000297
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000298 if (node.variableAccessData()->shouldUseDoubleFormat()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000299 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000300 m_variables.operand(node.local()).set(SpecDouble);
fpizlo@apple.com10f22fc2011-12-14 07:16:36 +0000301 break;
302 }
303
fpizlo@apple.com62336162012-06-07 01:35:59 +0000304 SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
305 if (isInt32Speculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000306 speculateInt32Unary(node);
fpizlo@apple.comf24804c2012-08-15 02:48:35 +0000307 else if (isCellSpeculation(predictedType)) {
fpizlo@apple.com00528432012-07-20 03:50:02 +0000308 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
309 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000310 } else if (isBooleanSpeculation(predictedType))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000311 speculateBooleanUnary(node);
312 else
313 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000314
315 m_variables.operand(node.local()) = forNode(node.child1());
316 break;
317 }
318
319 case SetArgument:
320 // Assert that the state of arguments has been set.
321 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000322 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000323 break;
324
325 case BitAnd:
326 case BitOr:
327 case BitXor:
328 case BitRShift:
329 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000330 case BitURShift: {
331 JSValue left = forNode(node.child1()).value();
332 JSValue right = forNode(node.child2()).value();
333 if (left && right && left.isInt32() && right.isInt32()) {
334 int32_t a = left.asInt32();
335 int32_t b = right.asInt32();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000336 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000337 switch (node.op()) {
338 case BitAnd:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000339 constantWasSet = trySetConstant(nodeIndex, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000340 break;
341 case BitOr:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000342 constantWasSet = trySetConstant(nodeIndex, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000343 break;
344 case BitXor:
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 BitRShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000348 constantWasSet = trySetConstant(nodeIndex, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000349 break;
350 case BitLShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000351 constantWasSet = trySetConstant(nodeIndex, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000352 break;
353 case BitURShift:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000354 constantWasSet = trySetConstant(nodeIndex, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000355 break;
356 default:
357 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000358 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000359 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000360 if (constantWasSet) {
361 m_foundConstants = true;
362 node.setCanExit(false);
363 break;
364 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000365 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000366 speculateInt32Binary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000367 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000368 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000369 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000370
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000371 case UInt32ToNumber: {
372 JSValue child = forNode(node.child1()).value();
373 if (child && child.isNumber()) {
374 ASSERT(child.isInt32());
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000375 if (trySetConstant(nodeIndex, JSValue(child.asUInt32()))) {
376 m_foundConstants = true;
377 node.setCanExit(false);
378 break;
379 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000380 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000381 if (!node.canSpeculateInteger()) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000382 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000383 node.setCanExit(false);
384 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000385 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000386 node.setCanExit(true);
387 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000388 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000389 }
390
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000391
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000392 case DoubleAsInt32: {
393 JSValue child = forNode(node.child1()).value();
394 if (child && child.isNumber()) {
395 double asDouble = child.asNumber();
396 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000397 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
398 && trySetConstant(nodeIndex, JSValue(asInt))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000399 m_foundConstants = true;
400 break;
401 }
402 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000403 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000404 forNode(node.child1()).filter(SpecNumber);
405 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000406 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000407 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000408
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000409 case ValueToInt32: {
410 JSValue child = forNode(node.child1()).value();
411 if (child && child.isNumber()) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000412 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000413 if (child.isInt32())
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000414 constantWasSet = trySetConstant(nodeIndex, child);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000415 else
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000416 constantWasSet = trySetConstant(nodeIndex, JSValue(JSC::toInt32(child.asDouble())));
417 if (constantWasSet) {
418 m_foundConstants = true;
419 node.setCanExit(false);
420 break;
421 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000422 }
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000423 if (m_graph[node.child1()].shouldSpeculateInteger())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000424 speculateInt32Unary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000425 else if (m_graph[node.child1()].shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000426 speculateNumberUnary(node);
fpizlo@apple.com2fc3dbd2012-03-14 02:54:58 +0000427 else if (m_graph[node.child1()].shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000428 speculateBooleanUnary(node);
429 else
430 node.setCanExit(false);
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000431
fpizlo@apple.com62336162012-06-07 01:35:59 +0000432 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000433 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000434 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000435
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000436 case Int32ToDouble: {
437 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000438 if (child && child.isNumber()
439 && trySetConstant(nodeIndex, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000440 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000441 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000442 break;
443 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000444 speculateNumberUnary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000445 if (isInt32Speculation(forNode(node.child1()).m_type))
446 forNode(nodeIndex).set(SpecDoubleReal);
447 else
448 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000449 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000450 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000451
452 case CheckNumber:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000453 forNode(node.child1()).filter(SpecNumber);
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000454 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000455
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000456 case ValueAdd:
457 case ArithAdd: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000458 JSValue left = forNode(node.child1()).value();
459 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000460 if (left && right && left.isNumber() && right.isNumber()
461 && trySetConstant(nodeIndex, JSValue(left.asNumber() + right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000462 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000463 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000464 break;
465 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000466 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000467 speculateInt32Binary(
468 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000469 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000470 break;
471 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000472 if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000473 speculateNumberBinary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000474 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
475 && isRealNumberSpeculation(forNode(node.child2()).m_type))
476 forNode(nodeIndex).set(SpecDoubleReal);
477 else
478 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000479 break;
480 }
fpizlo@apple.comd7897b12012-03-12 23:15:45 +0000481 if (node.op() == ValueAdd) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000482 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000483 forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000484 node.setCanExit(false);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000485 break;
486 }
487 // We don't handle this yet. :-(
488 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000489 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000490 break;
491 }
492
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000493 case ArithSub: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000494 JSValue left = forNode(node.child1()).value();
495 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000496 if (left && right && left.isNumber() && right.isNumber()
497 && trySetConstant(nodeIndex, JSValue(left.asNumber() - right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000498 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000499 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000500 break;
501 }
fpizlo@apple.comadf274c2012-02-18 07:56:10 +0000502 if (m_graph.addShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000503 speculateInt32Binary(
504 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000505 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000506 break;
507 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000508 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000509 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000510 break;
511 }
512
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000513 case ArithNegate: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000514 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000515 if (child && child.isNumber()
516 && trySetConstant(nodeIndex, JSValue(-child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000517 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000518 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000519 break;
520 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000521 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000522 speculateInt32Unary(
523 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000524 forNode(nodeIndex).set(SpecInt32);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000525 break;
526 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000527 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000528 forNode(nodeIndex).set(SpecDouble);
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000529 break;
530 }
531
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000532 case ArithMul: {
533 JSValue left = forNode(node.child1()).value();
534 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000535 if (left && right && left.isNumber() && right.isNumber()
536 && trySetConstant(nodeIndex, JSValue(left.asNumber() * right.asNumber()))) {
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000537 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000538 node.setCanExit(false);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000539 break;
540 }
541 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000542 speculateInt32Binary(
543 node,
544 !nodeCanTruncateInteger(node.arithNodeFlags())
545 || !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
fpizlo@apple.com62336162012-06-07 01:35:59 +0000546 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000547 break;
548 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000549 speculateNumberBinary(node);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000550 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
551 || isRealNumberSpeculation(forNode(node.child2()).m_type))
552 forNode(nodeIndex).set(SpecDoubleReal);
553 else
554 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000555 break;
556 }
557
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000558 case ArithDiv:
559 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000560 case ArithMax:
561 case ArithMod: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000562 JSValue left = forNode(node.child1()).value();
563 JSValue right = forNode(node.child2()).value();
564 if (left && right && left.isNumber() && right.isNumber()) {
565 double a = left.asNumber();
566 double b = right.asNumber();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000567 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000568 switch (node.op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000569 case ArithDiv:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000570 constantWasSet = trySetConstant(nodeIndex, JSValue(a / b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000571 break;
572 case ArithMin:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000573 constantWasSet = trySetConstant(nodeIndex, JSValue(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000574 break;
575 case ArithMax:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000576 constantWasSet = trySetConstant(nodeIndex, JSValue(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000577 break;
578 case ArithMod:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000579 constantWasSet = trySetConstant(nodeIndex, JSValue(fmod(a, b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000580 break;
581 default:
582 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000583 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000584 break;
585 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000586 if (constantWasSet) {
587 m_foundConstants = true;
588 node.setCanExit(false);
589 break;
590 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000591 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000592 if (Node::shouldSpeculateIntegerForArithmetic(
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000593 m_graph[node.child1()], m_graph[node.child2()])
594 && node.canSpeculateInteger()) {
595 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
fpizlo@apple.com62336162012-06-07 01:35:59 +0000596 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000597 break;
598 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000599 speculateNumberBinary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000600 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000601 break;
602 }
603
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000604 case ArithAbs: {
605 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000606 if (child && child.isNumber()
607 && trySetConstant(nodeIndex, JSValue(fabs(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000608 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000609 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000610 break;
611 }
fpizlo@apple.com81f75372012-11-08 22:55:27 +0000612 if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000613 && node.canSpeculateInteger()) {
614 speculateInt32Unary(node, true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000615 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000616 break;
617 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000618 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000619 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000620 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000621 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000622
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000623 case ArithSqrt: {
624 JSValue child = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000625 if (child && child.isNumber()
626 && trySetConstant(nodeIndex, JSValue(sqrt(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000627 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000628 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000629 break;
630 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000631 speculateNumberUnary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000632 forNode(nodeIndex).set(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000633 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000634 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000635
636 case LogicalNot: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000637 bool didSetConstant = false;
638 switch (booleanResult(node, forNode(node.child1()))) {
639 case DefinitelyTrue:
640 didSetConstant = trySetConstant(nodeIndex, jsBoolean(false));
641 break;
642 case DefinitelyFalse:
643 didSetConstant = trySetConstant(nodeIndex, jsBoolean(true));
644 break;
645 default:
646 break;
647 }
648 if (didSetConstant) {
fpizlo@apple.com152abff2012-06-19 23:10:12 +0000649 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000650 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000651 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000652 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000653 Node& child = m_graph[node.child1()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000654 if (isBooleanSpeculation(child.prediction()))
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000655 speculateBooleanUnary(node);
mhahnenberg@apple.comdb8065f2012-09-04 18:46:21 +0000656 else if (child.shouldSpeculateNonStringCellOrOther()) {
657 node.setCanExit(true);
658 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000659 } else if (child.shouldSpeculateInteger())
660 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000661 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000662 speculateNumberUnary(node);
663 else
664 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000665 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000666 break;
667 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000668
669 case IsUndefined:
670 case IsBoolean:
671 case IsNumber:
672 case IsString:
673 case IsObject:
674 case IsFunction: {
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000675 node.setCanExit(node.op() == IsUndefined && m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000676 JSValue child = forNode(node.child1()).value();
677 if (child) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000678 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000679 switch (node.op()) {
680 case IsUndefined:
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000681 if (m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
682 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
683 child.isCell()
684 ? false
685 : child.isUndefined()));
686 } else {
687 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
688 child.isCell()
689 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
690 : child.isUndefined()));
691 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000692 break;
693 case IsBoolean:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000694 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000695 break;
696 case IsNumber:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000697 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000698 break;
699 case IsString:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000700 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000701 break;
702 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000703 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000704 break;
705 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000706 if (constantWasSet) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000707 m_foundConstants = true;
708 break;
709 }
710 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000711 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000712 break;
713 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000714
715 case CompareLess:
716 case CompareLessEq:
717 case CompareGreater:
718 case CompareGreaterEq:
719 case CompareEq: {
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000720 bool constantWasSet = false;
721
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000722 JSValue leftConst = forNode(node.child1()).value();
723 JSValue rightConst = forNode(node.child2()).value();
724 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
725 double a = leftConst.asNumber();
726 double b = rightConst.asNumber();
727 switch (node.op()) {
728 case CompareLess:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000729 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000730 break;
731 case CompareLessEq:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000732 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a <= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000733 break;
734 case CompareGreater:
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 CompareGreaterEq:
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 CompareEq:
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 default:
744 ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000745 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000746 break;
747 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000748 }
749
750 if (!constantWasSet && node.op() == CompareEq) {
751 SpeculatedType leftType = forNode(node.child1()).m_type;
752 SpeculatedType rightType = forNode(node.child2()).m_type;
753 if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
754 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
755 constantWasSet = trySetConstant(nodeIndex, jsBoolean(false));
756 }
757
758 if (constantWasSet) {
759 m_foundConstants = true;
760 node.setCanExit(false);
761 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000762 }
763
fpizlo@apple.com62336162012-06-07 01:35:59 +0000764 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000765
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000766 Node& left = m_graph[node.child1()];
767 Node& right = m_graph[node.child2()];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000768 SpeculatedType filter;
769 SpeculatedTypeChecker checker;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000770 if (Node::shouldSpeculateInteger(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000771 filter = SpecInt32;
772 checker = isInt32Speculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000773 } else if (Node::shouldSpeculateNumber(left, right)) {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000774 filter = SpecNumber;
775 checker = isNumberSpeculation;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000776 } else if (node.op() == CompareEq) {
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000777 if ((m_graph.isConstant(node.child1().index())
778 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
779 || (m_graph.isConstant(node.child2().index())
780 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000781 // We can exit if we haven't fired the MasqueradesAsUndefind watchpoint yet.
782 node.setCanExit(m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000783 break;
784 }
785
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000786 if (left.shouldSpeculateString() || right.shouldSpeculateString()) {
787 node.setCanExit(false);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000788 break;
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000789 }
790 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCellOrOther()) {
791 node.setCanExit(true);
792 forNode(node.child1()).filter(SpecCell & ~SpecString);
793 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000794 break;
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000795 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000796 if (left.shouldSpeculateNonStringCellOrOther() && right.shouldSpeculateNonStringCell()) {
797 node.setCanExit(true);
798 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
799 forNode(node.child2()).filter(SpecCell & ~SpecString);
800 break;
801 }
802 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCell()) {
803 node.setCanExit(true);
804 forNode(node.child1()).filter(SpecCell & ~SpecString);
805 forNode(node.child2()).filter(SpecCell & ~SpecString);
806 break;
807 }
808
809 filter = SpecTop;
810 checker = isAnySpeculation;
811 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000812 } else {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000813 filter = SpecTop;
814 checker = isAnySpeculation;
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000815 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000816 }
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000817 node.setCanExit(
818 !checker(forNode(node.child1()).m_type)
819 || !checker(forNode(node.child2()).m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000820 forNode(node.child1()).filter(filter);
821 forNode(node.child2()).filter(filter);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000822 break;
823 }
824
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000825 case CompareStrictEq: {
826 JSValue left = forNode(node.child1()).value();
827 JSValue right = forNode(node.child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000828 if (left && right && left.isNumber() && right.isNumber()
829 && trySetConstant(nodeIndex, jsBoolean(left.asNumber() == right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000830 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000831 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000832 break;
833 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000834 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000835 if (m_graph.isJSConstant(node.child1().index())) {
836 JSValue value = m_graph.valueOfJSConstant(node.child1().index());
837 if (!value.isNumber() && !value.isString()) {
838 node.setCanExit(false);
839 break;
840 }
841 }
842 if (m_graph.isJSConstant(node.child2().index())) {
843 JSValue value = m_graph.valueOfJSConstant(node.child2().index());
844 if (!value.isNumber() && !value.isString()) {
845 node.setCanExit(false);
846 break;
847 }
848 }
849 if (Node::shouldSpeculateInteger(
850 m_graph[node.child1()], m_graph[node.child2()])) {
851 speculateInt32Binary(node);
852 break;
853 }
854 if (Node::shouldSpeculateNumber(
855 m_graph[node.child1()], m_graph[node.child2()])) {
856 speculateNumberBinary(node);
857 break;
858 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000859 Node& leftNode = m_graph[node.child1()];
860 Node& rightNode = m_graph[node.child2()];
861 if (leftNode.shouldSpeculateString() || rightNode.shouldSpeculateString()) {
862 node.setCanExit(false);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000863 break;
864 }
mhahnenberg@apple.com030c9da2012-08-30 21:11:21 +0000865 if (leftNode.shouldSpeculateNonStringCell() && rightNode.shouldSpeculateNonStringCell()) {
866 node.setCanExit(true);
867 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
868 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000869 break;
870 }
871 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000872 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000873 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000874
875 case StringCharCodeAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000876 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000877 forNode(node.child1()).filter(SpecString);
878 forNode(node.child2()).filter(SpecInt32);
879 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000880 break;
881
882 case StringCharAt:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000883 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000884 forNode(node.child1()).filter(SpecString);
885 forNode(node.child2()).filter(SpecInt32);
886 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000887 break;
888
889 case GetByVal: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000890 node.setCanExit(true);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000891 switch (node.arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +0000892 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +0000893 case Array::Unprofiled:
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000894 case Array::Undecided:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000895 ASSERT_NOT_REACHED();
896 break;
897 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000898 m_isValid = false;
899 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000900 case Array::Generic:
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000901 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000902 forNode(nodeIndex).makeTop();
903 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000904 case Array::String:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000905 forNode(node.child2()).filter(SpecInt32);
906 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000907 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000908 case Array::Arguments:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000909 forNode(node.child2()).filter(SpecInt32);
910 forNode(nodeIndex).makeTop();
911 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000912 case Array::Int32:
913 forNode(node.child2()).filter(SpecInt32);
914 if (node.arrayMode().isOutOfBounds()) {
915 clobberWorld(node.codeOrigin, indexInBlock);
916 forNode(nodeIndex).makeTop();
917 } else
918 forNode(nodeIndex).set(SpecInt32);
919 break;
920 case Array::Double:
921 forNode(node.child2()).filter(SpecInt32);
922 if (node.arrayMode().isOutOfBounds()) {
923 clobberWorld(node.codeOrigin, indexInBlock);
924 forNode(nodeIndex).makeTop();
925 } else
926 forNode(nodeIndex).set(SpecDoubleReal);
927 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000928 case Array::Contiguous:
929 case Array::ArrayStorage:
930 case Array::SlowPutArrayStorage:
fpizlo@apple.com163e4772012-09-04 21:15:02 +0000931 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000932 if (node.arrayMode().isOutOfBounds())
933 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +0000934 forNode(nodeIndex).makeTop();
935 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000936 case Array::Int8Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000937 forNode(node.child2()).filter(SpecInt32);
938 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000939 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000940 case Array::Int16Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000941 forNode(node.child2()).filter(SpecInt32);
942 forNode(nodeIndex).set(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000943 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000944 case Array::Int32Array:
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::Uint8Array:
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::Uint8ClampedArray:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000953 forNode(node.child2()).filter(SpecInt32);
954 forNode(nodeIndex).set(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000955 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000956 case Array::Uint16Array:
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::Uint32Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000961 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000962 if (node.shouldSpeculateInteger())
fpizlo@apple.com62336162012-06-07 01:35:59 +0000963 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000964 else
fpizlo@apple.com62336162012-06-07 01:35:59 +0000965 forNode(nodeIndex).set(SpecDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000966 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000967 case Array::Float32Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000968 forNode(node.child2()).filter(SpecInt32);
969 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000970 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000971 case Array::Float64Array:
fpizlo@apple.com62336162012-06-07 01:35:59 +0000972 forNode(node.child2()).filter(SpecInt32);
973 forNode(nodeIndex).set(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000974 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000975 default:
976 ASSERT_NOT_REACHED();
977 break;
oliver@apple.com07d75732011-12-03 01:47:27 +0000978 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000979 break;
980 }
981
982 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000983 case PutByValAlias: {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000984 node.setCanExit(true);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000985 Edge child1 = m_graph.varArgChild(node, 0);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +0000986 Edge child2 = m_graph.varArgChild(node, 1);
987 Edge child3 = m_graph.varArgChild(node, 2);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000988 switch (node.arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000989 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000990 m_isValid = false;
991 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000992 case Array::Generic:
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000993 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000994 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000995 case Array::Int32:
996 forNode(child1).filter(SpecCell);
997 forNode(child2).filter(SpecInt32);
998 forNode(child3).filter(SpecInt32);
999 if (node.arrayMode().isOutOfBounds())
1000 clobberWorld(node.codeOrigin, indexInBlock);
1001 break;
1002 case Array::Double:
1003 forNode(child1).filter(SpecCell);
1004 forNode(child2).filter(SpecInt32);
1005 forNode(child3).filter(SpecRealNumber);
1006 if (node.arrayMode().isOutOfBounds())
1007 clobberWorld(node.codeOrigin, indexInBlock);
1008 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001009 case Array::Contiguous:
1010 case Array::ArrayStorage:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001011 forNode(child1).filter(SpecCell);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001012 forNode(child2).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001013 if (node.arrayMode().isOutOfBounds())
1014 clobberWorld(node.codeOrigin, indexInBlock);
1015 break;
1016 case Array::SlowPutArrayStorage:
1017 forNode(child1).filter(SpecCell);
1018 forNode(child2).filter(SpecInt32);
1019 if (node.arrayMode().mayStoreToHole())
1020 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001021 break;
1022 case Array::Arguments:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001023 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001024 forNode(child2).filter(SpecInt32);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001025 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001026 case Array::Int8Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001027 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001028 forNode(child2).filter(SpecInt32);
1029 if (m_graph[child3].shouldSpeculateInteger())
1030 forNode(child3).filter(SpecInt32);
fpizlo@apple.com19a172792012-03-24 20:15:57 +00001031 else
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001032 forNode(child3).filter(SpecNumber);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001033 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001034 case Array::Int16Array:
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::Int32Array:
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::Uint8Array:
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::Uint8ClampedArray:
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);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +00001065 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001066 case Array::Uint16Array:
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);
oliver@apple.comaeec3d82011-12-02 01:56:53 +00001073 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001074 case Array::Uint32Array:
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::Float32Array:
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 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001086 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001087 case Array::Float64Array:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001088 forNode(child1).filter(SpecCell);
fpizlo@apple.coma4eaa8a2012-07-15 05:23:58 +00001089 forNode(child2).filter(SpecInt32);
1090 forNode(child3).filter(SpecNumber);
oliver@apple.com07d75732011-12-03 01:47:27 +00001091 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001092 default:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001093 CRASH();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001094 break;
oliver@apple.com07d75732011-12-03 01:47:27 +00001095 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001096 break;
1097 }
1098
1099 case ArrayPush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001100 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001101 switch (node.arrayMode().type()) {
1102 case Array::Int32:
1103 forNode(node.child2()).filter(SpecInt32);
1104 break;
1105 case Array::Double:
1106 forNode(node.child2()).filter(SpecRealNumber);
1107 break;
1108 default:
1109 break;
1110 }
fpizlo@apple.come0480cf2012-09-26 02:56:19 +00001111 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001112 forNode(nodeIndex).set(SpecNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001113 break;
1114
1115 case ArrayPop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001116 node.setCanExit(true);
fpizlo@apple.come0480cf2012-09-26 02:56:19 +00001117 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001118 forNode(nodeIndex).makeTop();
1119 break;
1120
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001121 case RegExpExec:
1122 case RegExpTest:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001123 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001124 !isCellSpeculation(forNode(node.child1()).m_type)
1125 || !isCellSpeculation(forNode(node.child2()).m_type));
1126 forNode(node.child1()).filter(SpecCell);
1127 forNode(node.child2()).filter(SpecCell);
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001128 forNode(nodeIndex).makeTop();
1129 break;
1130
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001131 case Jump:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001132 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001133 break;
1134
1135 case Branch: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001136 BooleanResult result = booleanResult(node, forNode(node.child1()));
1137 if (result == DefinitelyTrue) {
1138 m_branchDirection = TakeTrue;
1139 node.setCanExit(false);
1140 break;
1141 }
1142 if (result == DefinitelyFalse) {
1143 m_branchDirection = TakeFalse;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001144 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001145 break;
1146 }
1147 // FIXME: The above handles the trivial cases of sparse conditional
1148 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001149 // We can specialize the source variable's value on each direction of
1150 // the branch.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001151 Node& child = m_graph[node.child1()];
fpizlo@apple.comad60ef32012-03-22 03:47:55 +00001152 if (child.shouldSpeculateBoolean())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001153 speculateBooleanUnary(node);
mhahnenberg@apple.comc1925152012-09-01 00:38:37 +00001154 else if (child.shouldSpeculateNonStringCellOrOther()) {
1155 node.setCanExit(true);
1156 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001157 } else if (child.shouldSpeculateInteger())
1158 speculateInt32Unary(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001159 else if (child.shouldSpeculateNumber())
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001160 speculateNumberUnary(node);
1161 else
1162 node.setCanExit(false);
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001163 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001164 break;
1165 }
1166
1167 case Return:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001168 m_isValid = false;
1169 node.setCanExit(false);
1170 break;
1171
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001172 case Throw:
1173 case ThrowReferenceError:
1174 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001175 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001176 break;
1177
1178 case ToPrimitive: {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001179 JSValue childConst = forNode(node.child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +00001180 if (childConst && childConst.isNumber() && trySetConstant(nodeIndex, childConst)) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001181 m_foundConstants = true;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001182 node.setCanExit(false);
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001183 break;
1184 }
1185
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001186 Node& child = m_graph[node.child1()];
1187 if (child.shouldSpeculateInteger()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001188 speculateInt32Unary(node);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001189 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001190 break;
1191 }
1192
1193 AbstractValue& source = forNode(node.child1());
1194 AbstractValue& destination = forNode(nodeIndex);
1195
fpizlo@apple.com62336162012-06-07 01:35:59 +00001196 SpeculatedType type = source.m_type;
1197 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1198 type &= (SpecNumber | SpecString | SpecBoolean);
1199 type |= SpecString;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001200 }
1201 destination.set(type);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001202 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001203 break;
1204 }
1205
1206 case StrCat:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001207 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001208 forNode(nodeIndex).set(SpecString);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001209 break;
1210
1211 case NewArray:
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001212 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001213 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001214 m_haveStructures = true;
1215 break;
1216
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001217 case NewArrayBuffer:
fpizlo@apple.com68677de2012-10-11 19:36:04 +00001218 node.setCanExit(true);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001219 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
fpizlo@apple.com68677de2012-10-11 19:36:04 +00001220 m_haveStructures = true;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001221 break;
1222
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001223 case NewArrayWithSize:
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001224 node.setCanExit(true);
1225 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com1bc68482012-10-13 03:56:09 +00001226 forNode(nodeIndex).set(SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001227 m_haveStructures = true;
1228 break;
1229
1230 case NewRegexp:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001231 node.setCanExit(false);
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001232 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001233 m_haveStructures = true;
1234 break;
1235
1236 case ConvertThis: {
1237 Node& child = m_graph[node.child1()];
1238 AbstractValue& source = forNode(node.child1());
1239 AbstractValue& destination = forNode(nodeIndex);
1240
fpizlo@apple.com62336162012-06-07 01:35:59 +00001241 if (isObjectSpeculation(source.m_type)) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001242 // This is the simple case. We already know that the source is an
1243 // object, so there's nothing to do. I don't think this case will
1244 // be hit, but then again, you never know.
1245 destination = source;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001246 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001247 break;
1248 }
fpizlo@apple.com1ca63d02011-11-10 23:59:31 +00001249
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001250 node.setCanExit(true);
1251
fpizlo@apple.com62336162012-06-07 01:35:59 +00001252 if (isOtherSpeculation(child.prediction())) {
1253 source.filter(SpecOther);
1254 destination.set(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001255 break;
1256 }
1257
fpizlo@apple.com62336162012-06-07 01:35:59 +00001258 if (isObjectSpeculation(child.prediction())) {
1259 source.filter(SpecObjectMask);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001260 destination = source;
1261 break;
1262 }
1263
1264 destination = source;
fpizlo@apple.com62336162012-06-07 01:35:59 +00001265 destination.merge(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001266 break;
1267 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001268
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001269 case CreateThis: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001270 AbstractValue& source = forNode(node.child1());
1271 AbstractValue& destination = forNode(nodeIndex);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001272
fpizlo@apple.com62336162012-06-07 01:35:59 +00001273 node.setCanExit(!isCellSpeculation(source.m_type));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001274
fpizlo@apple.com62336162012-06-07 01:35:59 +00001275 source.filter(SpecFunction);
1276 destination.set(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001277 break;
1278 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001279
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001280 case NewObject:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001281 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001282 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001283 m_haveStructures = true;
1284 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001285
1286 case CreateActivation:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001287 node.setCanExit(false);
ggaren@apple.com70aed692012-09-01 00:46:58 +00001288 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->activationStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001289 m_haveStructures = true;
1290 break;
1291
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001292 case CreateArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001293 node.setCanExit(false);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001294 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1295 m_haveStructures = true;
1296 break;
1297
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001298 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001299 case TearOffArguments:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001300 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001301 // Does nothing that is user-visible.
1302 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001303
1304 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001305 if (isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001306 m_variables.operand(
fpizlo@apple.comb80bc2a32012-06-02 22:58:48 +00001307 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
1308 node.setCanExit(false);
1309 m_foundConstants = true;
1310 } else
1311 node.setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001312 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001313
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001314 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001315 // We know that this executable does not escape its arguments, so we can optimize
1316 // the arguments a bit. Note that this is not sufficient to force constant folding
1317 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1318 // We perform further optimizations on this later on.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001319 if (node.codeOrigin.inlineCallFrame)
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001320 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001321 else
fpizlo@apple.com62336162012-06-07 01:35:59 +00001322 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001323 node.setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001324 !isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001325 m_variables.operand(
1326 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001327 break;
1328
1329 case GetMyArgumentsLengthSafe:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001330 node.setCanExit(false);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001331 // This potentially clobbers all structures if the arguments object had a getter
1332 // installed on the length property.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001333 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001334 // We currently make no guarantee about what this returns because it does not
1335 // speculate that the length property is actually a length.
1336 forNode(nodeIndex).makeTop();
1337 break;
1338
1339 case GetMyArgumentByVal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001340 node.setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001341 // We know that this executable does not escape its arguments, so we can optimize
1342 // the arguments a bit. Note that this ends up being further optimized by the
1343 // ArgumentsSimplificationPhase.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001344 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001345 forNode(nodeIndex).makeTop();
1346 break;
1347
1348 case GetMyArgumentByValSafe:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001349 node.setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001350 // This potentially clobbers all structures if the property we're accessing has
1351 // a getter. We don't speculate against this.
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001352 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001353 // But we do speculate that the index is an integer.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001354 forNode(node.child1()).filter(SpecInt32);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001355 // And the result is unknown.
1356 forNode(nodeIndex).makeTop();
1357 break;
1358
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001359 case NewFunction:
1360 case NewFunctionExpression:
1361 case NewFunctionNoCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001362 node.setCanExit(false);
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001363 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1364 break;
1365
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001366 case GetCallee:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001367 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001368 forNode(nodeIndex).set(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001369 break;
1370
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001371 case GetScope:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001372 node.setCanExit(false);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001373 forNode(nodeIndex).set(SpecCellOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001374 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001375
1376 case GetScopeRegisters:
1377 node.setCanExit(false);
1378 forNode(node.child1()).filter(SpecCell);
1379 forNode(nodeIndex).clear(); // The result is not a JS value.
1380 break;
1381
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001382 case GetScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001383 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001384 forNode(nodeIndex).makeTop();
1385 break;
1386
1387 case PutScopedVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001388 node.setCanExit(false);
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001389 clobberCapturedVars(node.codeOrigin);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001390 break;
1391
1392 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001393 case GetByIdFlush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001394 node.setCanExit(true);
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001395 if (!node.prediction()) {
1396 m_isValid = false;
1397 break;
1398 }
fpizlo@apple.com62336162012-06-07 01:35:59 +00001399 if (isCellSpeculation(m_graph[node.child1()].prediction()))
1400 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001401 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001402 forNode(nodeIndex).makeTop();
1403 break;
1404
1405 case GetArrayLength:
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001406 node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
1407 forNode(nodeIndex).set(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001408 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001409
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001410 case CheckStructure:
1411 case ForwardCheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001412 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001413 AbstractValue& value = forNode(node.child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001414 // If this structure check is attempting to prove knowledge already held in
1415 // the futurePossibleStructure set then the constant folding phase should
1416 // turn this into a watchpoint instead.
1417 StructureSet& set = node.structureSet();
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001418 if (value.m_futurePossibleStructure.isSubsetOf(set)
1419 || value.m_currentKnownStructure.isSubsetOf(set))
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001420 m_foundConstants = true;
fpizlo@apple.com9d899a42012-05-25 05:41:03 +00001421 node.setCanExit(
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001422 !value.m_currentKnownStructure.isSubsetOf(set)
fpizlo@apple.com62336162012-06-07 01:35:59 +00001423 || !isCellSpeculation(value.m_type));
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001424 value.filter(set);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001425 m_haveStructures = true;
1426 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001427 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001428
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001429 case StructureTransitionWatchpoint:
1430 case ForwardStructureTransitionWatchpoint: {
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001431 AbstractValue& value = forNode(node.child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001432
1433 // It's only valid to issue a structure transition watchpoint if we already
1434 // know that the watchpoint covers a superset of the structures known to
1435 // belong to the set of future structures that this value may have.
1436 // Currently, we only issue singleton watchpoints (that check one structure)
1437 // and our futurePossibleStructure set can only contain zero, one, or an
1438 // infinity of structures.
1439 ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node.structure())));
1440
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00001441 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 +00001442 value.filter(node.structure());
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001443 m_haveStructures = true;
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001444 node.setCanExit(true);
1445 break;
1446 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001447
1448 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001449 case PhantomPutStructure:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001450 node.setCanExit(false);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00001451 if (!forNode(node.child1()).m_currentKnownStructure.isClear()) {
1452 clobberStructures(indexInBlock);
1453 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1454 m_haveStructures = true;
1455 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001456 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00001457 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00001458 case AllocatePropertyStorage:
1459 case ReallocatePropertyStorage:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001460 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001461 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001462 forNode(nodeIndex).clear(); // The result is not a JS value.
1463 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001464 case CheckArray: {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001465 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001466 m_foundConstants = true;
1467 node.setCanExit(false);
1468 break;
1469 }
1470 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 +00001471 switch (node.arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001472 case Array::String:
1473 forNode(node.child1()).filter(SpecString);
1474 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001475 case Array::Int32:
1476 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001477 case Array::Contiguous:
1478 case Array::ArrayStorage:
1479 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001480 forNode(node.child1()).filter(SpecCell);
1481 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001482 case Array::Arguments:
1483 forNode(node.child1()).filter(SpecArguments);
1484 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001485 case Array::Int8Array:
1486 forNode(node.child1()).filter(SpecInt8Array);
1487 break;
1488 case Array::Int16Array:
1489 forNode(node.child1()).filter(SpecInt16Array);
1490 break;
1491 case Array::Int32Array:
1492 forNode(node.child1()).filter(SpecInt32Array);
1493 break;
1494 case Array::Uint8Array:
1495 forNode(node.child1()).filter(SpecUint8Array);
1496 break;
1497 case Array::Uint8ClampedArray:
1498 forNode(node.child1()).filter(SpecUint8ClampedArray);
1499 break;
1500 case Array::Uint16Array:
1501 forNode(node.child1()).filter(SpecUint16Array);
1502 break;
1503 case Array::Uint32Array:
1504 forNode(node.child1()).filter(SpecUint32Array);
1505 break;
1506 case Array::Float32Array:
1507 forNode(node.child1()).filter(SpecFloat32Array);
1508 break;
1509 case Array::Float64Array:
1510 forNode(node.child1()).filter(SpecFloat64Array);
1511 break;
1512 default:
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001513 ASSERT_NOT_REACHED();
1514 break;
1515 }
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001516 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.comf08803e2012-10-26 01:57:07 +00001517 m_haveStructures = true;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001518 break;
1519 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001520 case Arrayify: {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001521 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00001522 m_foundConstants = true;
1523 node.setCanExit(false);
1524 break;
1525 }
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001526 ASSERT(node.arrayMode().conversion() == Array::Convert);
1527 node.setCanExit(true);
1528 forNode(node.child1()).filter(SpecCell);
1529 if (node.child2())
1530 forNode(node.child2()).filter(SpecInt32);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001531 clobberStructures(indexInBlock);
1532 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
1533 m_haveStructures = true;
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001534 break;
1535 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001536 case ArrayifyToStructure: {
1537 AbstractValue& value = forNode(node.child1());
1538 StructureSet set = node.structure();
1539 if (value.m_futurePossibleStructure.isSubsetOf(set)
1540 || value.m_currentKnownStructure.isSubsetOf(set))
1541 m_foundConstants = true;
1542 node.setCanExit(true);
1543 clobberStructures(indexInBlock);
1544 value.filter(set);
1545 m_haveStructures = true;
1546 break;
1547 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001548 case GetIndexedPropertyStorage: {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001549 switch (node.arrayMode().type()) {
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001550 case Array::String:
1551 // Strings are weird - we may spec fail if the string was a rope. That is of course
1552 // stupid, and we should fix that, but for now let's at least be honest about it.
1553 node.setCanExit(true);
1554 break;
1555 default:
1556 node.setCanExit(false);
1557 break;
1558 }
oliver@apple.com43e511c2011-12-09 08:45:46 +00001559 forNode(nodeIndex).clear();
1560 break;
1561 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001562 case GetByOffset:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001563 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001564 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001565 forNode(nodeIndex).makeTop();
1566 break;
1567
1568 case PutByOffset:
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001569 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
fpizlo@apple.com62336162012-06-07 01:35:59 +00001570 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001571 break;
1572
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001573 case CheckFunction:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001574 node.setCanExit(true); // Lies! We can do better.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001575 forNode(node.child1()).filter(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001576 // FIXME: Should be able to propagate the fact that we know what the function is.
1577 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001578
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001579 case PutById:
1580 case PutByIdDirect:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001581 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001582 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001583 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001584 break;
1585
1586 case GetGlobalVar:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001587 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001588 forNode(nodeIndex).makeTop();
1589 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001590
1591 case GlobalVarWatchpoint:
1592 node.setCanExit(true);
1593 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001594
1595 case PutGlobalVar:
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001596 case PutGlobalVarCheck:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001597 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001598 break;
1599
1600 case CheckHasInstance:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001601 node.setCanExit(true);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001602 forNode(node.child1()).filter(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001603 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1604 break;
1605
1606 case InstanceOf:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001607 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001608 // Again, sadly, we don't propagate the fact that we've done InstanceOf
fpizlo@apple.com62336162012-06-07 01:35:59 +00001609 if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
1610 forNode(node.child1()).filter(SpecCell);
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001611 forNode(node.child2()).filter(SpecCell);
fpizlo@apple.com62336162012-06-07 01:35:59 +00001612 forNode(nodeIndex).set(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001613 break;
1614
1615 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001616 case Flush:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001617 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001618 break;
1619
1620 case Breakpoint:
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 Call:
1625 case Construct:
1626 case Resolve:
1627 case ResolveBase:
1628 case ResolveBaseStrictPut:
1629 case ResolveGlobal:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001630 node.setCanExit(true);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001631 clobberWorld(node.codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001632 forNode(nodeIndex).makeTop();
1633 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001634
1635 case GarbageValue:
1636 clobberWorld(node.codeOrigin, indexInBlock);
1637 forNode(nodeIndex).makeTop();
1638 break;
1639
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001640 case ForceOSRExit:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001641 node.setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001642 m_isValid = false;
1643 break;
1644
1645 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001646 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001647 case Nop:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001648 node.setCanExit(false);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001649 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001650
1651 case LastNodeType:
1652 ASSERT_NOT_REACHED();
1653 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001654 }
1655
1656 return m_isValid;
1657}
1658
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001659inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1660{
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001661 clobberCapturedVars(codeOrigin);
1662 clobberStructures(indexInBlock);
1663}
1664
1665inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin)
1666{
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001667 if (codeOrigin.inlineCallFrame) {
1668 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1669 for (size_t i = capturedVars.size(); i--;) {
1670 if (!capturedVars.quickGet(i))
1671 continue;
1672 m_variables.local(i).makeTop();
1673 }
1674 } else {
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001675 for (size_t i = m_codeBlock->m_numVars; i--;) {
1676 if (m_codeBlock->isCaptured(i))
1677 m_variables.local(i).makeTop();
1678 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001679 }
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001680
1681 for (size_t i = m_variables.numberOfArguments(); i--;) {
1682 if (m_codeBlock->isCaptured(argumentToOperand(i)))
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001683 m_variables.argument(i).makeTop();
1684 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001685}
1686
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001687inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001688{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001689 if (!m_haveStructures)
1690 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001691 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001692 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001693 for (size_t i = m_variables.numberOfArguments(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001694 m_variables.argument(i).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001695 for (size_t i = m_variables.numberOfLocals(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001696 m_variables.local(i).clobberStructures();
1697 m_haveStructures = false;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001698 m_didClobber = true;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001699}
1700
1701inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1702{
1703 if (nodeIndex == NoNode)
1704 return false;
1705
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001706 AbstractValue source;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001707
1708 Node& node = m_graph[nodeIndex];
1709 if (!node.refCount())
1710 return false;
1711
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001712#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001713 dataLog(" It's live, node @%u.\n", nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001714#endif
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001715
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001716 if (node.variableAccessData()->isCaptured()) {
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001717 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001718#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001719 dataLog(" Transfering ");
1720 source.dump(WTF::dataFile());
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001721 dataLog(" from last access due to captured variable.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001722#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001723 } else {
1724 switch (node.op()) {
1725 case Phi:
1726 case SetArgument:
1727 case Flush:
1728 // The block transfers the value from head to tail.
1729 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001730#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001731 dataLog(" Transfering ");
1732 source.dump(WTF::dataFile());
1733 dataLog(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001734#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001735 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001736
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001737 case GetLocal:
1738 // The block refines the value with additional speculations.
1739 source = forNode(nodeIndex);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001740#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001741 dataLog(" Refining to ");
1742 source.dump(WTF::dataFile());
1743 dataLog("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001744#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001745 break;
1746
1747 case SetLocal:
1748 // The block sets the variable, and potentially refines it, both
1749 // before and after setting it.
1750 if (node.variableAccessData()->shouldUseDoubleFormat()) {
1751 // FIXME: This unnecessarily loses precision.
fpizlo@apple.com62336162012-06-07 01:35:59 +00001752 source.set(SpecDouble);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001753 } else
1754 source = forNode(node.child1());
1755#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1756 dataLog(" Setting to ");
1757 source.dump(WTF::dataFile());
1758 dataLog("\n");
1759#endif
1760 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001761
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001762 default:
1763 ASSERT_NOT_REACHED();
1764 break;
1765 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001766 }
1767
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001768 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001769 // Abstract execution did not change the output value of the variable, for this
1770 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001771#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001772 dataLog(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001773#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001774 return false;
1775 }
1776
1777 // Abstract execution reached a new conclusion about the speculations reached about
1778 // this variable after execution of this basic block. Update the state, and return
1779 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001780 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001781#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comd095b242012-02-12 03:21:32 +00001782 dataLog(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001783#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001784 return true;
1785}
1786
1787inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1788{
1789 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1790 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1791
1792 bool changed = false;
1793
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001794 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1795 AbstractValue& destination = to->valuesAtHead.argument(argument);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001796 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1797 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001798
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001799 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1800 AbstractValue& destination = to->valuesAtHead.local(local);
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001801 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1802 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001803
1804 if (!to->cfaHasVisited)
1805 changed = true;
1806
1807 to->cfaShouldRevisit |= changed;
1808
1809 return changed;
1810}
1811
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001812inline bool AbstractState::mergeToSuccessors(
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001813 Graph& graph, BasicBlock* basicBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001814{
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001815 Node& terminal = graph[basicBlock->last()];
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001816
1817 ASSERT(terminal.isTerminal());
1818
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001819 switch (terminal.op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001820 case Jump: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001821 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001822#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1823 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1824#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001825 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001826 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001827
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001828 case Branch: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001829 ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001830 bool changed = false;
1831#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1832 dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
1833#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001834 if (basicBlock->cfaBranchDirection != TakeFalse)
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001835 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001836#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1837 dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1838#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001839 if (basicBlock->cfaBranchDirection != TakeTrue)
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001840 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001841 return changed;
1842 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001843
1844 case Return:
1845 case Throw:
1846 case ThrowReferenceError:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001847 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001848 return false;
1849
1850 default:
1851 ASSERT_NOT_REACHED();
1852 return false;
1853 }
1854}
1855
1856inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1857{
1858 if (destinationNodeIndex == NoNode)
1859 return false;
1860
1861 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1862
1863 // FIXME: We could do some sparse conditional propagation here!
1864
1865 return destination.merge(source);
1866}
1867
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001868void AbstractState::dump(FILE* out)
1869{
1870 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001871 for (size_t i = 0; i < m_block->size(); ++i) {
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001872 NodeIndex index = m_block->at(i);
1873 AbstractValue& value = m_nodes[index];
1874 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001875 continue;
1876 if (first)
1877 first = false;
1878 else
1879 fprintf(out, " ");
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001880 fprintf(out, "@%lu:", static_cast<unsigned long>(index));
1881 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001882 }
1883}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001884
1885} } // namespace JSC::DFG
1886
1887#endif // ENABLE(DFG_JIT)
1888