blob: ba277ca035a48c81c4bba7f313c3cc843678fcba [file] [log] [blame]
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001/*
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002 * Copyright (C) 2011, 2012, 2013 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"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000033#include "GetByIdStatus.h"
oliver@apple.come722ad02013-01-09 02:37:29 +000034#include "Operations.h"
fpizlo@apple.comc2c67632012-11-17 08:37:14 +000035#include "PutByIdStatus.h"
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +000036#include "StringObject.h"
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000037
38namespace JSC { namespace DFG {
39
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000040AbstractState::AbstractState(Graph& graph)
41 : m_codeBlock(graph.m_codeBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000042 , m_graph(graph)
fpizlo@apple.comadf274c2012-02-18 07:56:10 +000043 , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000044 , m_block(0)
45{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000046}
47
48AbstractState::~AbstractState() { }
49
50void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
51{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000052 ASSERT(!m_block);
53
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000054 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
55 ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
56 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
57
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000058 for (size_t i = 0; i < basicBlock->size(); i++)
fpizlo@apple.comf8f33842013-01-14 06:58:57 +000059 forNode(basicBlock->at(i)).clear();
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +000060
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000061 m_variables = basicBlock->valuesAtHead;
62 m_haveStructures = false;
63 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +000064 if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000065 m_haveStructures = true;
66 break;
67 }
68 }
69 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +000070 if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000071 m_haveStructures = true;
72 break;
73 }
74 }
75
76 basicBlock->cfaShouldRevisit = false;
77 basicBlock->cfaHasVisited = true;
78 m_block = basicBlock;
79 m_isValid = true;
fpizlo@apple.com3187c922012-05-18 21:47:53 +000080 m_foundConstants = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +000081 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000082}
83
84void AbstractState::initialize(Graph& graph)
85{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000086 BasicBlock* root = graph.m_blocks[0].get();
87 root->cfaShouldRevisit = true;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000088 root->cfaHasVisited = false;
89 root->cfaFoundConstants = false;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000090 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000091 Node* node = root->variablesAtHead.argument(i);
92 ASSERT(node->op() == SetArgument);
fpizlo@apple.com5470ec72013-02-25 20:23:55 +000093 if (!node->variableAccessData()->shouldUnboxIfPossible()) {
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +000094 root->valuesAtHead.argument(i).makeTop();
95 continue;
96 }
97
oliver@apple.comea771492013-07-25 03:58:38 +000098 SpeculatedType prediction =
99 node->variableAccessData()->argumentAwarePrediction();
fpizlo@apple.com62336162012-06-07 01:35:59 +0000100 if (isInt32Speculation(prediction))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000101 root->valuesAtHead.argument(i).setType(SpecInt32);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000102 else if (isBooleanSpeculation(prediction))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000103 root->valuesAtHead.argument(i).setType(SpecBoolean);
fpizlo@apple.com00528432012-07-20 03:50:02 +0000104 else if (isCellSpeculation(prediction))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000105 root->valuesAtHead.argument(i).setType(SpecCell);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000106 else
107 root->valuesAtHead.argument(i).makeTop();
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000108
109 root->valuesAtTail.argument(i).clear();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000110 }
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000111 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000112 Node* node = root->variablesAtHead.local(i);
113 if (node && node->variableAccessData()->isCaptured())
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000114 root->valuesAtHead.local(i).makeTop();
115 else
116 root->valuesAtHead.local(i).clear();
117 root->valuesAtTail.local(i).clear();
118 }
119 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
120 BasicBlock* block = graph.m_blocks[blockIndex].get();
121 if (!block)
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000122 continue;
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000123 if (!block->isReachable)
124 continue;
125 block->cfaShouldRevisit = false;
126 block->cfaHasVisited = false;
127 block->cfaFoundConstants = false;
128 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
129 block->valuesAtHead.argument(i).clear();
130 block->valuesAtTail.argument(i).clear();
131 }
132 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
133 block->valuesAtHead.local(i).clear();
134 block->valuesAtTail.local(i).clear();
135 }
fpizlo@apple.com0fd7ec92012-08-19 21:59:12 +0000136 if (!block->isOSRTarget)
137 continue;
138 if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
139 continue;
140 for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
141 AbstractValue value;
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000142 value.setMostSpecific(graph, graph.m_mustHandleValues[i]);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +0000143 int operand = graph.m_mustHandleValues.operandForIndex(i);
144 block->valuesAtHead.operand(operand).merge(value);
145#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000146 dataLogF(" Initializing Block #%u, operand r%d, to ", blockIndex, operand);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +0000147 block->valuesAtHead.operand(operand).dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000148 dataLogF("\n");
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +0000149#endif
fpizlo@apple.com0fd7ec92012-08-19 21:59:12 +0000150 }
151 block->cfaShouldRevisit = true;
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000152 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000153}
154
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000155bool AbstractState::endBasicBlock(MergeMode mergeMode)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000156{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000157 ASSERT(m_block);
158
159 BasicBlock* block = m_block; // Save the block for successor merging.
160
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000161 block->cfaFoundConstants = m_foundConstants;
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000162 block->cfaDidFinish = m_isValid;
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000163 block->cfaBranchDirection = m_branchDirection;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000164
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000165 if (!m_isValid) {
166 reset();
167 return false;
168 }
169
170 bool changed = false;
171
172 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000173 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
174#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000175 dataLogF(" Merging state for argument %zu.\n", argument);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000176#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000177 AbstractValue& destination = block->valuesAtTail.argument(argument);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000178 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000179 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000180
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000181 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
182#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000183 dataLogF(" Merging state for local %zu.\n", local);
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000184#endif
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +0000185 AbstractValue& destination = block->valuesAtTail.local(local);
fpizlo@apple.com75824e82012-05-30 17:02:49 +0000186 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
fpizlo@apple.comfab66052011-11-22 03:02:33 +0000187 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000188 }
189
190 ASSERT(mergeMode != DontMerge || !changed);
191
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000192#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000193 dataLogF(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000194#endif
195
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000196 reset();
197
198 if (mergeMode != MergeToSuccessors)
199 return changed;
200
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000201 return mergeToSuccessors(m_graph, block);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000202}
203
204void AbstractState::reset()
205{
206 m_block = 0;
207 m_isValid = false;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000208 m_branchDirection = InvalidBranchDirection;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000209}
210
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000211AbstractState::BooleanResult AbstractState::booleanResult(Node* node, AbstractValue& value)
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000212{
213 JSValue childConst = value.value();
214 if (childConst) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000215 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->codeOrigin)->globalExec()))
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000216 return DefinitelyTrue;
217 return DefinitelyFalse;
218 }
219
220 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
221 if (isCellSpeculation(value.m_type)
222 && value.m_currentKnownStructure.hasSingleton()) {
223 Structure* structure = value.m_currentKnownStructure.singleton();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000224 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000225 && structure->typeInfo().type() != StringType)
226 return DefinitelyTrue;
227 }
228
229 return UnknownBooleanResult;
230}
231
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000232bool AbstractState::startExecuting(Node* node)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000233{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000234 ASSERT(m_block);
235 ASSERT(m_isValid);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000236
237 m_didClobber = false;
238
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000239 node->setCanExit(false);
240
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000241 if (!node->shouldGenerate())
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000242 return false;
243
244 return true;
245}
246
247bool AbstractState::startExecuting(unsigned indexInBlock)
248{
249 return startExecuting(m_block->at(indexInBlock));
250}
251
252void AbstractState::executeEdges(Node* node)
253{
254 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
255}
256
257void AbstractState::executeEdges(unsigned indexInBlock)
258{
259 executeEdges(m_block->at(indexInBlock));
260}
261
262void AbstractState::verifyEdge(Node*, Edge edge)
263{
264 RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
265}
266
267void AbstractState::verifyEdges(Node* node)
268{
269 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
270}
271
272bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
273{
274 if (!ASSERT_DISABLED)
275 verifyEdges(node);
276
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000277 switch (node->op()) {
fpizlo@apple.com53aa8dc2011-11-15 21:54:38 +0000278 case JSConstant:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +0000279 case WeakJSConstant:
280 case PhantomArguments: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000281 forNode(node).set(m_graph, m_graph.valueOfJSConstant(node));
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000282 break;
283 }
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000284
285 case Identity: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000286 forNode(node) = forNode(node->child1());
fpizlo@apple.com5d271712012-11-16 06:19:54 +0000287 break;
288 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000289
290 case GetLocal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000291 VariableAccessData* variableAccessData = node->variableAccessData();
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000292 if (variableAccessData->prediction() == SpecNone) {
293 m_isValid = false;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000294 break;
295 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000296 AbstractValue value = m_variables.operand(variableAccessData->local());
297 if (!variableAccessData->isCaptured()) {
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000298 if (value.isClear())
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000299 node->setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000300 }
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000301 if (value.value())
302 m_foundConstants = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000303 forNode(node) = value;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000304 break;
305 }
306
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000307 case GetLocalUnlinked: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000308 AbstractValue value = m_variables.operand(node->unlinkedLocal());
fpizlo@apple.com8e537cd2012-06-01 23:54:36 +0000309 if (value.value())
310 m_foundConstants = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000311 forNode(node) = value;
fpizlo@apple.com9b928722012-05-24 00:18:55 +0000312 break;
313 }
314
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000315 case SetLocal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000316 m_variables.operand(node->local()) = forNode(node->child1());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000317 break;
318 }
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000319
320 case MovHintAndCheck: {
321 // Don't need to do anything. A MovHint is effectively a promise that the SetLocal
322 // was dead.
323 break;
324 }
325
326 case MovHint:
327 case ZombieHint: {
328 RELEASE_ASSERT_NOT_REACHED();
329 break;
330 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000331
332 case SetArgument:
333 // Assert that the state of arguments has been set.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000334 ASSERT(!m_block->valuesAtHead.operand(node->local()).isClear());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000335 break;
336
337 case BitAnd:
338 case BitOr:
339 case BitXor:
340 case BitRShift:
341 case BitLShift:
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000342 case BitURShift: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000343 JSValue left = forNode(node->child1()).value();
344 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000345 if (left && right && left.isInt32() && right.isInt32()) {
346 int32_t a = left.asInt32();
347 int32_t b = right.asInt32();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000348 bool constantWasSet;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000349 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000350 case BitAnd:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000351 constantWasSet = trySetConstant(node, JSValue(a & b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000352 break;
353 case BitOr:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000354 constantWasSet = trySetConstant(node, JSValue(a | b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000355 break;
356 case BitXor:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000357 constantWasSet = trySetConstant(node, JSValue(a ^ b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000358 break;
359 case BitRShift:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000360 constantWasSet = trySetConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000361 break;
362 case BitLShift:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000363 constantWasSet = trySetConstant(node, JSValue(a << static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000364 break;
365 case BitURShift:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000366 constantWasSet = trySetConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000367 break;
368 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000369 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000370 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000371 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000372 if (constantWasSet) {
373 m_foundConstants = true;
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000374 break;
375 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000376 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000377 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000378 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000379 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000380
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000381 case UInt32ToNumber: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000382 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000383 if (child && child.isNumber()) {
384 ASSERT(child.isInt32());
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000385 if (trySetConstant(node, JSValue(child.asUInt32()))) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000386 m_foundConstants = true;
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000387 break;
388 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000389 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000390 if (!node->canSpeculateInteger())
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000391 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000392 else {
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000393 forNode(node).setType(SpecInt32);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000394 node->setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +0000395 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000396 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000397 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000398
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000399 case DoubleAsInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000400 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000401 if (child && child.isNumber()) {
402 double asDouble = child.asNumber();
403 int32_t asInt = JSC::toInt32(asDouble);
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000404 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000405 && trySetConstant(node, JSValue(asInt))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000406 m_foundConstants = true;
407 break;
408 }
409 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000410 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000411 forNode(node).setType(SpecInt32);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000412 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000413 }
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000414
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000415 case ValueToInt32: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000416 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000417 if (child && child.isNumber()) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000418 bool constantWasSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000419 if (child.isInt32())
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000420 constantWasSet = trySetConstant(node, child);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000421 else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000422 constantWasSet = trySetConstant(node, JSValue(JSC::toInt32(child.asDouble())));
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000423 if (constantWasSet) {
424 m_foundConstants = true;
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000425 break;
426 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000427 }
fpizlo@apple.com9c7addf2012-03-08 10:01:32 +0000428
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000429 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000430 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000431 }
oliver@apple.com64367322013-04-26 00:41:38 +0000432
fpizlo@apple.com393289d2013-02-12 00:29:20 +0000433 case Int32ToDouble:
434 case ForwardInt32ToDouble: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000435 JSValue child = forNode(node->child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000436 if (child && child.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000437 && trySetConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000438 m_foundConstants = true;
439 break;
440 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000441 if (isInt32Speculation(forNode(node->child1()).m_type))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000442 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000443 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000444 forNode(node).setType(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000445 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000446 }
fpizlo@apple.coma1cc0fd2012-04-24 20:43:01 +0000447
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000448 case ValueAdd:
449 case ArithAdd: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000450 JSValue left = forNode(node->child1()).value();
451 JSValue right = forNode(node->child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000452 if (left && right && left.isNumber() && right.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000453 && trySetConstant(node, JSValue(left.asNumber() + right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000454 m_foundConstants = true;
455 break;
456 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000457 switch (node->binaryUseKind()) {
458 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000459 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000460 if (!nodeCanTruncateInteger(node->arithNodeFlags()))
461 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000462 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000463 case NumberUse:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000464 if (isRealNumberSpeculation(forNode(node->child1()).m_type)
465 && isRealNumberSpeculation(forNode(node->child2()).m_type))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000466 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000467 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000468 forNode(node).setType(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000469 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000470 default:
471 RELEASE_ASSERT(node->op() == ValueAdd);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000472 clobberWorld(node->codeOrigin, indexInBlock);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000473 forNode(node).setType(SpecString | SpecInt32 | SpecNumber);
fpizlo@apple.comc0d21912012-02-14 21:26:26 +0000474 break;
475 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000476 break;
477 }
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000478
479 case MakeRope: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000480 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000481 break;
482 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000483
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000484 case ArithSub: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000485 JSValue left = forNode(node->child1()).value();
486 JSValue right = forNode(node->child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000487 if (left && right && left.isNumber() && right.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000488 && trySetConstant(node, JSValue(left.asNumber() - right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000489 m_foundConstants = true;
490 break;
491 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000492 switch (node->binaryUseKind()) {
493 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000494 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000495 if (!nodeCanTruncateInteger(node->arithNodeFlags()))
496 node->setCanExit(true);
497 break;
498 case NumberUse:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000499 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000500 break;
501 default:
502 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000503 break;
504 }
fpizlo@apple.com0c31ace2012-02-01 23:08:54 +0000505 break;
506 }
507
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000508 case ArithNegate: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000509 JSValue child = forNode(node->child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000510 if (child && child.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000511 && trySetConstant(node, JSValue(-child.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000512 m_foundConstants = true;
513 break;
514 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000515 switch (node->child1().useKind()) {
516 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000517 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000518 if (!nodeCanTruncateInteger(node->arithNodeFlags()))
519 node->setCanExit(true);
520 break;
521 case NumberUse:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000522 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000523 break;
524 default:
525 RELEASE_ASSERT_NOT_REACHED();
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000526 break;
527 }
barraclough@apple.com8ff7e8c2012-02-28 00:31:28 +0000528 break;
529 }
530
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000531 case ArithMul: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000532 JSValue left = forNode(node->child1()).value();
533 JSValue right = forNode(node->child2()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000534 if (left && right && left.isNumber() && right.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000535 && trySetConstant(node, JSValue(left.asNumber() * right.asNumber()))) {
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000536 m_foundConstants = true;
537 break;
538 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000539 switch (node->binaryUseKind()) {
540 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000541 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000542 if (!nodeCanTruncateInteger(node->arithNodeFlags())
543 || !nodeCanIgnoreNegativeZero(node->arithNodeFlags()))
544 node->setCanExit(true);
545 break;
546 case NumberUse:
547 if (isRealNumberSpeculation(forNode(node->child1()).m_type)
548 || isRealNumberSpeculation(forNode(node->child2()).m_type))
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000549 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000550 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000551 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000552 break;
553 default:
554 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000555 break;
556 }
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000557 break;
558 }
oliver@apple.com64367322013-04-26 00:41:38 +0000559
560 case ArithIMul: {
oliver@apple.com67e0f332013-07-25 03:59:00 +0000561 forNode(node).setType(SpecInt32);
oliver@apple.com64367322013-04-26 00:41:38 +0000562 break;
563 }
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000564
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000565 case ArithDiv:
566 case ArithMin:
fpizlo@apple.com19a172792012-03-24 20:15:57 +0000567 case ArithMax:
568 case ArithMod: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000569 JSValue left = forNode(node->child1()).value();
570 JSValue right = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000571 if (left && right && left.isNumber() && right.isNumber()) {
572 double a = left.asNumber();
573 double b = right.asNumber();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000574 bool constantWasSet;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000575 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000576 case ArithDiv:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000577 constantWasSet = trySetConstant(node, JSValue(a / b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000578 break;
579 case ArithMin:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000580 constantWasSet = trySetConstant(node, JSValue(a < b ? a : (b <= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000581 break;
582 case ArithMax:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000583 constantWasSet = trySetConstant(node, JSValue(a > b ? a : (b >= a ? b : a + b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000584 break;
585 case ArithMod:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000586 constantWasSet = trySetConstant(node, JSValue(fmod(a, b)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000587 break;
588 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000589 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000590 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000591 break;
592 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000593 if (constantWasSet) {
594 m_foundConstants = true;
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000595 break;
596 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000597 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000598 switch (node->binaryUseKind()) {
599 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000600 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000601 node->setCanExit(true);
602 break;
603 case NumberUse:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000604 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000605 break;
606 default:
607 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000608 break;
609 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000610 break;
611 }
612
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000613 case ArithAbs: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000614 JSValue child = forNode(node->child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000615 if (child && child.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000616 && trySetConstant(node, JSValue(fabs(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000617 m_foundConstants = true;
618 break;
619 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000620 switch (node->child1().useKind()) {
621 case Int32Use:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000622 forNode(node).setType(SpecInt32);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000623 node->setCanExit(true);
624 break;
625 case NumberUse:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000626 forNode(node).setType(SpecDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000627 break;
628 default:
629 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000630 break;
631 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000632 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000633 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000634
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000635 case ArithSqrt: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000636 JSValue child = forNode(node->child1()).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000637 if (child && child.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000638 && trySetConstant(node, JSValue(sqrt(child.asNumber())))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000639 m_foundConstants = true;
640 break;
641 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000642 forNode(node).setType(SpecDouble);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000643 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000644 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000645
646 case LogicalNot: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000647 bool didSetConstant = false;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000648 switch (booleanResult(node, forNode(node->child1()))) {
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000649 case DefinitelyTrue:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000650 didSetConstant = trySetConstant(node, jsBoolean(false));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000651 break;
652 case DefinitelyFalse:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000653 didSetConstant = trySetConstant(node, jsBoolean(true));
fpizlo@apple.com367a1102012-11-10 23:33:29 +0000654 break;
655 default:
656 break;
657 }
658 if (didSetConstant) {
fpizlo@apple.com152abff2012-06-19 23:10:12 +0000659 m_foundConstants = true;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +0000660 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000661 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000662 switch (node->child1().useKind()) {
663 case BooleanUse:
664 case Int32Use:
665 case NumberUse:
666 case UntypedUse:
667 break;
668 case ObjectOrOtherUse:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000669 node->setCanExit(true);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000670 break;
671 default:
672 RELEASE_ASSERT_NOT_REACHED();
673 break;
674 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000675 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000676 break;
677 }
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000678
679 case IsUndefined:
680 case IsBoolean:
681 case IsNumber:
682 case IsString:
683 case IsObject:
684 case IsFunction: {
oliver@apple.com67e0f332013-07-25 03:59:00 +0000685 node->setCanExit(
686 node->op() == IsUndefined
687 && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->codeOrigin));
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000688 JSValue child = forNode(node->child1()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000689 if (child) {
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000690 bool constantWasSet;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000691 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000692 case IsUndefined:
oliver@apple.com67e0f332013-07-25 03:59:00 +0000693 constantWasSet = trySetConstant(node, jsBoolean(
694 child.isCell()
695 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin))
696 : child.isUndefined()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000697 break;
698 case IsBoolean:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000699 constantWasSet = trySetConstant(node, jsBoolean(child.isBoolean()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000700 break;
701 case IsNumber:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000702 constantWasSet = trySetConstant(node, jsBoolean(child.isNumber()));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000703 break;
704 case IsString:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000705 constantWasSet = trySetConstant(node, jsBoolean(isJSString(child)));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000706 break;
oliver@apple.come722ad02013-01-09 02:37:29 +0000707 case IsObject:
708 if (child.isNull() || !child.isObject()) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000709 constantWasSet = trySetConstant(node, jsBoolean(child.isNull()));
oliver@apple.come722ad02013-01-09 02:37:29 +0000710 break;
711 }
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000712 default:
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000713 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000714 break;
715 }
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000716 if (constantWasSet) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000717 m_foundConstants = true;
718 break;
719 }
720 }
oliver@apple.come722ad02013-01-09 02:37:29 +0000721
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000722 forNode(node).setType(SpecBoolean);
fpizlo@apple.com1d216892012-04-12 00:55:44 +0000723 break;
724 }
oliver@apple.come722ad02013-01-09 02:37:29 +0000725
726 case TypeOf: {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000727 VM* vm = m_codeBlock->vm();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000728 JSValue child = forNode(node->child1()).value();
729 AbstractValue& abstractChild = forNode(node->child1());
oliver@apple.come722ad02013-01-09 02:37:29 +0000730 if (child) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000731 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->codeOrigin), child);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000732 if (trySetConstant(node, typeString)) {
oliver@apple.come722ad02013-01-09 02:37:29 +0000733 m_foundConstants = true;
734 break;
735 }
736 } else if (isNumberSpeculation(abstractChild.m_type)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000737 if (trySetConstant(node, vm->smallStrings.numberString())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000738 forNode(node->child1()).filter(SpecNumber);
oliver@apple.come722ad02013-01-09 02:37:29 +0000739 m_foundConstants = true;
740 break;
741 }
742 } else if (isStringSpeculation(abstractChild.m_type)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000743 if (trySetConstant(node, vm->smallStrings.stringString())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000744 forNode(node->child1()).filter(SpecString);
oliver@apple.come722ad02013-01-09 02:37:29 +0000745 m_foundConstants = true;
746 break;
747 }
748 } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000749 if (trySetConstant(node, vm->smallStrings.objectString())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000750 forNode(node->child1()).filter(SpecFinalObject | SpecArray | SpecArguments);
oliver@apple.come722ad02013-01-09 02:37:29 +0000751 m_foundConstants = true;
752 break;
753 }
754 } else if (isFunctionSpeculation(abstractChild.m_type)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000755 if (trySetConstant(node, vm->smallStrings.functionString())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000756 forNode(node->child1()).filter(SpecFunction);
oliver@apple.come722ad02013-01-09 02:37:29 +0000757 m_foundConstants = true;
758 break;
759 }
760 } else if (isBooleanSpeculation(abstractChild.m_type)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000761 if (trySetConstant(node, vm->smallStrings.booleanString())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000762 forNode(node->child1()).filter(SpecBoolean);
oliver@apple.come722ad02013-01-09 02:37:29 +0000763 m_foundConstants = true;
764 break;
765 }
fpizlo@apple.comcd81b572013-02-11 21:39:35 +0000766 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000767
768 switch (node->child1().useKind()) {
769 case StringUse:
770 case CellUse:
fpizlo@apple.comcd81b572013-02-11 21:39:35 +0000771 node->setCanExit(true);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000772 break;
773 case UntypedUse:
774 break;
775 default:
776 RELEASE_ASSERT_NOT_REACHED();
777 break;
oliver@apple.come722ad02013-01-09 02:37:29 +0000778 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000779 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
oliver@apple.come722ad02013-01-09 02:37:29 +0000780 break;
781 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000782
783 case CompareLess:
784 case CompareLessEq:
785 case CompareGreater:
786 case CompareGreaterEq:
fpizlo@apple.comb03b1402013-02-11 22:23:08 +0000787 case CompareEq:
788 case CompareEqConstant: {
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000789 bool constantWasSet = false;
790
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000791 JSValue leftConst = forNode(node->child1()).value();
792 JSValue rightConst = forNode(node->child2()).value();
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000793 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
794 double a = leftConst.asNumber();
795 double b = rightConst.asNumber();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000796 switch (node->op()) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000797 case CompareLess:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000798 constantWasSet = trySetConstant(node, jsBoolean(a < b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000799 break;
800 case CompareLessEq:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000801 constantWasSet = trySetConstant(node, jsBoolean(a <= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000802 break;
803 case CompareGreater:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000804 constantWasSet = trySetConstant(node, jsBoolean(a > b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000805 break;
806 case CompareGreaterEq:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000807 constantWasSet = trySetConstant(node, jsBoolean(a >= b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000808 break;
809 case CompareEq:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000810 constantWasSet = trySetConstant(node, jsBoolean(a == b));
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000811 break;
812 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000813 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000814 constantWasSet = false;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000815 break;
816 }
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000817 }
818
fpizlo@apple.comb03b1402013-02-11 22:23:08 +0000819 if (!constantWasSet && (node->op() == CompareEqConstant || node->op() == CompareEq)) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000820 SpeculatedType leftType = forNode(node->child1()).m_type;
821 SpeculatedType rightType = forNode(node->child2()).m_type;
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000822 if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
823 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000824 constantWasSet = trySetConstant(node, jsBoolean(false));
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000825 }
826
827 if (constantWasSet) {
828 m_foundConstants = true;
fpizlo@apple.comf884bb72012-11-09 01:57:14 +0000829 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000830 }
831
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000832 forNode(node).setType(SpecBoolean);
fpizlo@apple.com8b7cf382012-03-31 02:21:35 +0000833
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000834 // This is overly conservative. But the only thing this prevents is store elimination,
835 // and how likely is it, really, that you'll have redundant stores across a comparison
836 // operation? Comparison operations are typically at the end of basic blocks, so
837 // unless we have global store elimination (super unlikely given how unprofitable that
838 // optimization is to begin with), you aren't going to be wanting to store eliminate
839 // across an equality op.
840 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000841 break;
842 }
843
fpizlo@apple.comb03b1402013-02-11 22:23:08 +0000844 case CompareStrictEq:
845 case CompareStrictEqConstant: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000846 Node* leftNode = node->child1().node();
847 Node* rightNode = node->child2().node();
848 JSValue left = forNode(leftNode).value();
849 JSValue right = forNode(rightNode).value();
fpizlo@apple.comcacd7dc2012-07-09 23:28:53 +0000850 if (left && right && left.isNumber() && right.isNumber()
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000851 && trySetConstant(node, jsBoolean(left.asNumber() == right.asNumber()))) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000852 m_foundConstants = true;
853 break;
854 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000855 forNode(node).setType(SpecBoolean);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000856 node->setCanExit(true); // This is overly conservative.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000857 break;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000858 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000859
860 case StringCharCodeAt:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000861 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000862 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000863 break;
864
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000865 case StringFromCharCode:
oliver@apple.com67e0f332013-07-25 03:59:00 +0000866 forNode(node).setType(SpecString);
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000867 break;
868
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000869 case StringCharAt:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000870 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000871 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000872 break;
873
874 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000875 node->setCanExit(true);
876 switch (node->arrayMode().type()) {
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +0000877 case Array::SelectUsingPredictions:
fpizlo@apple.com97af5762012-09-19 22:36:44 +0000878 case Array::Unprofiled:
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000879 case Array::Undecided:
oliver@apple.com5598c182013-01-23 22:25:07 +0000880 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000881 break;
882 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000883 m_isValid = false;
884 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000885 case Array::Generic:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000886 clobberWorld(node->codeOrigin, indexInBlock);
887 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000888 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000889 case Array::String:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000890 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000891 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000892 case Array::Arguments:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000893 forNode(node).makeTop();
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000894 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000895 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000896 if (node->arrayMode().isOutOfBounds()) {
897 clobberWorld(node->codeOrigin, indexInBlock);
898 forNode(node).makeTop();
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000899 } else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000900 forNode(node).setType(SpecInt32);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000901 break;
902 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000903 if (node->arrayMode().isOutOfBounds()) {
904 clobberWorld(node->codeOrigin, indexInBlock);
905 forNode(node).makeTop();
906 } else if (node->arrayMode().isSaneChain())
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000907 forNode(node).setType(SpecDouble);
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000908 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000909 forNode(node).setType(SpecDoubleReal);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000910 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000911 case Array::Contiguous:
912 case Array::ArrayStorage:
913 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000914 if (node->arrayMode().isOutOfBounds())
915 clobberWorld(node->codeOrigin, indexInBlock);
916 forNode(node).makeTop();
fpizlo@apple.comfa34ff82012-09-05 01:27:50 +0000917 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000918 case Array::Int8Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000919 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000920 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000921 case Array::Int16Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000922 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000923 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000924 case Array::Int32Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000925 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000926 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000927 case Array::Uint8Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000928 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000929 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000930 case Array::Uint8ClampedArray:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000931 forNode(node).setType(SpecInt32);
caio.oliveira@openbossa.org992fc372012-01-18 01:11:16 +0000932 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000933 case Array::Uint16Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000934 forNode(node).setType(SpecInt32);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000935 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000936 case Array::Uint32Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000937 if (node->shouldSpeculateInteger())
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000938 forNode(node).setType(SpecInt32);
fpizlo@apple.com691ac792012-03-13 22:59:43 +0000939 else
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000940 forNode(node).setType(SpecDouble);
oliver@apple.comaeec3d82011-12-02 01:56:53 +0000941 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000942 case Array::Float32Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000943 forNode(node).setType(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000944 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000945 case Array::Float64Array:
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000946 forNode(node).setType(SpecDouble);
oliver@apple.com07d75732011-12-03 01:47:27 +0000947 break;
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000948 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000949 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000950 break;
oliver@apple.com07d75732011-12-03 01:47:27 +0000951 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000952 break;
953 }
954
955 case PutByVal:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000956 case PutByValAlias: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000957 node->setCanExit(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000958 switch (node->arrayMode().modeForPut().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000959 case Array::ForceExit:
fpizlo@apple.com6306b5652011-12-23 05:47:17 +0000960 m_isValid = false;
961 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000962 case Array::Generic:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000963 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000964 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000965 case Array::Int32:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000966 if (node->arrayMode().isOutOfBounds())
967 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000968 break;
969 case Array::Double:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000970 if (node->arrayMode().isOutOfBounds())
971 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000972 break;
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000973 case Array::Contiguous:
974 case Array::ArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000975 if (node->arrayMode().isOutOfBounds())
976 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +0000977 break;
978 case Array::SlowPutArrayStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000979 if (node->arrayMode().mayStoreToHole())
980 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000981 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000982 default:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000983 break;
oliver@apple.com07d75732011-12-03 01:47:27 +0000984 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000985 break;
986 }
987
988 case ArrayPush:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000989 node->setCanExit(true);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000990 clobberWorld(node->codeOrigin, indexInBlock);
oliver@apple.comfe0cc192013-07-25 03:58:58 +0000991 forNode(node).setType(SpecNumber);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000992 break;
993
994 case ArrayPop:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000995 node->setCanExit(true);
996 clobberWorld(node->codeOrigin, indexInBlock);
997 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000998 break;
999
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001000 case RegExpExec:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001001 forNode(node).makeTop();
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001002 break;
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001003
1004 case RegExpTest:
oliver@apple.com67e0f332013-07-25 03:59:00 +00001005 forNode(node).setType(SpecBoolean);
msaboff@apple.com3fc51292013-04-25 18:35:04 +00001006 break;
barraclough@apple.com077fdd42012-03-18 01:08:16 +00001007
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001008 case Jump:
1009 break;
1010
1011 case Branch: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001012 Node* child = node->child1().node();
1013 BooleanResult result = booleanResult(node, forNode(child));
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001014 if (result == DefinitelyTrue) {
1015 m_branchDirection = TakeTrue;
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001016 break;
1017 }
1018 if (result == DefinitelyFalse) {
1019 m_branchDirection = TakeFalse;
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001020 break;
1021 }
1022 // FIXME: The above handles the trivial cases of sparse conditional
1023 // constant propagation, but we can do better:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001024 // We can specialize the source variable's value on each direction of
1025 // the branch.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001026 node->setCanExit(true); // This is overly conservative.
fpizlo@apple.comdb7ba192012-05-24 02:28:52 +00001027 m_branchDirection = TakeBoth;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001028 break;
1029 }
1030
1031 case Return:
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001032 m_isValid = false;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001033 break;
1034
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001035 case Throw:
1036 case ThrowReferenceError:
1037 m_isValid = false;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001038 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001039 break;
1040
1041 case ToPrimitive: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001042 JSValue childConst = forNode(node->child1()).value();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001043 if (childConst && childConst.isNumber() && trySetConstant(node, childConst)) {
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001044 m_foundConstants = true;
1045 break;
1046 }
1047
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001048 ASSERT(node->child1().useKind() == UntypedUse);
1049
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001050 AbstractValue& source = forNode(node->child1());
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001051 AbstractValue& destination = forNode(node);
1052
1053 // NB. The more canonical way of writing this would have been:
1054 //
1055 // destination = source;
1056 // if (destination.m_type & !(SpecNumber | SpecString | SpecBoolean)) {
1057 // destination.filter(SpecNumber | SpecString | SpecBoolean);
1058 // AbstractValue string;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001059 // string.set(vm->stringStructure);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001060 // destination.merge(string);
1061 // }
1062 //
1063 // The reason why this would, in most other cases, have been better is that
1064 // then destination would preserve any non-SpeculatedType knowledge of source.
1065 // As it stands, the code below forgets any non-SpeculatedType knowledge that
1066 // source would have had. Fortunately, though, for things like strings and
1067 // numbers and booleans, we don't care about the non-SpeculatedType knowedge:
1068 // the structure won't tell us anything we don't already know, and neither
1069 // will ArrayModes. And if the source was a meaningful constant then we
1070 // would have handled that above. Unfortunately, this does mean that
1071 // ToPrimitive will currently forget string constants. But that's not a big
1072 // deal since we don't do any optimization on those currently.
1073
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001074 clobberWorld(node->codeOrigin, indexInBlock);
1075
fpizlo@apple.com62336162012-06-07 01:35:59 +00001076 SpeculatedType type = source.m_type;
1077 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1078 type &= (SpecNumber | SpecString | SpecBoolean);
1079 type |= SpecString;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001080 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001081 destination.setType(type);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001082 break;
1083 }
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001084
1085 case ToString: {
1086 switch (node->child1().useKind()) {
1087 case StringObjectUse:
1088 // This also filters that the StringObject has the primordial StringObject
1089 // structure.
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001090 forNode(node->child1()).filter(
1091 m_graph, m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001092 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1093 break;
1094 case StringOrStringObjectUse:
1095 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1096 break;
1097 case CellUse:
1098 case UntypedUse:
1099 clobberWorld(node->codeOrigin, indexInBlock);
1100 break;
1101 default:
1102 RELEASE_ASSERT_NOT_REACHED();
1103 break;
1104 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001105 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001106 break;
1107 }
1108
1109 case NewStringObject: {
1110 ASSERT(node->structure()->classInfo() == &StringObject::s_info);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001111 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001112 break;
1113 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001114
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001115 case NewArray:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001116 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001117 forNode(node).set(
1118 m_graph,
1119 m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001120 m_haveStructures = true;
1121 break;
1122
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001123 case NewArrayBuffer:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001124 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001125 forNode(node).set(
1126 m_graph,
1127 m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
fpizlo@apple.com68677de2012-10-11 19:36:04 +00001128 m_haveStructures = true;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00001129 break;
1130
fpizlo@apple.com6c89cd32012-06-26 19:42:05 +00001131 case NewArrayWithSize:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001132 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001133 forNode(node).setType(SpecArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001134 m_haveStructures = true;
1135 break;
1136
1137 case NewRegexp:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001138 forNode(node).set(m_graph, m_graph.globalObjectFor(node->codeOrigin)->regExpStructure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001139 m_haveStructures = true;
1140 break;
1141
oliver@apple.come2fe4ce2013-07-25 03:59:41 +00001142 case ToThis: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001143 AbstractValue& source = forNode(node->child1());
1144 AbstractValue& destination = forNode(node);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001145
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001146 destination = source;
1147 destination.merge(SpecObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001148 break;
1149 }
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001150
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001151 case CreateThis: {
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001152 forNode(node).setType(SpecFinalObject);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001153 break;
1154 }
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001155
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001156 case AllocationProfileWatchpoint:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001157 node->setCanExit(true);
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +00001158 break;
barraclough@apple.comcef11dc2012-05-10 18:40:29 +00001159
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001160 case NewObject:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001161 forNode(node).set(m_graph, node->structure());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001162 m_haveStructures = true;
1163 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001164
1165 case CreateActivation:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001166 forNode(node).set(
1167 m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->activationStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001168 m_haveStructures = true;
1169 break;
1170
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001171 case CreateArguments:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001172 forNode(node).set(
1173 m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->argumentsStructure());
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001174 m_haveStructures = true;
1175 break;
1176
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001177 case TearOffActivation:
fpizlo@apple.com15c03c72012-05-23 02:34:13 +00001178 case TearOffArguments:
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001179 // Does nothing that is user-visible.
1180 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001181
1182 case CheckArgumentsNotCreated:
fpizlo@apple.com62336162012-06-07 01:35:59 +00001183 if (isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001184 m_variables.operand(
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001185 m_graph.argumentsRegisterFor(node->codeOrigin)).m_type))
fpizlo@apple.comb80bc2a32012-06-02 22:58:48 +00001186 m_foundConstants = true;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001187 else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001188 node->setCanExit(true);
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001189 break;
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001190
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001191 case GetMyArgumentsLength:
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001192 // We know that this executable does not escape its arguments, so we can optimize
1193 // the arguments a bit. Note that this is not sufficient to force constant folding
1194 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1195 // We perform further optimizations on this later on.
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001196 if (node->codeOrigin.inlineCallFrame) {
1197 forNode(node).set(
1198 m_graph, jsNumber(node->codeOrigin.inlineCallFrame->arguments.size() - 1));
1199 } else
1200 forNode(node).setType(SpecInt32);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001201 node->setCanExit(
fpizlo@apple.com62336162012-06-07 01:35:59 +00001202 !isEmptySpeculation(
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001203 m_variables.operand(
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001204 m_graph.argumentsRegisterFor(node->codeOrigin)).m_type));
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001205 break;
1206
1207 case GetMyArgumentsLengthSafe:
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001208 // This potentially clobbers all structures if the arguments object had a getter
1209 // installed on the length property.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001210 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001211 // We currently make no guarantee about what this returns because it does not
1212 // speculate that the length property is actually a length.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001213 forNode(node).makeTop();
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001214 break;
1215
1216 case GetMyArgumentByVal:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001217 node->setCanExit(true);
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001218 // We know that this executable does not escape its arguments, so we can optimize
1219 // the arguments a bit. Note that this ends up being further optimized by the
1220 // ArgumentsSimplificationPhase.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001221 forNode(node).makeTop();
fpizlo@apple.com9a548f12012-05-24 05:33:09 +00001222 break;
1223
1224 case GetMyArgumentByValSafe:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001225 node->setCanExit(true);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001226 // This potentially clobbers all structures if the property we're accessing has
1227 // a getter. We don't speculate against this.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001228 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001229 // And the result is unknown.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001230 forNode(node).makeTop();
fpizlo@apple.com6d4456e2012-05-23 03:48:52 +00001231 break;
1232
fpizlo@apple.com507dca12013-07-17 23:27:31 +00001233 case NewFunction: {
1234 AbstractValue& value = forNode(node);
1235 value = forNode(node->child1());
1236
1237 if (!(value.m_type & SpecEmpty)) {
1238 m_foundConstants = true;
1239 break;
1240 }
1241
oliver@apple.com02039462013-07-25 03:59:29 +00001242 value.setType((value.m_type & ~SpecEmpty) | SpecFunction);
fpizlo@apple.com507dca12013-07-17 23:27:31 +00001243 break;
1244 }
1245
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001246 case NewFunctionExpression:
1247 case NewFunctionNoCheck:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001248 forNode(node).set(
1249 m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->functionStructure());
fpizlo@apple.com17da7f32012-02-25 23:05:38 +00001250 break;
1251
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001252 case GetCallee:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001253 forNode(node).setType(SpecFunction);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001254 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001255
1256 case SetCallee:
1257 case SetMyScope:
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001258 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001259
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001260 case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
fpizlo@apple.com20d46242012-11-30 21:56:24 +00001261 case GetMyScope:
1262 case SkipTopScope:
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001263 forNode(node).setType(SpecCellOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001264 break;
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001265
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001266 case SkipScope: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001267 JSValue child = forNode(node->child1()).value();
1268 if (child && trySetConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001269 m_foundConstants = true;
1270 break;
1271 }
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001272 forNode(node).setType(SpecCellOther);
fpizlo@apple.coma0bd0582012-12-04 20:25:24 +00001273 break;
1274 }
1275
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001276 case GetScopeRegisters:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001277 forNode(node).clear(); // The result is not a JS value.
ggaren@apple.comce086ca2012-09-23 22:48:19 +00001278 break;
1279
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001280 case GetScopedVar:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001281 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001282 break;
1283
1284 case PutScopedVar:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001285 clobberCapturedVars(node->codeOrigin);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001286 break;
1287
1288 case GetById:
fpizlo@apple.comdc03dc52012-01-17 00:53:40 +00001289 case GetByIdFlush:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001290 node->setCanExit(true);
1291 if (!node->prediction()) {
fpizlo@apple.com49bfe572011-10-31 23:50:57 +00001292 m_isValid = false;
1293 break;
1294 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001295 if (isCellSpeculation(node->child1()->prediction())) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001296 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001297 GetByIdStatus status = GetByIdStatus::computeFor(
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001298 m_graph.m_vm, structure,
oliver@apple.com02039462013-07-25 03:59:29 +00001299 m_graph.m_identifiers[node->identifierNumber()]);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001300 if (status.isSimple()) {
1301 // Assert things that we can't handle and that the computeFor() method
1302 // above won't be able to return.
1303 ASSERT(status.structureSet().size() == 1);
oliver@apple.com98fb6bf2013-07-25 03:59:44 +00001304 ASSERT(!status.chain());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001305
1306 if (status.specificValue())
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001307 forNode(node).set(m_graph, status.specificValue());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001308 else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001309 forNode(node).makeTop();
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001310 forNode(node->child1()).filter(m_graph, status.structureSet());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001311
1312 m_foundConstants = true;
1313 break;
1314 }
1315 }
1316 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001317 clobberWorld(node->codeOrigin, indexInBlock);
1318 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001319 break;
1320
1321 case GetArrayLength:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001322 node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001323 forNode(node).setType(SpecInt32);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001324 break;
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001325
1326 case CheckExecutable: {
1327 // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
1328 // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
1329 // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
1330 // https://bugs.webkit.org/show_bug.cgi?id=106201
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001331 node->setCanExit(true);
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00001332 break;
1333 }
oliver@apple.comf4596ca2011-10-19 21:25:10 +00001334
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001335 case CheckStructure:
1336 case ForwardCheckStructure: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001337 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001338 AbstractValue& value = forNode(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001339 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001340 // If this structure check is attempting to prove knowledge already held in
1341 // the futurePossibleStructure set then the constant folding phase should
1342 // turn this into a watchpoint instead.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001343 StructureSet& set = node->structureSet();
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001344 if (value.m_futurePossibleStructure.isSubsetOf(set)
1345 || value.m_currentKnownStructure.isSubsetOf(set))
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001346 m_foundConstants = true;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001347 if (!value.m_currentKnownStructure.isSubsetOf(set))
1348 node->setCanExit(true);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001349 value.filter(m_graph, set);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001350 m_haveStructures = true;
1351 break;
fpizlo@apple.com91b2c682012-05-24 06:24:36 +00001352 }
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001353
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001354 case StructureTransitionWatchpoint:
1355 case ForwardStructureTransitionWatchpoint: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001356 AbstractValue& value = forNode(node->child1());
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001357
1358 // It's only valid to issue a structure transition watchpoint if we already
1359 // know that the watchpoint covers a superset of the structures known to
1360 // belong to the set of future structures that this value may have.
1361 // Currently, we only issue singleton watchpoints (that check one structure)
1362 // and our futurePossibleStructure set can only contain zero, one, or an
1363 // infinity of structures.
oliver@apple.com67e0f332013-07-25 03:59:00 +00001364 ASSERT(
1365 value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure()))
1366 || m_graph.m_watchpoints.shouldAssumeMixedState(node->structure()->transitionWatchpointSet()));
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +00001367
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001368 value.filter(m_graph, node->structure());
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001369 m_haveStructures = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001370 node->setCanExit(true);
fpizlo@apple.com04e41152012-06-15 22:14:53 +00001371 break;
1372 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001373
1374 case PutStructure:
fpizlo@apple.com7e0f6502012-05-25 22:45:57 +00001375 case PhantomPutStructure:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001376 if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00001377 clobberStructures(indexInBlock);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001378 forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure);
fpizlo@apple.com6e0a9ed2012-09-16 02:36:22 +00001379 m_haveStructures = true;
1380 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001381 break;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00001382 case GetButterfly:
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +00001383 case AllocatePropertyStorage:
1384 case ReallocatePropertyStorage:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001385 forNode(node).clear(); // The result is not a JS value.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001386 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001387 case CheckArray: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001388 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001389 m_foundConstants = true;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001390 break;
1391 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001392 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.
1393 switch (node->arrayMode().type()) {
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001394 case Array::String:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001395 forNode(node->child1()).filter(SpecString);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001396 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001397 case Array::Int32:
1398 case Array::Double:
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001399 case Array::Contiguous:
1400 case Array::ArrayStorage:
1401 case Array::SlowPutArrayStorage:
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001402 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001403 case Array::Arguments:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001404 forNode(node->child1()).filter(SpecArguments);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001405 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001406 case Array::Int8Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001407 forNode(node->child1()).filter(SpecInt8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001408 break;
1409 case Array::Int16Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001410 forNode(node->child1()).filter(SpecInt16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001411 break;
1412 case Array::Int32Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001413 forNode(node->child1()).filter(SpecInt32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001414 break;
1415 case Array::Uint8Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001416 forNode(node->child1()).filter(SpecUint8Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001417 break;
1418 case Array::Uint8ClampedArray:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001419 forNode(node->child1()).filter(SpecUint8ClampedArray);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001420 break;
1421 case Array::Uint16Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001422 forNode(node->child1()).filter(SpecUint16Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001423 break;
1424 case Array::Uint32Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001425 forNode(node->child1()).filter(SpecUint32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001426 break;
1427 case Array::Float32Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001428 forNode(node->child1()).filter(SpecFloat32Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001429 break;
1430 case Array::Float64Array:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001431 forNode(node->child1()).filter(SpecFloat64Array);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +00001432 break;
1433 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001434 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +00001435 break;
1436 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001437 forNode(node->child1()).filterArrayModes(node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.comf08803e2012-10-26 01:57:07 +00001438 m_haveStructures = true;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001439 break;
1440 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001441 case Arrayify: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001442 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00001443 m_foundConstants = true;
fpizlo@apple.com372c6d52012-10-20 06:53:04 +00001444 break;
1445 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001446 ASSERT(node->arrayMode().conversion() == Array::Convert
1447 || node->arrayMode().conversion() == Array::RageConvert);
1448 node->setCanExit(true);
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001449 clobberStructures(indexInBlock);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001450 forNode(node->child1()).filterArrayModes(node->arrayMode().arrayModesThatPassFiltering());
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001451 m_haveStructures = true;
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001452 break;
1453 }
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001454 case ArrayifyToStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001455 AbstractValue& value = forNode(node->child1());
1456 StructureSet set = node->structure();
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001457 if (value.m_futurePossibleStructure.isSubsetOf(set)
1458 || value.m_currentKnownStructure.isSubsetOf(set))
1459 m_foundConstants = true;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001460 node->setCanExit(true);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001461 clobberStructures(indexInBlock);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001462 value.filter(m_graph, set);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001463 m_haveStructures = true;
1464 break;
1465 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001466 case GetIndexedPropertyStorage: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001467 forNode(node).clear();
oliver@apple.com43e511c2011-12-09 08:45:46 +00001468 break;
1469 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001470 case GetByOffset: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001471 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001472 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001473 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001474
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001475 case PutByOffset: {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001476 break;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001477 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001478
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001479 case CheckFunction: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001480 JSValue value = forNode(node->child1()).value();
1481 if (value == node->function()) {
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001482 m_foundConstants = true;
1483 ASSERT(value);
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001484 break;
1485 }
1486
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001487 node->setCanExit(true); // Lies! We can do better.
fpizlo@apple.comf0dc46c2013-04-24 03:18:04 +00001488 forNode(node->child1()).filterByValue(node->function());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001489 break;
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +00001490 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001491
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001492 case PutById:
1493 case PutByIdDirect:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001494 node->setCanExit(true);
1495 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001496 PutByIdStatus status = PutByIdStatus::computeFor(
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001497 m_graph.m_vm,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001498 m_graph.globalObjectFor(node->codeOrigin),
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001499 structure,
oliver@apple.com02039462013-07-25 03:59:29 +00001500 m_graph.m_identifiers[node->identifierNumber()],
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001501 node->op() == PutByIdDirect);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001502 if (status.isSimpleReplace()) {
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001503 forNode(node->child1()).filter(m_graph, structure);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001504 m_foundConstants = true;
1505 break;
1506 }
1507 if (status.isSimpleTransition()) {
1508 clobberStructures(indexInBlock);
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001509 forNode(node->child1()).set(m_graph, status.newStructure());
fpizlo@apple.comc2c67632012-11-17 08:37:14 +00001510 m_haveStructures = true;
1511 m_foundConstants = true;
1512 break;
1513 }
1514 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001515 clobberWorld(node->codeOrigin, indexInBlock);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001516 break;
1517
1518 case GetGlobalVar:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001519 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001520 break;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001521
1522 case GlobalVarWatchpoint:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001523 node->setCanExit(true);
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001524 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001525
1526 case PutGlobalVar:
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001527 case PutGlobalVarCheck:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001528 break;
1529
1530 case CheckHasInstance:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001531 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001532 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1533 break;
1534
1535 case InstanceOf:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001536 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001537 // Again, sadly, we don't propagate the fact that we've done InstanceOf
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001538 forNode(node).setType(SpecBoolean);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001539 break;
1540
1541 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +00001542 case Flush:
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +00001543 case PhantomLocal:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001544 case Breakpoint:
1545 break;
1546
1547 case Call:
1548 case Construct:
1549 case Resolve:
1550 case ResolveBase:
1551 case ResolveBaseStrictPut:
1552 case ResolveGlobal:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001553 node->setCanExit(true);
1554 clobberWorld(node->codeOrigin, indexInBlock);
1555 forNode(node).makeTop();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001556 break;
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001557
1558 case GarbageValue:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001559 clobberWorld(node->codeOrigin, indexInBlock);
1560 forNode(node).makeTop();
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001561 break;
1562
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001563 case ForceOSRExit:
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001564 node->setCanExit(true);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001565 m_isValid = false;
1566 break;
1567
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00001568 case CheckWatchdogTimer:
1569 node->setCanExit(true);
1570 break;
1571
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001572 case Phantom:
fpizlo@apple.com116a0892011-11-03 08:06:42 +00001573 case InlineStart:
fpizlo@apple.com390f57c2011-12-19 06:36:05 +00001574 case Nop:
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00001575 case CountExecution:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001576 break;
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001577
1578 case LastNodeType:
oliver@apple.com5598c182013-01-23 22:25:07 +00001579 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comd7897b12012-03-12 23:15:45 +00001580 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001581 }
1582
1583 return m_isValid;
1584}
1585
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001586bool AbstractState::executeEffects(unsigned indexInBlock)
1587{
1588 return executeEffects(indexInBlock, m_block->at(indexInBlock));
1589}
1590
1591bool AbstractState::execute(unsigned indexInBlock)
1592{
1593 Node* node = m_block->at(indexInBlock);
1594 if (!startExecuting(node))
1595 return true;
1596
1597 executeEdges(node);
1598 return executeEffects(indexInBlock, node);
1599}
1600
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001601inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1602{
fpizlo@apple.comcaa68812012-08-02 04:32:30 +00001603 clobberCapturedVars(codeOrigin);
1604 clobberStructures(indexInBlock);
1605}
1606
1607inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin)
1608{
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001609 if (codeOrigin.inlineCallFrame) {
1610 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1611 for (size_t i = capturedVars.size(); i--;) {
1612 if (!capturedVars.quickGet(i))
1613 continue;
1614 m_variables.local(i).makeTop();
1615 }
1616 } else {
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001617 for (size_t i = m_codeBlock->m_numVars; i--;) {
1618 if (m_codeBlock->isCaptured(i))
1619 m_variables.local(i).makeTop();
1620 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001621 }
ggaren@apple.com81c360e2012-09-14 02:17:01 +00001622
1623 for (size_t i = m_variables.numberOfArguments(); i--;) {
1624 if (m_codeBlock->isCaptured(argumentToOperand(i)))
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001625 m_variables.argument(i).makeTop();
1626 }
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001627}
1628
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001629inline void AbstractState::clobberStructures(unsigned indexInBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001630{
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001631 if (!m_haveStructures)
1632 return;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001633 for (size_t i = indexInBlock + 1; i--;)
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001634 forNode(m_block->at(i)).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001635 for (size_t i = m_variables.numberOfArguments(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001636 m_variables.argument(i).clobberStructures();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001637 for (size_t i = m_variables.numberOfLocals(); i--;)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001638 m_variables.local(i).clobberStructures();
1639 m_haveStructures = false;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +00001640 m_didClobber = true;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001641}
1642
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001643inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001644{
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001645 if (!node)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001646 return false;
1647
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001648 AbstractValue source;
fpizlo@apple.com359475a2013-01-15 00:53:39 +00001649
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001650 if (node->variableAccessData()->isCaptured()) {
fpizlo@apple.com359475a2013-01-15 00:53:39 +00001651 // If it's captured then we know that whatever value was stored into the variable last is the
1652 // one we care about. This is true even if the variable at tail is dead, which might happen if
1653 // the last thing we did to the variable was a GetLocal and then ended up now using the
1654 // GetLocal's result.
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001655
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001656 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001657#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001658 dataLogF(" Transfering ");
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001659 source.dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001660 dataLogF(" from last access due to captured variable.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001661#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001662 } else {
fpizlo@apple.com359475a2013-01-15 00:53:39 +00001663#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001664 dataLogF(" It's live, node @%u.\n", node->index());
fpizlo@apple.com359475a2013-01-15 00:53:39 +00001665#endif
1666
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001667 switch (node->op()) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001668 case Phi:
1669 case SetArgument:
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +00001670 case PhantomLocal:
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001671 case Flush:
1672 // The block transfers the value from head to tail.
1673 source = inVariable;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001674#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001675 dataLogF(" Transfering ");
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001676 source.dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001677 dataLogF(" from head to tail.\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001678#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001679 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001680
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001681 case GetLocal:
1682 // The block refines the value with additional speculations.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001683 source = forNode(node);
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001684#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001685 dataLogF(" Refining to ");
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001686 source.dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001687 dataLogF("\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001688#endif
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001689 break;
1690
1691 case SetLocal:
1692 // The block sets the variable, and potentially refines it, both
1693 // before and after setting it.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001694 if (node->variableAccessData()->shouldUseDoubleFormat()) {
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001695 // FIXME: This unnecessarily loses precision.
oliver@apple.comfe0cc192013-07-25 03:58:58 +00001696 source.setType(SpecDouble);
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001697 } else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001698 source = forNode(node->child1());
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001699#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001700 dataLogF(" Setting to ");
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001701 source.dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001702 dataLogF("\n");
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001703#endif
1704 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001705
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001706 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001707 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com75824e82012-05-30 17:02:49 +00001708 break;
1709 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001710 }
1711
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001712 if (destination == source) {
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001713 // Abstract execution did not change the output value of the variable, for this
1714 // basic block, on this iteration.
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001715#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001716 dataLogF(" Not changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001717#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001718 return false;
1719 }
1720
1721 // Abstract execution reached a new conclusion about the speculations reached about
1722 // this variable after execution of this basic block. Update the state, and return
1723 // true to indicate that the fixpoint must go on!
fpizlo@apple.comcd3adcc2012-03-08 09:02:48 +00001724 destination = source;
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001725#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com01902c82012-11-22 04:23:36 +00001726 dataLogF(" Changed!\n");
fpizlo@apple.comfab66052011-11-22 03:02:33 +00001727#endif
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001728 return true;
1729}
1730
1731inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1732{
1733 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1734 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1735
1736 bool changed = false;
1737
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001738 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
fpizlo@apple.com84ba1e42013-03-06 23:14:02 +00001739 AbstractValue& destination = to->valuesAtHead.argument(argument);
1740 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001741 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001742
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001743 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
fpizlo@apple.com84ba1e42013-03-06 23:14:02 +00001744 AbstractValue& destination = to->valuesAtHead.local(local);
1745 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
fpizlo@apple.comb0da6b62012-02-24 21:31:37 +00001746 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001747
1748 if (!to->cfaHasVisited)
1749 changed = true;
1750
1751 to->cfaShouldRevisit |= changed;
1752
1753 return changed;
1754}
1755
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001756inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBlock)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001757{
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001758 Node* terminal = basicBlock->last();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001759
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001760 ASSERT(terminal->isTerminal());
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001761
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001762 switch (terminal->op()) {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001763 case Jump: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001764 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001765#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
rgabor@webkit.orgd3df10d2013-02-11 17:01:06 +00001766 dataLogF(" Merging to block #%u.\n", terminal->takenBlockIndex());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001767#endif
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001768 return merge(basicBlock, graph.m_blocks[terminal->takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001769 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001770
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001771 case Branch: {
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001772 ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001773 bool changed = false;
1774#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001775 dataLogF(" Merging to block #%u.\n", terminal->takenBlockIndex());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001776#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001777 if (basicBlock->cfaBranchDirection != TakeFalse)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001778 changed |= merge(basicBlock, graph.m_blocks[terminal->takenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001779#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
rgabor@webkit.orgd3df10d2013-02-11 17:01:06 +00001780 dataLogF(" Merging to block #%u.\n", terminal->notTakenBlockIndex());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001781#endif
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001782 if (basicBlock->cfaBranchDirection != TakeTrue)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001783 changed |= merge(basicBlock, graph.m_blocks[terminal->notTakenBlockIndex()].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001784 return changed;
1785 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001786
1787 case Return:
1788 case Throw:
1789 case ThrowReferenceError:
fpizlo@apple.com367a1102012-11-10 23:33:29 +00001790 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001791 return false;
1792
1793 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001794 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001795 return false;
1796 }
1797}
1798
fpizlo@apple.com84ba1e42013-03-06 23:14:02 +00001799inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, Node* destinationNode, Node* sourceNode)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001800{
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001801 if (!destinationNode)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001802 return false;
1803
fpizlo@apple.com84ba1e42013-03-06 23:14:02 +00001804 ASSERT_UNUSED(sourceNode, sourceNode);
1805
1806 // FIXME: We could do some sparse conditional propagation here!
1807
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001808 return destination.merge(source);
1809}
1810
fpizlo@apple.com2ee99362012-11-24 03:16:47 +00001811void AbstractState::dump(PrintStream& out)
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001812{
1813 bool first = true;
yuqiang.xian@intel.comfa12f4e2012-03-07 04:56:05 +00001814 for (size_t i = 0; i < m_block->size(); ++i) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001815 Node* node = m_block->at(i);
1816 AbstractValue& value = forNode(node);
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001817 if (value.isClear())
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001818 continue;
1819 if (first)
1820 first = false;
1821 else
fpizlo@apple.com2ee99362012-11-24 03:16:47 +00001822 out.printf(" ");
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001823 out.printf("@%lu:", static_cast<unsigned long>(node->index()));
yuqiang.xian@intel.com861d9182012-03-01 07:39:31 +00001824 value.dump(out);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001825 }
1826}
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001827
1828} } // namespace JSC::DFG
1829
1830#endif // ENABLE(DFG_JIT)
1831