2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGAbstractState.h"
31 #include "CodeBlock.h"
32 #include "DFGBasicBlock.h"
33 #include "GetByIdStatus.h"
34 #include "PutByIdStatus.h"
36 namespace JSC { namespace DFG {
38 AbstractState::AbstractState(Graph& graph)
39 : m_codeBlock(graph.m_codeBlock)
41 , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
44 m_nodes.resize(graph.size());
47 AbstractState::~AbstractState() { }
49 void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
53 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
54 ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
55 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
57 // This is usually a no-op, but it is possible that the graph has grown since the
58 // abstract state was last used.
59 m_nodes.resize(m_graph.size());
61 for (size_t i = 0; i < basicBlock->size(); i++)
62 m_nodes[basicBlock->at(i)].clear();
64 m_variables = basicBlock->valuesAtHead;
65 m_haveStructures = false;
66 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
67 if (m_variables.argument(i).m_currentKnownStructure.isNeitherClearNorTop()) {
68 m_haveStructures = true;
72 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
73 if (m_variables.local(i).m_currentKnownStructure.isNeitherClearNorTop()) {
74 m_haveStructures = true;
79 basicBlock->cfaShouldRevisit = false;
80 basicBlock->cfaHasVisited = true;
83 m_foundConstants = false;
84 m_branchDirection = InvalidBranchDirection;
87 void AbstractState::initialize(Graph& graph)
89 BasicBlock* root = graph.m_blocks[0].get();
90 root->cfaShouldRevisit = true;
91 root->cfaHasVisited = false;
92 root->cfaFoundConstants = false;
93 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
94 Node& node = graph[root->variablesAtHead.argument(i)];
95 ASSERT(node.op() == SetArgument);
96 if (!node.shouldGenerate()) {
97 // The argument is dead. We don't do any checks for such arguments, and so
98 // for the purpose of the analysis, they contain no value.
99 root->valuesAtHead.argument(i).clear();
103 if (node.variableAccessData()->isCaptured()) {
104 root->valuesAtHead.argument(i).makeTop();
108 SpeculatedType prediction = node.variableAccessData()->prediction();
109 if (isInt32Speculation(prediction))
110 root->valuesAtHead.argument(i).set(SpecInt32);
111 else if (isBooleanSpeculation(prediction))
112 root->valuesAtHead.argument(i).set(SpecBoolean);
113 else if (isCellSpeculation(prediction))
114 root->valuesAtHead.argument(i).set(SpecCell);
116 root->valuesAtHead.argument(i).makeTop();
118 root->valuesAtTail.argument(i).clear();
120 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
121 NodeIndex nodeIndex = root->variablesAtHead.local(i);
122 if (nodeIndex != NoNode && graph[nodeIndex].variableAccessData()->isCaptured())
123 root->valuesAtHead.local(i).makeTop();
125 root->valuesAtHead.local(i).clear();
126 root->valuesAtTail.local(i).clear();
128 for (BlockIndex blockIndex = 1 ; blockIndex < graph.m_blocks.size(); ++blockIndex) {
129 BasicBlock* block = graph.m_blocks[blockIndex].get();
132 if (!block->isReachable)
134 block->cfaShouldRevisit = false;
135 block->cfaHasVisited = false;
136 block->cfaFoundConstants = false;
137 for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) {
138 block->valuesAtHead.argument(i).clear();
139 block->valuesAtTail.argument(i).clear();
141 for (size_t i = 0; i < block->valuesAtHead.numberOfLocals(); ++i) {
142 block->valuesAtHead.local(i).clear();
143 block->valuesAtTail.local(i).clear();
145 if (!block->isOSRTarget)
147 if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
149 for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
151 value.setMostSpecific(graph.m_mustHandleValues[i]);
152 int operand = graph.m_mustHandleValues.operandForIndex(i);
153 block->valuesAtHead.operand(operand).merge(value);
154 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
155 dataLogF(" Initializing Block #%u, operand r%d, to ", blockIndex, operand);
156 block->valuesAtHead.operand(operand).dump(WTF::dataFile());
160 block->cfaShouldRevisit = true;
164 bool AbstractState::endBasicBlock(MergeMode mergeMode)
168 BasicBlock* block = m_block; // Save the block for successor merging.
170 block->cfaFoundConstants = m_foundConstants;
171 block->cfaDidFinish = m_isValid;
172 block->cfaBranchDirection = m_branchDirection;
179 bool changed = false;
181 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
182 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
183 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
184 dataLogF(" Merging state for argument %zu.\n", argument);
186 AbstractValue& destination = block->valuesAtTail.argument(argument);
187 changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
190 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
191 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
192 dataLogF(" Merging state for local %zu.\n", local);
194 AbstractValue& destination = block->valuesAtTail.local(local);
195 changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
199 ASSERT(mergeMode != DontMerge || !changed);
201 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
202 dataLogF(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
207 if (mergeMode != MergeToSuccessors)
210 return mergeToSuccessors(m_graph, block);
213 void AbstractState::reset()
217 m_branchDirection = InvalidBranchDirection;
220 AbstractState::BooleanResult AbstractState::booleanResult(Node& node, AbstractValue& value)
222 JSValue childConst = value.value();
224 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec()))
225 return DefinitelyTrue;
226 return DefinitelyFalse;
229 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
230 if (isCellSpeculation(value.m_type)
231 && value.m_currentKnownStructure.hasSingleton()) {
232 Structure* structure = value.m_currentKnownStructure.singleton();
233 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
234 && structure->typeInfo().type() != StringType)
235 return DefinitelyTrue;
238 return UnknownBooleanResult;
241 bool AbstractState::execute(unsigned indexInBlock)
246 m_didClobber = false;
248 NodeIndex nodeIndex = m_block->at(indexInBlock);
249 Node& node = m_graph[nodeIndex];
251 if (!node.shouldGenerate())
257 case PhantomArguments: {
258 forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
259 node.setCanExit(false);
264 forNode(nodeIndex) = forNode(node.child1());
265 node.setCanExit(false);
270 VariableAccessData* variableAccessData = node.variableAccessData();
271 if (variableAccessData->prediction() == SpecNone) {
273 node.setCanExit(true);
276 bool canExit = false;
277 AbstractValue value = m_variables.operand(variableAccessData->local());
278 if (!variableAccessData->isCaptured()) {
283 m_foundConstants = true;
284 forNode(nodeIndex) = value;
285 node.setCanExit(canExit);
289 case GetLocalUnlinked: {
290 AbstractValue value = m_variables.operand(node.unlinkedLocal());
292 m_foundConstants = true;
293 forNode(nodeIndex) = value;
294 node.setCanExit(false);
299 if (node.variableAccessData()->isCaptured()
300 || m_graph.isCreatedThisArgument(node.local())) {
301 m_variables.operand(node.local()) = forNode(node.child1());
302 node.setCanExit(false);
306 if (node.variableAccessData()->shouldUseDoubleFormat()) {
307 speculateNumberUnary(node);
308 m_variables.operand(node.local()).set(SpecDouble);
312 SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
313 if (isInt32Speculation(predictedType))
314 speculateInt32Unary(node);
315 else if (isCellSpeculation(predictedType)) {
316 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
317 forNode(node.child1()).filter(SpecCell);
318 } else if (isBooleanSpeculation(predictedType))
319 speculateBooleanUnary(node);
321 node.setCanExit(false);
323 m_variables.operand(node.local()) = forNode(node.child1());
328 // Assert that the state of arguments has been set.
329 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
330 node.setCanExit(false);
339 JSValue left = forNode(node.child1()).value();
340 JSValue right = forNode(node.child2()).value();
341 if (left && right && left.isInt32() && right.isInt32()) {
342 int32_t a = left.asInt32();
343 int32_t b = right.asInt32();
347 constantWasSet = trySetConstant(nodeIndex, JSValue(a & b));
350 constantWasSet = trySetConstant(nodeIndex, JSValue(a | b));
353 constantWasSet = trySetConstant(nodeIndex, JSValue(a ^ b));
356 constantWasSet = trySetConstant(nodeIndex, JSValue(a >> static_cast<uint32_t>(b)));
359 constantWasSet = trySetConstant(nodeIndex, JSValue(a << static_cast<uint32_t>(b)));
362 constantWasSet = trySetConstant(nodeIndex, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
365 ASSERT_NOT_REACHED();
366 constantWasSet = false;
368 if (constantWasSet) {
369 m_foundConstants = true;
370 node.setCanExit(false);
374 speculateInt32Binary(node);
375 forNode(nodeIndex).set(SpecInt32);
379 case UInt32ToNumber: {
380 JSValue child = forNode(node.child1()).value();
381 if (child && child.isNumber()) {
382 ASSERT(child.isInt32());
383 if (trySetConstant(nodeIndex, JSValue(child.asUInt32()))) {
384 m_foundConstants = true;
385 node.setCanExit(false);
389 if (!node.canSpeculateInteger()) {
390 forNode(nodeIndex).set(SpecDouble);
391 node.setCanExit(false);
393 forNode(nodeIndex).set(SpecInt32);
394 node.setCanExit(true);
400 case DoubleAsInt32: {
401 JSValue child = forNode(node.child1()).value();
402 if (child && child.isNumber()) {
403 double asDouble = child.asNumber();
404 int32_t asInt = JSC::toInt32(asDouble);
405 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)
406 && trySetConstant(nodeIndex, JSValue(asInt))) {
407 m_foundConstants = true;
411 node.setCanExit(true);
412 forNode(node.child1()).filter(SpecNumber);
413 forNode(nodeIndex).set(SpecInt32);
418 JSValue child = forNode(node.child1()).value();
419 if (child && child.isNumber()) {
422 constantWasSet = trySetConstant(nodeIndex, child);
424 constantWasSet = trySetConstant(nodeIndex, JSValue(JSC::toInt32(child.asDouble())));
425 if (constantWasSet) {
426 m_foundConstants = true;
427 node.setCanExit(false);
431 if (m_graph[node.child1()].shouldSpeculateInteger())
432 speculateInt32Unary(node);
433 else if (m_graph[node.child1()].shouldSpeculateNumber())
434 speculateNumberUnary(node);
435 else if (m_graph[node.child1()].shouldSpeculateBoolean())
436 speculateBooleanUnary(node);
438 node.setCanExit(false);
440 forNode(nodeIndex).set(SpecInt32);
444 case Int32ToDouble: {
445 JSValue child = forNode(node.child1()).value();
446 if (child && child.isNumber()
447 && trySetConstant(nodeIndex, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) {
448 m_foundConstants = true;
449 node.setCanExit(false);
452 speculateNumberUnary(node);
453 if (isInt32Speculation(forNode(node.child1()).m_type))
454 forNode(nodeIndex).set(SpecDoubleReal);
456 forNode(nodeIndex).set(SpecDouble);
461 forNode(node.child1()).filter(SpecNumber);
466 JSValue left = forNode(node.child1()).value();
467 JSValue right = forNode(node.child2()).value();
468 if (left && right && left.isNumber() && right.isNumber()
469 && trySetConstant(nodeIndex, JSValue(left.asNumber() + right.asNumber()))) {
470 m_foundConstants = true;
471 node.setCanExit(false);
474 if (m_graph.addShouldSpeculateInteger(node)) {
475 speculateInt32Binary(
476 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
477 forNode(nodeIndex).set(SpecInt32);
480 if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) {
481 speculateNumberBinary(node);
482 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
483 && isRealNumberSpeculation(forNode(node.child2()).m_type))
484 forNode(nodeIndex).set(SpecDoubleReal);
486 forNode(nodeIndex).set(SpecDouble);
489 if (node.op() == ValueAdd) {
490 clobberWorld(node.codeOrigin, indexInBlock);
491 forNode(nodeIndex).set(SpecString | SpecInt32 | SpecNumber);
492 node.setCanExit(false);
495 // We don't handle this yet. :-(
497 node.setCanExit(true);
502 JSValue left = forNode(node.child1()).value();
503 JSValue right = forNode(node.child2()).value();
504 if (left && right && left.isNumber() && right.isNumber()
505 && trySetConstant(nodeIndex, JSValue(left.asNumber() - right.asNumber()))) {
506 m_foundConstants = true;
507 node.setCanExit(false);
510 if (m_graph.addShouldSpeculateInteger(node)) {
511 speculateInt32Binary(
512 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
513 forNode(nodeIndex).set(SpecInt32);
516 speculateNumberBinary(node);
517 forNode(nodeIndex).set(SpecDouble);
522 JSValue child = forNode(node.child1()).value();
523 if (child && child.isNumber()
524 && trySetConstant(nodeIndex, JSValue(-child.asNumber()))) {
525 m_foundConstants = true;
526 node.setCanExit(false);
529 if (m_graph.negateShouldSpeculateInteger(node)) {
531 node, !nodeCanTruncateInteger(node.arithNodeFlags()));
532 forNode(nodeIndex).set(SpecInt32);
535 speculateNumberUnary(node);
536 forNode(nodeIndex).set(SpecDouble);
541 JSValue left = forNode(node.child1()).value();
542 JSValue right = forNode(node.child2()).value();
543 if (left && right && left.isNumber() && right.isNumber()
544 && trySetConstant(nodeIndex, JSValue(left.asNumber() * right.asNumber()))) {
545 m_foundConstants = true;
546 node.setCanExit(false);
549 if (m_graph.mulShouldSpeculateInteger(node)) {
550 speculateInt32Binary(
552 !nodeCanTruncateInteger(node.arithNodeFlags())
553 || !nodeCanIgnoreNegativeZero(node.arithNodeFlags()));
554 forNode(nodeIndex).set(SpecInt32);
557 speculateNumberBinary(node);
558 if (isRealNumberSpeculation(forNode(node.child1()).m_type)
559 || isRealNumberSpeculation(forNode(node.child2()).m_type))
560 forNode(nodeIndex).set(SpecDoubleReal);
562 forNode(nodeIndex).set(SpecDouble);
570 JSValue left = forNode(node.child1()).value();
571 JSValue right = forNode(node.child2()).value();
572 if (left && right && left.isNumber() && right.isNumber()) {
573 double a = left.asNumber();
574 double b = right.asNumber();
578 constantWasSet = trySetConstant(nodeIndex, JSValue(a / b));
581 constantWasSet = trySetConstant(nodeIndex, JSValue(a < b ? a : (b <= a ? b : a + b)));
584 constantWasSet = trySetConstant(nodeIndex, JSValue(a > b ? a : (b >= a ? b : a + b)));
587 constantWasSet = trySetConstant(nodeIndex, JSValue(fmod(a, b)));
590 ASSERT_NOT_REACHED();
591 constantWasSet = false;
594 if (constantWasSet) {
595 m_foundConstants = true;
596 node.setCanExit(false);
600 if (Node::shouldSpeculateIntegerForArithmetic(
601 m_graph[node.child1()], m_graph[node.child2()])
602 && node.canSpeculateInteger()) {
603 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
604 forNode(nodeIndex).set(SpecInt32);
607 speculateNumberBinary(node);
608 forNode(nodeIndex).set(SpecDouble);
613 JSValue child = forNode(node.child1()).value();
614 if (child && child.isNumber()
615 && trySetConstant(nodeIndex, JSValue(fabs(child.asNumber())))) {
616 m_foundConstants = true;
617 node.setCanExit(false);
620 if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
621 && node.canSpeculateInteger()) {
622 speculateInt32Unary(node, true);
623 forNode(nodeIndex).set(SpecInt32);
626 speculateNumberUnary(node);
627 forNode(nodeIndex).set(SpecDouble);
632 JSValue child = forNode(node.child1()).value();
633 if (child && child.isNumber()
634 && trySetConstant(nodeIndex, JSValue(sqrt(child.asNumber())))) {
635 m_foundConstants = true;
636 node.setCanExit(false);
639 speculateNumberUnary(node);
640 forNode(nodeIndex).set(SpecDouble);
645 bool didSetConstant = false;
646 switch (booleanResult(node, forNode(node.child1()))) {
648 didSetConstant = trySetConstant(nodeIndex, jsBoolean(false));
650 case DefinitelyFalse:
651 didSetConstant = trySetConstant(nodeIndex, jsBoolean(true));
656 if (didSetConstant) {
657 m_foundConstants = true;
658 node.setCanExit(false);
661 Node& child = m_graph[node.child1()];
662 if (isBooleanSpeculation(child.prediction()))
663 speculateBooleanUnary(node);
664 else if (child.shouldSpeculateNonStringCellOrOther()) {
665 node.setCanExit(true);
666 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
667 } else if (child.shouldSpeculateInteger())
668 speculateInt32Unary(node);
669 else if (child.shouldSpeculateNumber())
670 speculateNumberUnary(node);
672 node.setCanExit(false);
673 forNode(nodeIndex).set(SpecBoolean);
683 node.setCanExit(node.op() == IsUndefined && m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
684 JSValue child = forNode(node.child1()).value();
689 if (m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
690 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
693 : child.isUndefined()));
695 constantWasSet = trySetConstant(nodeIndex, jsBoolean(
697 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
698 : child.isUndefined()));
702 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isBoolean()));
705 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNumber()));
708 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child)));
711 constantWasSet = false;
714 if (constantWasSet) {
715 m_foundConstants = true;
719 forNode(nodeIndex).set(SpecBoolean);
726 case CompareGreaterEq:
728 bool constantWasSet = false;
730 JSValue leftConst = forNode(node.child1()).value();
731 JSValue rightConst = forNode(node.child2()).value();
732 if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
733 double a = leftConst.asNumber();
734 double b = rightConst.asNumber();
737 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
740 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a <= b));
743 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a > b));
745 case CompareGreaterEq:
746 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a >= b));
749 constantWasSet = trySetConstant(nodeIndex, jsBoolean(a == b));
752 ASSERT_NOT_REACHED();
753 constantWasSet = false;
758 if (!constantWasSet && node.op() == CompareEq) {
759 SpeculatedType leftType = forNode(node.child1()).m_type;
760 SpeculatedType rightType = forNode(node.child2()).m_type;
761 if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
762 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
763 constantWasSet = trySetConstant(nodeIndex, jsBoolean(false));
766 if (constantWasSet) {
767 m_foundConstants = true;
768 node.setCanExit(false);
772 forNode(nodeIndex).set(SpecBoolean);
774 Node& left = m_graph[node.child1()];
775 Node& right = m_graph[node.child2()];
776 SpeculatedType filter;
777 SpeculatedTypeChecker checker;
778 if (Node::shouldSpeculateInteger(left, right)) {
780 checker = isInt32Speculation;
781 } else if (Node::shouldSpeculateNumber(left, right)) {
783 checker = isNumberSpeculation;
784 } else if (node.op() == CompareEq) {
785 if ((m_graph.isConstant(node.child1().index())
786 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
787 || (m_graph.isConstant(node.child2().index())
788 && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
789 // We can exit if we haven't fired the MasqueradesAsUndefind watchpoint yet.
790 node.setCanExit(m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid());
794 if (left.shouldSpeculateString() || right.shouldSpeculateString()) {
795 node.setCanExit(false);
798 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCellOrOther()) {
799 node.setCanExit(true);
800 forNode(node.child1()).filter(SpecCell & ~SpecString);
801 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
804 if (left.shouldSpeculateNonStringCellOrOther() && right.shouldSpeculateNonStringCell()) {
805 node.setCanExit(true);
806 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
807 forNode(node.child2()).filter(SpecCell & ~SpecString);
810 if (left.shouldSpeculateNonStringCell() && right.shouldSpeculateNonStringCell()) {
811 node.setCanExit(true);
812 forNode(node.child1()).filter(SpecCell & ~SpecString);
813 forNode(node.child2()).filter(SpecCell & ~SpecString);
818 checker = isAnySpeculation;
819 clobberWorld(node.codeOrigin, indexInBlock);
822 checker = isAnySpeculation;
823 clobberWorld(node.codeOrigin, indexInBlock);
826 !checker(forNode(node.child1()).m_type)
827 || !checker(forNode(node.child2()).m_type));
828 forNode(node.child1()).filter(filter);
829 forNode(node.child2()).filter(filter);
833 case CompareStrictEq: {
834 JSValue left = forNode(node.child1()).value();
835 JSValue right = forNode(node.child2()).value();
836 if (left && right && left.isNumber() && right.isNumber()
837 && trySetConstant(nodeIndex, jsBoolean(left.asNumber() == right.asNumber()))) {
838 m_foundConstants = true;
839 node.setCanExit(false);
842 forNode(nodeIndex).set(SpecBoolean);
843 if (m_graph.isJSConstant(node.child1().index())) {
844 JSValue value = m_graph.valueOfJSConstant(node.child1().index());
845 if (!value.isNumber() && !value.isString()) {
846 node.setCanExit(false);
850 if (m_graph.isJSConstant(node.child2().index())) {
851 JSValue value = m_graph.valueOfJSConstant(node.child2().index());
852 if (!value.isNumber() && !value.isString()) {
853 node.setCanExit(false);
857 if (Node::shouldSpeculateInteger(
858 m_graph[node.child1()], m_graph[node.child2()])) {
859 speculateInt32Binary(node);
862 if (Node::shouldSpeculateNumber(
863 m_graph[node.child1()], m_graph[node.child2()])) {
864 speculateNumberBinary(node);
867 Node& leftNode = m_graph[node.child1()];
868 Node& rightNode = m_graph[node.child2()];
869 if (leftNode.shouldSpeculateString() || rightNode.shouldSpeculateString()) {
870 node.setCanExit(false);
873 if (leftNode.shouldSpeculateNonStringCell() && rightNode.shouldSpeculateNonStringCell()) {
874 node.setCanExit(true);
875 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
876 forNode(node.child2()).filter((SpecCell & ~SpecString) | SpecOther);
879 node.setCanExit(false);
883 case StringCharCodeAt:
884 node.setCanExit(true);
885 forNode(node.child1()).filter(SpecString);
886 forNode(node.child2()).filter(SpecInt32);
887 forNode(nodeIndex).set(SpecInt32);
891 node.setCanExit(true);
892 forNode(node.child1()).filter(SpecString);
893 forNode(node.child2()).filter(SpecInt32);
894 forNode(nodeIndex).set(SpecString);
898 node.setCanExit(true);
899 switch (node.arrayMode().type()) {
900 case Array::SelectUsingPredictions:
901 case Array::Unprofiled:
902 case Array::Undecided:
903 ASSERT_NOT_REACHED();
905 case Array::ForceExit:
909 clobberWorld(node.codeOrigin, indexInBlock);
910 forNode(nodeIndex).makeTop();
913 forNode(node.child2()).filter(SpecInt32);
914 forNode(nodeIndex).set(SpecString);
916 case Array::Arguments:
917 forNode(node.child2()).filter(SpecInt32);
918 forNode(nodeIndex).makeTop();
921 forNode(node.child2()).filter(SpecInt32);
922 if (node.arrayMode().isOutOfBounds()) {
923 clobberWorld(node.codeOrigin, indexInBlock);
924 forNode(nodeIndex).makeTop();
926 forNode(nodeIndex).set(SpecInt32);
929 forNode(node.child2()).filter(SpecInt32);
930 if (node.arrayMode().isOutOfBounds()) {
931 clobberWorld(node.codeOrigin, indexInBlock);
932 forNode(nodeIndex).makeTop();
933 } else if (node.arrayMode().isSaneChain())
934 forNode(nodeIndex).set(SpecDouble);
936 forNode(nodeIndex).set(SpecDoubleReal);
938 case Array::Contiguous:
939 case Array::ArrayStorage:
940 case Array::SlowPutArrayStorage:
941 forNode(node.child2()).filter(SpecInt32);
942 if (node.arrayMode().isOutOfBounds())
943 clobberWorld(node.codeOrigin, indexInBlock);
944 forNode(nodeIndex).makeTop();
946 case Array::Int8Array:
947 forNode(node.child2()).filter(SpecInt32);
948 forNode(nodeIndex).set(SpecInt32);
950 case Array::Int16Array:
951 forNode(node.child2()).filter(SpecInt32);
952 forNode(nodeIndex).set(SpecInt32);
954 case Array::Int32Array:
955 forNode(node.child2()).filter(SpecInt32);
956 forNode(nodeIndex).set(SpecInt32);
958 case Array::Uint8Array:
959 forNode(node.child2()).filter(SpecInt32);
960 forNode(nodeIndex).set(SpecInt32);
962 case Array::Uint8ClampedArray:
963 forNode(node.child2()).filter(SpecInt32);
964 forNode(nodeIndex).set(SpecInt32);
966 case Array::Uint16Array:
967 forNode(node.child2()).filter(SpecInt32);
968 forNode(nodeIndex).set(SpecInt32);
970 case Array::Uint32Array:
971 forNode(node.child2()).filter(SpecInt32);
972 if (node.shouldSpeculateInteger())
973 forNode(nodeIndex).set(SpecInt32);
975 forNode(nodeIndex).set(SpecDouble);
977 case Array::Float32Array:
978 forNode(node.child2()).filter(SpecInt32);
979 forNode(nodeIndex).set(SpecDouble);
981 case Array::Float64Array:
982 forNode(node.child2()).filter(SpecInt32);
983 forNode(nodeIndex).set(SpecDouble);
986 ASSERT_NOT_REACHED();
993 case PutByValAlias: {
994 node.setCanExit(true);
995 Edge child1 = m_graph.varArgChild(node, 0);
996 Edge child2 = m_graph.varArgChild(node, 1);
997 Edge child3 = m_graph.varArgChild(node, 2);
998 switch (node.arrayMode().modeForPut().type()) {
999 case Array::ForceExit:
1002 case Array::Generic:
1003 clobberWorld(node.codeOrigin, indexInBlock);
1006 forNode(child1).filter(SpecCell);
1007 forNode(child2).filter(SpecInt32);
1008 forNode(child3).filter(SpecInt32);
1009 if (node.arrayMode().isOutOfBounds())
1010 clobberWorld(node.codeOrigin, indexInBlock);
1013 forNode(child1).filter(SpecCell);
1014 forNode(child2).filter(SpecInt32);
1015 forNode(child3).filter(SpecRealNumber);
1016 if (node.arrayMode().isOutOfBounds())
1017 clobberWorld(node.codeOrigin, indexInBlock);
1019 case Array::Contiguous:
1020 case Array::ArrayStorage:
1021 forNode(child1).filter(SpecCell);
1022 forNode(child2).filter(SpecInt32);
1023 if (node.arrayMode().isOutOfBounds())
1024 clobberWorld(node.codeOrigin, indexInBlock);
1026 case Array::SlowPutArrayStorage:
1027 forNode(child1).filter(SpecCell);
1028 forNode(child2).filter(SpecInt32);
1029 if (node.arrayMode().mayStoreToHole())
1030 clobberWorld(node.codeOrigin, indexInBlock);
1032 case Array::Arguments:
1033 forNode(child1).filter(SpecCell);
1034 forNode(child2).filter(SpecInt32);
1036 case Array::Int8Array:
1037 forNode(child1).filter(SpecCell);
1038 forNode(child2).filter(SpecInt32);
1039 if (m_graph[child3].shouldSpeculateInteger())
1040 forNode(child3).filter(SpecInt32);
1042 forNode(child3).filter(SpecNumber);
1044 case Array::Int16Array:
1045 forNode(child1).filter(SpecCell);
1046 forNode(child2).filter(SpecInt32);
1047 if (m_graph[child3].shouldSpeculateInteger())
1048 forNode(child3).filter(SpecInt32);
1050 forNode(child3).filter(SpecNumber);
1052 case Array::Int32Array:
1053 forNode(child1).filter(SpecCell);
1054 forNode(child2).filter(SpecInt32);
1055 if (m_graph[child3].shouldSpeculateInteger())
1056 forNode(child3).filter(SpecInt32);
1058 forNode(child3).filter(SpecNumber);
1060 case Array::Uint8Array:
1061 forNode(child1).filter(SpecCell);
1062 forNode(child2).filter(SpecInt32);
1063 if (m_graph[child3].shouldSpeculateInteger())
1064 forNode(child3).filter(SpecInt32);
1066 forNode(child3).filter(SpecNumber);
1068 case Array::Uint8ClampedArray:
1069 forNode(child1).filter(SpecCell);
1070 forNode(child2).filter(SpecInt32);
1071 if (m_graph[child3].shouldSpeculateInteger())
1072 forNode(child3).filter(SpecInt32);
1074 forNode(child3).filter(SpecNumber);
1076 case Array::Uint16Array:
1077 forNode(child1).filter(SpecCell);
1078 forNode(child2).filter(SpecInt32);
1079 if (m_graph[child3].shouldSpeculateInteger())
1080 forNode(child3).filter(SpecInt32);
1082 forNode(child3).filter(SpecNumber);
1084 case Array::Uint32Array:
1085 forNode(child1).filter(SpecCell);
1086 forNode(child2).filter(SpecInt32);
1087 if (m_graph[child3].shouldSpeculateInteger())
1088 forNode(child3).filter(SpecInt32);
1090 forNode(child3).filter(SpecNumber);
1092 case Array::Float32Array:
1093 forNode(child1).filter(SpecCell);
1094 forNode(child2).filter(SpecInt32);
1095 forNode(child3).filter(SpecNumber);
1097 case Array::Float64Array:
1098 forNode(child1).filter(SpecCell);
1099 forNode(child2).filter(SpecInt32);
1100 forNode(child3).filter(SpecNumber);
1110 node.setCanExit(true);
1111 switch (node.arrayMode().type()) {
1113 forNode(node.child2()).filter(SpecInt32);
1116 forNode(node.child2()).filter(SpecRealNumber);
1121 clobberWorld(node.codeOrigin, indexInBlock);
1122 forNode(nodeIndex).set(SpecNumber);
1126 node.setCanExit(true);
1127 clobberWorld(node.codeOrigin, indexInBlock);
1128 forNode(nodeIndex).makeTop();
1134 !isCellSpeculation(forNode(node.child1()).m_type)
1135 || !isCellSpeculation(forNode(node.child2()).m_type));
1136 forNode(node.child1()).filter(SpecCell);
1137 forNode(node.child2()).filter(SpecCell);
1138 forNode(nodeIndex).makeTop();
1142 node.setCanExit(false);
1146 BooleanResult result = booleanResult(node, forNode(node.child1()));
1147 if (result == DefinitelyTrue) {
1148 m_branchDirection = TakeTrue;
1149 node.setCanExit(false);
1152 if (result == DefinitelyFalse) {
1153 m_branchDirection = TakeFalse;
1154 node.setCanExit(false);
1157 // FIXME: The above handles the trivial cases of sparse conditional
1158 // constant propagation, but we can do better:
1159 // We can specialize the source variable's value on each direction of
1161 Node& child = m_graph[node.child1()];
1162 if (child.shouldSpeculateBoolean())
1163 speculateBooleanUnary(node);
1164 else if (child.shouldSpeculateNonStringCellOrOther()) {
1165 node.setCanExit(true);
1166 forNode(node.child1()).filter((SpecCell & ~SpecString) | SpecOther);
1167 } else if (child.shouldSpeculateInteger())
1168 speculateInt32Unary(node);
1169 else if (child.shouldSpeculateNumber())
1170 speculateNumberUnary(node);
1172 node.setCanExit(false);
1173 m_branchDirection = TakeBoth;
1179 node.setCanExit(false);
1183 case ThrowReferenceError:
1185 node.setCanExit(true);
1189 JSValue childConst = forNode(node.child1()).value();
1190 if (childConst && childConst.isNumber() && trySetConstant(nodeIndex, childConst)) {
1191 m_foundConstants = true;
1192 node.setCanExit(false);
1196 Node& child = m_graph[node.child1()];
1197 if (child.shouldSpeculateInteger()) {
1198 speculateInt32Unary(node);
1199 forNode(nodeIndex).set(SpecInt32);
1203 AbstractValue& source = forNode(node.child1());
1204 AbstractValue& destination = forNode(nodeIndex);
1206 SpeculatedType type = source.m_type;
1207 if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
1208 type &= (SpecNumber | SpecString | SpecBoolean);
1211 destination.set(type);
1212 node.setCanExit(false);
1217 node.setCanExit(false);
1218 forNode(nodeIndex).set(SpecString);
1222 node.setCanExit(true);
1223 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
1224 m_haveStructures = true;
1227 case NewArrayBuffer:
1228 node.setCanExit(true);
1229 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
1230 m_haveStructures = true;
1233 case NewArrayWithSize:
1234 node.setCanExit(true);
1235 forNode(node.child1()).filter(SpecInt32);
1236 forNode(nodeIndex).set(SpecArray);
1237 m_haveStructures = true;
1241 node.setCanExit(false);
1242 forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
1243 m_haveStructures = true;
1247 Node& child = m_graph[node.child1()];
1248 AbstractValue& source = forNode(node.child1());
1249 AbstractValue& destination = forNode(nodeIndex);
1251 if (isObjectSpeculation(source.m_type)) {
1252 // This is the simple case. We already know that the source is an
1253 // object, so there's nothing to do. I don't think this case will
1254 // be hit, but then again, you never know.
1255 destination = source;
1256 node.setCanExit(false);
1257 m_foundConstants = true; // Tell the constant folder to turn this into Identity.
1261 node.setCanExit(true);
1263 if (isOtherSpeculation(child.prediction())) {
1264 source.filter(SpecOther);
1265 destination.set(SpecObjectOther);
1269 if (isObjectSpeculation(child.prediction())) {
1270 source.filter(SpecObjectMask);
1271 destination = source;
1275 destination = source;
1276 destination.merge(SpecObjectOther);
1281 AbstractValue& source = forNode(node.child1());
1282 AbstractValue& destination = forNode(nodeIndex);
1284 node.setCanExit(!isCellSpeculation(source.m_type));
1286 source.filter(SpecFunction);
1287 destination.set(SpecFinalObject);
1291 case InheritorIDWatchpoint:
1292 node.setCanExit(true);
1296 node.setCanExit(false);
1297 forNode(nodeIndex).set(node.structure());
1298 m_haveStructures = true;
1301 case CreateActivation:
1302 node.setCanExit(false);
1303 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->activationStructure());
1304 m_haveStructures = true;
1307 case CreateArguments:
1308 node.setCanExit(false);
1309 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->argumentsStructure());
1310 m_haveStructures = true;
1313 case TearOffActivation:
1314 case TearOffArguments:
1315 node.setCanExit(false);
1316 // Does nothing that is user-visible.
1319 case CheckArgumentsNotCreated:
1320 if (isEmptySpeculation(
1321 m_variables.operand(
1322 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type)) {
1323 node.setCanExit(false);
1324 m_foundConstants = true;
1326 node.setCanExit(true);
1329 case GetMyArgumentsLength:
1330 // We know that this executable does not escape its arguments, so we can optimize
1331 // the arguments a bit. Note that this is not sufficient to force constant folding
1332 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1333 // We perform further optimizations on this later on.
1334 if (node.codeOrigin.inlineCallFrame)
1335 forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
1337 forNode(nodeIndex).set(SpecInt32);
1339 !isEmptySpeculation(
1340 m_variables.operand(
1341 m_graph.argumentsRegisterFor(node.codeOrigin)).m_type));
1344 case GetMyArgumentsLengthSafe:
1345 node.setCanExit(false);
1346 // This potentially clobbers all structures if the arguments object had a getter
1347 // installed on the length property.
1348 clobberWorld(node.codeOrigin, indexInBlock);
1349 // We currently make no guarantee about what this returns because it does not
1350 // speculate that the length property is actually a length.
1351 forNode(nodeIndex).makeTop();
1354 case GetMyArgumentByVal:
1355 node.setCanExit(true);
1356 // We know that this executable does not escape its arguments, so we can optimize
1357 // the arguments a bit. Note that this ends up being further optimized by the
1358 // ArgumentsSimplificationPhase.
1359 forNode(node.child1()).filter(SpecInt32);
1360 forNode(nodeIndex).makeTop();
1363 case GetMyArgumentByValSafe:
1364 node.setCanExit(true);
1365 // This potentially clobbers all structures if the property we're accessing has
1366 // a getter. We don't speculate against this.
1367 clobberWorld(node.codeOrigin, indexInBlock);
1368 // But we do speculate that the index is an integer.
1369 forNode(node.child1()).filter(SpecInt32);
1370 // And the result is unknown.
1371 forNode(nodeIndex).makeTop();
1375 case NewFunctionExpression:
1376 case NewFunctionNoCheck:
1377 node.setCanExit(false);
1378 forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
1382 node.setCanExit(false);
1383 forNode(nodeIndex).set(SpecFunction);
1388 node.setCanExit(false);
1389 forNode(nodeIndex).set(SpecCellOther);
1393 node.setCanExit(false);
1394 JSValue child = forNode(node.child1()).value();
1395 if (child && trySetConstant(nodeIndex, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {
1396 m_foundConstants = true;
1399 forNode(nodeIndex).set(SpecCellOther);
1403 case GetScopeRegisters:
1404 node.setCanExit(false);
1405 forNode(node.child1()).filter(SpecCell);
1406 forNode(nodeIndex).clear(); // The result is not a JS value.
1410 node.setCanExit(false);
1411 forNode(nodeIndex).makeTop();
1415 node.setCanExit(false);
1416 clobberCapturedVars(node.codeOrigin);
1421 node.setCanExit(true);
1422 if (!node.prediction()) {
1426 if (isCellSpeculation(m_graph[node.child1()].prediction())) {
1427 forNode(node.child1()).filter(SpecCell);
1429 if (Structure* structure = forNode(node.child1()).bestProvenStructure()) {
1430 GetByIdStatus status = GetByIdStatus::computeFor(
1431 m_graph.m_globalData, structure,
1432 m_graph.m_codeBlock->identifier(node.identifierNumber()));
1433 if (status.isSimple()) {
1434 // Assert things that we can't handle and that the computeFor() method
1435 // above won't be able to return.
1436 ASSERT(status.structureSet().size() == 1);
1437 ASSERT(status.chain().isEmpty());
1439 if (status.specificValue())
1440 forNode(nodeIndex).set(status.specificValue());
1442 forNode(nodeIndex).makeTop();
1443 forNode(node.child1()).filter(status.structureSet());
1445 m_foundConstants = true;
1450 clobberWorld(node.codeOrigin, indexInBlock);
1451 forNode(nodeIndex).makeTop();
1454 case GetArrayLength:
1455 node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
1456 forNode(nodeIndex).set(SpecInt32);
1459 case CheckStructure:
1460 case ForwardCheckStructure: {
1461 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
1462 AbstractValue& value = forNode(node.child1());
1463 // If this structure check is attempting to prove knowledge already held in
1464 // the futurePossibleStructure set then the constant folding phase should
1465 // turn this into a watchpoint instead.
1466 StructureSet& set = node.structureSet();
1467 if (value.m_futurePossibleStructure.isSubsetOf(set)
1468 || value.m_currentKnownStructure.isSubsetOf(set))
1469 m_foundConstants = true;
1471 !value.m_currentKnownStructure.isSubsetOf(set)
1472 || !isCellSpeculation(value.m_type));
1474 m_haveStructures = true;
1478 case StructureTransitionWatchpoint:
1479 case ForwardStructureTransitionWatchpoint: {
1480 AbstractValue& value = forNode(node.child1());
1482 // It's only valid to issue a structure transition watchpoint if we already
1483 // know that the watchpoint covers a superset of the structures known to
1484 // belong to the set of future structures that this value may have.
1485 // Currently, we only issue singleton watchpoints (that check one structure)
1486 // and our futurePossibleStructure set can only contain zero, one, or an
1487 // infinity of structures.
1488 ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node.structure())));
1490 ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.
1491 value.filter(node.structure());
1492 m_haveStructures = true;
1493 node.setCanExit(true);
1498 case PhantomPutStructure:
1499 node.setCanExit(false);
1500 if (!forNode(node.child1()).m_currentKnownStructure.isClear()) {
1501 clobberStructures(indexInBlock);
1502 forNode(node.child1()).set(node.structureTransitionData().newStructure);
1503 m_haveStructures = true;
1507 case AllocatePropertyStorage:
1508 case ReallocatePropertyStorage:
1509 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
1510 forNode(node.child1()).filter(SpecCell);
1511 forNode(nodeIndex).clear(); // The result is not a JS value.
1514 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
1515 m_foundConstants = true;
1516 node.setCanExit(false);
1519 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.
1520 switch (node.arrayMode().type()) {
1522 forNode(node.child1()).filter(SpecString);
1526 case Array::Contiguous:
1527 case Array::ArrayStorage:
1528 case Array::SlowPutArrayStorage:
1529 forNode(node.child1()).filter(SpecCell);
1531 case Array::Arguments:
1532 forNode(node.child1()).filter(SpecArguments);
1534 case Array::Int8Array:
1535 forNode(node.child1()).filter(SpecInt8Array);
1537 case Array::Int16Array:
1538 forNode(node.child1()).filter(SpecInt16Array);
1540 case Array::Int32Array:
1541 forNode(node.child1()).filter(SpecInt32Array);
1543 case Array::Uint8Array:
1544 forNode(node.child1()).filter(SpecUint8Array);
1546 case Array::Uint8ClampedArray:
1547 forNode(node.child1()).filter(SpecUint8ClampedArray);
1549 case Array::Uint16Array:
1550 forNode(node.child1()).filter(SpecUint16Array);
1552 case Array::Uint32Array:
1553 forNode(node.child1()).filter(SpecUint32Array);
1555 case Array::Float32Array:
1556 forNode(node.child1()).filter(SpecFloat32Array);
1558 case Array::Float64Array:
1559 forNode(node.child1()).filter(SpecFloat64Array);
1562 ASSERT_NOT_REACHED();
1565 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
1566 m_haveStructures = true;
1570 if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
1571 m_foundConstants = true;
1572 node.setCanExit(false);
1575 ASSERT(node.arrayMode().conversion() == Array::Convert
1576 || node.arrayMode().conversion() == Array::RageConvert);
1577 node.setCanExit(true);
1578 forNode(node.child1()).filter(SpecCell);
1580 forNode(node.child2()).filter(SpecInt32);
1581 clobberStructures(indexInBlock);
1582 forNode(node.child1()).filterArrayModes(node.arrayMode().arrayModesThatPassFiltering());
1583 m_haveStructures = true;
1586 case ArrayifyToStructure: {
1587 AbstractValue& value = forNode(node.child1());
1588 StructureSet set = node.structure();
1589 if (value.m_futurePossibleStructure.isSubsetOf(set)
1590 || value.m_currentKnownStructure.isSubsetOf(set))
1591 m_foundConstants = true;
1592 node.setCanExit(true);
1593 clobberStructures(indexInBlock);
1595 m_haveStructures = true;
1598 case GetIndexedPropertyStorage: {
1599 switch (node.arrayMode().type()) {
1601 // Strings are weird - we may spec fail if the string was a rope. That is of course
1602 // stupid, and we should fix that, but for now let's at least be honest about it.
1603 node.setCanExit(true);
1606 node.setCanExit(false);
1609 forNode(nodeIndex).clear();
1613 if (!m_graph[node.child1()].hasStorageResult()) {
1614 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
1615 forNode(node.child1()).filter(SpecCell);
1617 forNode(nodeIndex).makeTop();
1621 bool canExit = false;
1622 if (!m_graph[node.child1()].hasStorageResult()) {
1623 canExit |= !isCellSpeculation(forNode(node.child1()).m_type);
1624 forNode(node.child1()).filter(SpecCell);
1626 canExit |= !isCellSpeculation(forNode(node.child2()).m_type);
1627 forNode(node.child2()).filter(SpecCell);
1628 node.setCanExit(canExit);
1632 case CheckFunction: {
1633 JSValue value = forNode(node.child1()).value();
1634 if (value == node.function()) {
1635 m_foundConstants = true;
1637 node.setCanExit(false);
1641 node.setCanExit(true); // Lies! We can do better.
1642 if (!forNode(node.child1()).filterByValue(node.function())) {
1651 node.setCanExit(true);
1652 if (Structure* structure = forNode(node.child1()).bestProvenStructure()) {
1653 PutByIdStatus status = PutByIdStatus::computeFor(
1654 m_graph.m_globalData,
1655 m_graph.globalObjectFor(node.codeOrigin),
1657 m_graph.m_codeBlock->identifier(node.identifierNumber()),
1658 node.op() == PutByIdDirect);
1659 if (status.isSimpleReplace()) {
1660 forNode(node.child1()).filter(structure);
1661 m_foundConstants = true;
1664 if (status.isSimpleTransition()) {
1665 clobberStructures(indexInBlock);
1666 forNode(node.child1()).set(status.newStructure());
1667 m_haveStructures = true;
1668 m_foundConstants = true;
1672 forNode(node.child1()).filter(SpecCell);
1673 clobberWorld(node.codeOrigin, indexInBlock);
1677 node.setCanExit(false);
1678 forNode(nodeIndex).makeTop();
1681 case GlobalVarWatchpoint:
1682 node.setCanExit(true);
1686 case PutGlobalVarCheck:
1687 node.setCanExit(false);
1690 case CheckHasInstance:
1691 node.setCanExit(true);
1692 forNode(node.child1()).filter(SpecCell);
1693 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1697 node.setCanExit(true);
1698 // Again, sadly, we don't propagate the fact that we've done InstanceOf
1699 if (!(m_graph[node.child1()].prediction() & ~SpecCell) && !(forNode(node.child1()).m_type & ~SpecCell))
1700 forNode(node.child1()).filter(SpecCell);
1701 forNode(node.child2()).filter(SpecCell);
1702 forNode(nodeIndex).set(SpecBoolean);
1707 node.setCanExit(false);
1711 node.setCanExit(false);
1718 case ResolveBaseStrictPut:
1720 node.setCanExit(true);
1721 clobberWorld(node.codeOrigin, indexInBlock);
1722 forNode(nodeIndex).makeTop();
1726 clobberWorld(node.codeOrigin, indexInBlock);
1727 forNode(nodeIndex).makeTop();
1731 node.setCanExit(true);
1738 node.setCanExit(false);
1742 ASSERT_NOT_REACHED();
1749 inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock)
1751 clobberCapturedVars(codeOrigin);
1752 clobberStructures(indexInBlock);
1755 inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin)
1757 if (codeOrigin.inlineCallFrame) {
1758 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1759 for (size_t i = capturedVars.size(); i--;) {
1760 if (!capturedVars.quickGet(i))
1762 m_variables.local(i).makeTop();
1765 for (size_t i = m_codeBlock->m_numVars; i--;) {
1766 if (m_codeBlock->isCaptured(i))
1767 m_variables.local(i).makeTop();
1771 for (size_t i = m_variables.numberOfArguments(); i--;) {
1772 if (m_codeBlock->isCaptured(argumentToOperand(i)))
1773 m_variables.argument(i).makeTop();
1777 inline void AbstractState::clobberStructures(unsigned indexInBlock)
1779 if (!m_haveStructures)
1781 for (size_t i = indexInBlock + 1; i--;)
1782 forNode(m_block->at(i)).clobberStructures();
1783 for (size_t i = m_variables.numberOfArguments(); i--;)
1784 m_variables.argument(i).clobberStructures();
1785 for (size_t i = m_variables.numberOfLocals(); i--;)
1786 m_variables.local(i).clobberStructures();
1787 m_haveStructures = false;
1788 m_didClobber = true;
1791 inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
1793 if (nodeIndex == NoNode)
1796 AbstractValue source;
1798 Node& node = m_graph[nodeIndex];
1799 if (!node.refCount())
1802 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1803 dataLogF(" It's live, node @%u.\n", nodeIndex);
1806 if (node.variableAccessData()->isCaptured()) {
1807 source = inVariable;
1808 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1809 dataLogF(" Transfering ");
1810 source.dump(WTF::dataFile());
1811 dataLogF(" from last access due to captured variable.\n");
1814 switch (node.op()) {
1818 // The block transfers the value from head to tail.
1819 source = inVariable;
1820 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1821 dataLogF(" Transfering ");
1822 source.dump(WTF::dataFile());
1823 dataLogF(" from head to tail.\n");
1828 // The block refines the value with additional speculations.
1829 source = forNode(nodeIndex);
1830 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1831 dataLogF(" Refining to ");
1832 source.dump(WTF::dataFile());
1838 // The block sets the variable, and potentially refines it, both
1839 // before and after setting it.
1840 if (node.variableAccessData()->shouldUseDoubleFormat()) {
1841 // FIXME: This unnecessarily loses precision.
1842 source.set(SpecDouble);
1844 source = forNode(node.child1());
1845 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1846 dataLogF(" Setting to ");
1847 source.dump(WTF::dataFile());
1853 ASSERT_NOT_REACHED();
1858 if (destination == source) {
1859 // Abstract execution did not change the output value of the variable, for this
1860 // basic block, on this iteration.
1861 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1862 dataLogF(" Not changed!\n");
1867 // Abstract execution reached a new conclusion about the speculations reached about
1868 // this variable after execution of this basic block. Update the state, and return
1869 // true to indicate that the fixpoint must go on!
1870 destination = source;
1871 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1872 dataLogF(" Changed!\n");
1877 inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
1879 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
1880 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
1882 bool changed = false;
1884 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
1885 AbstractValue& destination = to->valuesAtHead.argument(argument);
1886 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
1889 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
1890 AbstractValue& destination = to->valuesAtHead.local(local);
1891 changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
1894 if (!to->cfaHasVisited)
1897 to->cfaShouldRevisit |= changed;
1902 inline bool AbstractState::mergeToSuccessors(
1903 Graph& graph, BasicBlock* basicBlock)
1905 Node& terminal = graph[basicBlock->last()];
1907 ASSERT(terminal.isTerminal());
1909 switch (terminal.op()) {
1911 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
1912 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1913 dataLogF(" Merging to block #%u.\n", terminal.takenBlockIndex());
1915 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
1919 ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
1920 bool changed = false;
1921 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1922 dataLogF(" Merging to block #%u.\n", terminal.takenBlockIndex());
1924 if (basicBlock->cfaBranchDirection != TakeFalse)
1925 changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
1926 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1927 dataLogF(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
1929 if (basicBlock->cfaBranchDirection != TakeTrue)
1930 changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
1936 case ThrowReferenceError:
1937 ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
1941 ASSERT_NOT_REACHED();
1946 inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
1948 if (destinationNodeIndex == NoNode)
1951 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
1953 // FIXME: We could do some sparse conditional propagation here!
1955 return destination.merge(source);
1958 void AbstractState::dump(PrintStream& out)
1961 for (size_t i = 0; i < m_block->size(); ++i) {
1962 NodeIndex index = m_block->at(i);
1963 AbstractValue& value = m_nodes[index];
1964 if (value.isClear())
1970 out.printf("@%lu:", static_cast<unsigned long>(index));
1975 } } // namespace JSC::DFG
1977 #endif // ENABLE(DFG_JIT)