2 * Copyright (C) 2013-2016 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.
26 #ifndef DFGAbstractInterpreterInlines_h
27 #define DFGAbstractInterpreterInlines_h
31 #include "ArrayConstructor.h"
32 #include "DFGAbstractInterpreter.h"
33 #include "GetByIdStatus.h"
34 #include "GetterSetter.h"
35 #include "JITOperations.h"
36 #include "MathCommon.h"
37 #include "Operations.h"
38 #include "PutByIdStatus.h"
39 #include "StringObject.h"
41 namespace JSC { namespace DFG {
43 template<typename AbstractStateType>
44 AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
45 : m_codeBlock(graph.m_codeBlock)
49 if (m_graph.m_form == SSA)
50 m_phiChildren = std::make_unique<PhiChildren>(m_graph);
53 template<typename AbstractStateType>
54 AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
58 template<typename AbstractStateType>
59 typename AbstractInterpreter<AbstractStateType>::BooleanResult
60 AbstractInterpreter<AbstractStateType>::booleanResult(
61 Node* node, AbstractValue& value)
63 JSValue childConst = value.value();
65 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
66 return DefinitelyTrue;
67 return DefinitelyFalse;
70 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
71 if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
73 for (unsigned i = value.m_structure.size(); i--;) {
74 Structure* structure = value.m_structure[i];
75 if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
76 || structure->typeInfo().type() == StringType) {
82 return DefinitelyTrue;
85 return UnknownBooleanResult;
88 template<typename AbstractStateType>
89 void AbstractInterpreter<AbstractStateType>::startExecuting()
91 ASSERT(m_state.block());
92 ASSERT(m_state.isValid());
94 m_state.setDidClobber(false);
97 template<typename AbstractStateType>
98 void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
100 m_graph.doToChildren(
103 filterEdgeByUse(edge);
107 template<typename AbstractStateType>
108 void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
110 executeEdges(m_state.block()->at(indexInBlock));
113 template<typename AbstractStateType>
114 void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
116 // Some use kinds are required to not have checks, because we know somehow that the incoming
117 // value will already have the type we want. In those cases, AI may not be smart enough to
118 // prove that this is indeed the case. But the existance of the edge is enough to prove that
119 // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
120 // and FTL backends may emit checks in a node that lacks a valid exit origin.
121 m_graph.doToChildren(
124 if (mayHaveTypeCheck(edge.useKind()))
127 filterEdgeByUse(edge);
131 template<typename AbstractStateType>
132 void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
134 if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
137 DFG_CRASH(m_graph, node, toCString("Edge verification error: ", node, "->", edge, " was expected to have type ", SpeculationDump(typeFilterFor(edge.useKind())), " but has type ", SpeculationDump(forNode(edge).m_type), " (", forNode(edge).m_type, ")").data());
140 template<typename AbstractStateType>
141 void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
143 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
146 template<typename AbstractStateType>
147 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
149 if (!ASSERT_DISABLED)
152 m_state.createValueForNode(node);
154 switch (node->op()) {
157 case Int52Constant: {
158 setBuiltInConstant(node, *node->constant());
162 case LazyJSConstant: {
163 LazyJSValue value = node->lazyJSValue();
164 switch (value.kind()) {
165 case LazyJSValue::KnownValue:
166 setConstant(node, value.value()->value());
168 case LazyJSValue::SingleCharacterString:
169 case LazyJSValue::KnownStringImpl:
170 case LazyJSValue::NewStringImpl:
171 forNode(node).setType(m_graph, SpecString);
178 forNode(node) = forNode(node->child1());
179 if (forNode(node).value())
180 m_state.setFoundConstants(true);
184 case ExtractOSREntryLocal: {
185 forNode(node).makeBytecodeTop();
190 VariableAccessData* variableAccessData = node->variableAccessData();
191 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
192 // The value in the local should already be checked.
193 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
195 m_state.setFoundConstants(true);
196 forNode(node) = value;
201 StackAccessData* data = node->stackAccessData();
202 AbstractValue value = m_state.variables().operand(data->local);
203 // The value in the local should already be checked.
204 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
206 m_state.setFoundConstants(true);
207 forNode(node) = value;
211 case GetLocalUnlinked: {
212 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
214 m_state.setFoundConstants(true);
215 forNode(node) = value;
220 m_state.variables().operand(node->local()) = forNode(node->child1());
225 m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
230 // Don't need to do anything. A MovHint only informs us about what would have happened
231 // in bytecode, but this code is just concerned with what is actually happening during
237 // This is just a hint telling us that the OSR state of the local is no longer inside the
243 // Assert that the state of arguments has been set. SetArgument means that someone set
244 // the argument values out-of-band, and currently this always means setting to a
246 ASSERT(!m_state.variables().operand(node->local()).isClear());
250 case ForwardVarargs: {
251 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
252 // itself into a straight-line sequence of GetStack/PutStack.
253 // https://bugs.webkit.org/show_bug.cgi?id=143071
254 clobberWorld(node->origin.semantic, clobberLimit);
255 LoadVarargsData* data = node->loadVarargsData();
256 m_state.variables().operand(data->count).setType(SpecInt32Only);
257 for (unsigned i = data->limit - 1; i--;)
258 m_state.variables().operand(data->start.offset() + i).makeHeapTop();
268 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
269 clobberWorld(node->origin.semantic, clobberLimit);
270 forNode(node).setType(m_graph, SpecInt32Only);
274 JSValue left = forNode(node->child1()).value();
275 JSValue right = forNode(node->child2()).value();
276 if (left && right && left.isInt32() && right.isInt32()) {
277 int32_t a = left.asInt32();
278 int32_t b = right.asInt32();
279 switch (node->op()) {
281 setConstant(node, JSValue(a & b));
284 setConstant(node, JSValue(a | b));
287 setConstant(node, JSValue(a ^ b));
290 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
293 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
296 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
299 RELEASE_ASSERT_NOT_REACHED();
305 if (node->op() == BitAnd
306 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
307 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
308 forNode(node).setType(SpecBoolInt32);
312 forNode(node).setType(SpecInt32Only);
316 case UInt32ToNumber: {
317 JSValue child = forNode(node->child1()).value();
318 if (doesOverflow(node->arithMode())) {
320 if (child && child.isAnyInt()) {
321 int64_t machineInt = child.asAnyInt();
322 setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
325 forNode(node).setType(SpecAnyInt);
328 if (child && child.isInt32()) {
329 uint32_t value = child.asInt32();
330 setConstant(node, jsNumber(value));
333 forNode(node).setType(SpecAnyIntAsDouble);
336 if (child && child.isInt32()) {
337 int32_t value = child.asInt32();
339 setConstant(node, jsNumber(value));
343 forNode(node).setType(SpecInt32Only);
347 case BooleanToNumber: {
348 JSValue concreteValue = forNode(node->child1()).value();
350 if (concreteValue.isBoolean())
351 setConstant(node, jsNumber(concreteValue.asBoolean()));
353 setConstant(node, *m_graph.freeze(concreteValue));
356 AbstractValue& value = forNode(node);
357 value = forNode(node->child1());
358 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
359 m_state.setFoundConstants(true);
360 if (value.m_type & SpecBoolean) {
361 value.merge(SpecBoolInt32);
362 value.filter(~SpecBoolean);
367 case DoubleAsInt32: {
368 JSValue child = forNode(node->child1()).value();
369 if (child && child.isNumber()) {
370 double asDouble = child.asNumber();
371 int32_t asInt = JSC::toInt32(asDouble);
372 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
373 setConstant(node, JSValue(asInt));
377 forNode(node).setType(SpecInt32Only);
382 JSValue child = forNode(node->child1()).value();
384 if (child.isNumber()) {
386 setConstant(node, child);
388 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
391 if (child.isBoolean()) {
392 setConstant(node, jsNumber(child.asBoolean()));
395 if (child.isUndefinedOrNull()) {
396 setConstant(node, jsNumber(0));
401 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
402 forNode(node).setType(SpecBoolInt32);
406 forNode(node).setType(SpecInt32Only);
411 JSValue child = forNode(node->child1()).value();
413 if (child.isNumber()) {
414 setConstant(node, jsDoubleNumber(child.asNumber()));
417 if (child.isUndefined()) {
418 setConstant(node, jsDoubleNumber(PNaN));
421 if (child.isNull() || child.isFalse()) {
422 setConstant(node, jsDoubleNumber(0));
425 if (child.isTrue()) {
426 setConstant(node, jsDoubleNumber(1));
431 SpeculatedType type = forNode(node->child1()).m_type;
432 switch (node->child1().useKind()) {
434 if (type & SpecOther) {
436 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
438 if (type & SpecBoolean) {
439 type &= ~SpecBoolean;
440 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
442 type &= SpecBytecodeNumber;
452 RELEASE_ASSERT_NOT_REACHED();
454 forNode(node).setType(type);
455 forNode(node).fixTypeForRepresentation(m_graph, node);
460 JSValue child = forNode(node->child1()).value();
461 if (child && child.isAnyInt()) {
462 setConstant(node, child);
466 forNode(node).setType(SpecInt32Only);
471 JSValue value = forNode(node->child1()).value();
473 setConstant(node, value);
477 forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
478 forNode(node).fixTypeForRepresentation(m_graph, node);
483 ASSERT(node->binaryUseKind() == UntypedUse);
484 clobberWorld(node->origin.semantic, clobberLimit);
485 forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
490 forNode(node).setType(m_graph, SpecString);
495 JSValue left = forNode(node->child1()).value();
496 JSValue right = forNode(node->child2()).value();
497 switch (node->binaryUseKind()) {
499 if (left && right && left.isInt32() && right.isInt32()) {
500 if (!shouldCheckOverflow(node->arithMode())) {
501 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
504 JSValue result = jsNumber(left.asNumber() + right.asNumber());
505 if (result.isInt32()) {
506 setConstant(node, result);
510 forNode(node).setType(SpecInt32Only);
513 if (left && right && left.isAnyInt() && right.isAnyInt()) {
514 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
515 if (result.isAnyInt()) {
516 setConstant(node, result);
520 forNode(node).setType(SpecAnyInt);
523 if (left && right && left.isNumber() && right.isNumber()) {
524 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
527 forNode(node).setType(
529 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
532 RELEASE_ASSERT_NOT_REACHED();
539 JSValue operand = forNode(node->child1()).value();
540 if (operand && operand.isNumber()) {
541 uint32_t value = toUInt32(operand.asNumber());
542 setConstant(node, jsNumber(clz32(value)));
545 forNode(node).setType(SpecInt32Only);
550 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
555 JSValue left = forNode(node->child1()).value();
556 JSValue right = forNode(node->child2()).value();
557 switch (node->binaryUseKind()) {
559 if (left && right && left.isInt32() && right.isInt32()) {
560 if (!shouldCheckOverflow(node->arithMode())) {
561 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
564 JSValue result = jsNumber(left.asNumber() - right.asNumber());
565 if (result.isInt32()) {
566 setConstant(node, result);
570 forNode(node).setType(SpecInt32Only);
573 if (left && right && left.isAnyInt() && right.isAnyInt()) {
574 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
575 if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
576 setConstant(node, result);
580 forNode(node).setType(SpecAnyInt);
583 if (left && right && left.isNumber() && right.isNumber()) {
584 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
587 forNode(node).setType(
588 typeOfDoubleDifference(
589 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
592 clobberWorld(node->origin.semantic, clobberLimit);
593 forNode(node).setType(m_graph, SpecBytecodeNumber);
596 RELEASE_ASSERT_NOT_REACHED();
603 JSValue child = forNode(node->child1()).value();
604 switch (node->child1().useKind()) {
606 if (child && child.isInt32()) {
607 if (!shouldCheckOverflow(node->arithMode())) {
608 setConstant(node, jsNumber(-child.asInt32()));
612 if (shouldCheckNegativeZero(node->arithMode()))
613 doubleResult = -child.asNumber();
615 doubleResult = 0 - child.asNumber();
616 JSValue valueResult = jsNumber(doubleResult);
617 if (valueResult.isInt32()) {
618 setConstant(node, valueResult);
622 forNode(node).setType(SpecInt32Only);
625 if (child && child.isAnyInt()) {
627 if (shouldCheckNegativeZero(node->arithMode()))
628 doubleResult = -child.asNumber();
630 doubleResult = 0 - child.asNumber();
631 JSValue valueResult = jsNumber(doubleResult);
632 if (valueResult.isAnyInt()) {
633 setConstant(node, valueResult);
637 forNode(node).setType(SpecAnyInt);
640 if (child && child.isNumber()) {
641 setConstant(node, jsDoubleNumber(-child.asNumber()));
644 forNode(node).setType(
645 typeOfDoubleNegation(
646 forNode(node->child1()).m_type));
649 RELEASE_ASSERT_NOT_REACHED();
656 JSValue left = forNode(node->child1()).value();
657 JSValue right = forNode(node->child2()).value();
658 switch (node->binaryUseKind()) {
660 if (left && right && left.isInt32() && right.isInt32()) {
661 if (!shouldCheckOverflow(node->arithMode())) {
662 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
665 double doubleResult = left.asNumber() * right.asNumber();
666 if (!shouldCheckNegativeZero(node->arithMode()))
667 doubleResult += 0; // Sanitizes zero.
668 JSValue valueResult = jsNumber(doubleResult);
669 if (valueResult.isInt32()) {
670 setConstant(node, valueResult);
674 forNode(node).setType(SpecInt32Only);
677 if (left && right && left.isAnyInt() && right.isAnyInt()) {
678 double doubleResult = left.asNumber() * right.asNumber();
679 if (!shouldCheckNegativeZero(node->arithMode()))
681 JSValue valueResult = jsNumber(doubleResult);
682 if (valueResult.isAnyInt()) {
683 setConstant(node, valueResult);
687 forNode(node).setType(SpecAnyInt);
690 if (left && right && left.isNumber() && right.isNumber()) {
691 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
694 forNode(node).setType(
696 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
699 clobberWorld(node->origin.semantic, clobberLimit);
700 forNode(node).setType(m_graph, SpecBytecodeNumber);
703 RELEASE_ASSERT_NOT_REACHED();
710 JSValue left = forNode(node->child1()).value();
711 JSValue right = forNode(node->child2()).value();
712 switch (node->binaryUseKind()) {
714 if (left && right && left.isInt32() && right.isInt32()) {
715 double doubleResult = left.asNumber() / right.asNumber();
716 if (!shouldCheckOverflow(node->arithMode()))
717 doubleResult = toInt32(doubleResult);
718 else if (!shouldCheckNegativeZero(node->arithMode()))
719 doubleResult += 0; // Sanitizes zero.
720 JSValue valueResult = jsNumber(doubleResult);
721 if (valueResult.isInt32()) {
722 setConstant(node, valueResult);
726 forNode(node).setType(SpecInt32Only);
729 if (left && right && left.isNumber() && right.isNumber()) {
730 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
733 forNode(node).setType(
734 typeOfDoubleQuotient(
735 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
738 clobberWorld(node->origin.semantic, clobberLimit);
739 forNode(node).setType(m_graph, SpecBytecodeNumber);
742 RELEASE_ASSERT_NOT_REACHED();
749 JSValue left = forNode(node->child1()).value();
750 JSValue right = forNode(node->child2()).value();
751 switch (node->binaryUseKind()) {
753 if (left && right && left.isInt32() && right.isInt32()) {
754 double doubleResult = fmod(left.asNumber(), right.asNumber());
755 if (!shouldCheckOverflow(node->arithMode()))
756 doubleResult = toInt32(doubleResult);
757 else if (!shouldCheckNegativeZero(node->arithMode()))
758 doubleResult += 0; // Sanitizes zero.
759 JSValue valueResult = jsNumber(doubleResult);
760 if (valueResult.isInt32()) {
761 setConstant(node, valueResult);
765 forNode(node).setType(SpecInt32Only);
768 if (left && right && left.isNumber() && right.isNumber()) {
769 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
772 forNode(node).setType(
773 typeOfDoubleBinaryOp(
774 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
777 RELEASE_ASSERT_NOT_REACHED();
784 JSValue left = forNode(node->child1()).value();
785 JSValue right = forNode(node->child2()).value();
786 switch (node->binaryUseKind()) {
788 if (left && right && left.isInt32() && right.isInt32()) {
789 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
792 forNode(node).setType(SpecInt32Only);
795 if (left && right && left.isNumber() && right.isNumber()) {
796 double a = left.asNumber();
797 double b = right.asNumber();
798 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
801 forNode(node).setType(
803 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
806 RELEASE_ASSERT_NOT_REACHED();
813 JSValue left = forNode(node->child1()).value();
814 JSValue right = forNode(node->child2()).value();
815 switch (node->binaryUseKind()) {
817 if (left && right && left.isInt32() && right.isInt32()) {
818 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
821 forNode(node).setType(SpecInt32Only);
824 if (left && right && left.isNumber() && right.isNumber()) {
825 double a = left.asNumber();
826 double b = right.asNumber();
827 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
830 forNode(node).setType(
832 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
835 RELEASE_ASSERT_NOT_REACHED();
842 JSValue child = forNode(node->child1()).value();
843 switch (node->child1().useKind()) {
845 if (child && child.isInt32()) {
846 JSValue result = jsNumber(fabs(child.asNumber()));
847 if (result.isInt32()) {
848 setConstant(node, result);
852 forNode(node).setType(SpecInt32Only);
855 if (child && child.isNumber()) {
856 setConstant(node, jsDoubleNumber(fabs(child.asNumber())));
859 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
862 RELEASE_ASSERT_NOT_REACHED();
869 JSValue childY = forNode(node->child2()).value();
870 if (childY && childY.isNumber()) {
871 if (!childY.asNumber()) {
872 setConstant(node, jsDoubleNumber(1));
876 JSValue childX = forNode(node->child1()).value();
877 if (childX && childX.isNumber()) {
878 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
882 forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
887 forNode(node).setType(m_graph, SpecDoubleReal);
895 JSValue operand = forNode(node->child1()).value();
896 if (operand && operand.isNumber()) {
897 double roundedValue = 0;
898 if (node->op() == ArithRound)
899 roundedValue = jsRound(operand.asNumber());
900 else if (node->op() == ArithFloor)
901 roundedValue = floor(operand.asNumber());
902 else if (node->op() == ArithCeil)
903 roundedValue = ceil(operand.asNumber());
905 ASSERT(node->op() == ArithTrunc);
906 roundedValue = trunc(operand.asNumber());
909 if (producesInteger(node->arithRoundingMode())) {
910 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
911 if (roundedValueAsInt32 == roundedValue) {
912 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
913 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
914 setConstant(node, jsNumber(roundedValueAsInt32));
918 setConstant(node, jsNumber(roundedValueAsInt32));
923 setConstant(node, jsDoubleNumber(roundedValue));
927 if (producesInteger(node->arithRoundingMode()))
928 forNode(node).setType(SpecInt32Only);
930 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
935 JSValue child = forNode(node->child1()).value();
936 if (child && child.isNumber()) {
937 setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
940 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
945 JSValue child = forNode(node->child1()).value();
946 if (child && child.isNumber()) {
947 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
950 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
955 JSValue child = forNode(node->child1()).value();
956 if (child && child.isNumber()) {
957 setConstant(node, jsDoubleNumber(sin(child.asNumber())));
960 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
965 JSValue child = forNode(node->child1()).value();
966 if (child && child.isNumber()) {
967 setConstant(node, jsDoubleNumber(cos(child.asNumber())));
970 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
975 JSValue child = forNode(node->child1()).value();
976 if (child && child.isNumber()) {
977 setConstant(node, jsDoubleNumber(log(child.asNumber())));
980 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
985 switch (booleanResult(node, forNode(node->child1()))) {
987 setConstant(node, jsBoolean(false));
989 case DefinitelyFalse:
990 setConstant(node, jsBoolean(true));
993 forNode(node).setType(SpecBoolean);
1001 case IsArrayConstructor:
1007 case IsObjectOrNull:
1009 case IsRegExpObject: {
1010 AbstractValue child = forNode(node->child1());
1011 if (child.value()) {
1012 bool constantWasSet = true;
1013 switch (node->op()) {
1015 if (child.value().isObject()) {
1016 if (child.value().getObject()->type() == ArrayType) {
1017 setConstant(node, jsBoolean(true));
1021 if (child.value().getObject()->type() == ProxyObjectType) {
1022 // We have no way of knowing what type we are proxing yet.
1023 constantWasSet = false;
1028 setConstant(node, jsBoolean(false));
1031 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
1033 case IsArrayConstructor:
1034 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->classInfo() == ArrayConstructor::info()));
1037 setConstant(node, jsBoolean(
1038 child.value().isCell()
1039 ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1040 : child.value().isUndefined()));
1043 setConstant(node, jsBoolean(child.value().isBoolean()));
1046 setConstant(node, jsBoolean(child.value().isNumber()));
1049 setConstant(node, jsBoolean(isJSString(child.value())));
1052 setConstant(node, jsBoolean(child.value().isObject()));
1054 case IsObjectOrNull:
1055 if (child.value().isObject()) {
1056 JSObject* object = asObject(child.value());
1057 if (object->type() == JSFunctionType)
1058 setConstant(node, jsBoolean(false));
1059 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1060 setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1062 // FIXME: This could just call getCallData.
1063 // https://bugs.webkit.org/show_bug.cgi?id=144457
1064 constantWasSet = false;
1067 setConstant(node, jsBoolean(child.value().isNull()));
1070 if (child.value().isObject()) {
1071 JSObject* object = asObject(child.value());
1072 if (object->type() == JSFunctionType)
1073 setConstant(node, jsBoolean(true));
1074 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1075 setConstant(node, jsBoolean(false));
1077 // FIXME: This could just call getCallData.
1078 // https://bugs.webkit.org/show_bug.cgi?id=144457
1079 constantWasSet = false;
1082 setConstant(node, jsBoolean(false));
1084 case IsRegExpObject:
1085 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
1088 constantWasSet = false;
1095 // FIXME: This code should really use AbstractValue::isType() and
1096 // AbstractValue::couldBeType().
1097 // https://bugs.webkit.org/show_bug.cgi?id=146870
1099 bool constantWasSet = false;
1100 switch (node->op()) {
1103 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1104 if (!(child.m_type & ~SpecArray)) {
1105 setConstant(node, jsBoolean(true));
1106 constantWasSet = true;
1110 if (!(child.m_type & SpecObject)) {
1111 setConstant(node, jsBoolean(false));
1112 constantWasSet = true;
1118 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1119 // https://bugs.webkit.org/show_bug.cgi?id=144456
1121 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1122 setConstant(node, jsBoolean(false));
1123 constantWasSet = true;
1129 if (!(child.m_type & ~SpecBoolean)) {
1130 setConstant(node, jsBoolean(true));
1131 constantWasSet = true;
1135 if (!(child.m_type & SpecBoolean)) {
1136 setConstant(node, jsBoolean(false));
1137 constantWasSet = true;
1143 if (!(child.m_type & ~SpecFullNumber)) {
1144 setConstant(node, jsBoolean(true));
1145 constantWasSet = true;
1149 if (!(child.m_type & SpecFullNumber)) {
1150 setConstant(node, jsBoolean(false));
1151 constantWasSet = true;
1157 if (!(child.m_type & ~SpecString)) {
1158 setConstant(node, jsBoolean(true));
1159 constantWasSet = true;
1163 if (!(child.m_type & SpecString)) {
1164 setConstant(node, jsBoolean(false));
1165 constantWasSet = true;
1171 if (!(child.m_type & ~SpecObject)) {
1172 setConstant(node, jsBoolean(true));
1173 constantWasSet = true;
1177 if (!(child.m_type & SpecObject)) {
1178 setConstant(node, jsBoolean(false));
1179 constantWasSet = true;
1184 case IsObjectOrNull:
1185 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1186 // https://bugs.webkit.org/show_bug.cgi?id=144456
1188 // These expressions are complicated to parse. A helpful way to parse this is that
1189 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1190 // disjoint set from S". Things like "T - S" means that, provided that S is a
1191 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1192 // mean the "union of T and S".
1194 // Is the child's type an object that isn't an other-object (i.e. object that could
1195 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1197 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1198 setConstant(node, jsBoolean(true));
1199 constantWasSet = true;
1203 // Is the child's type definitely not either of: an object that isn't a function,
1204 // or either undefined or null? Then: we should fold this to false. This means
1205 // for example that if it's any non-function object, including those that have
1206 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1207 // if it's undefined-or-null, since the type bits don't distinguish between
1208 // undefined (which should fold to false) and null (which should fold to true).
1209 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1210 setConstant(node, jsBoolean(false));
1211 constantWasSet = true;
1217 if (!(child.m_type & ~SpecFunction)) {
1218 setConstant(node, jsBoolean(true));
1219 constantWasSet = true;
1223 if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
1224 setConstant(node, jsBoolean(false));
1225 constantWasSet = true;
1230 case IsRegExpObject:
1231 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1232 if (!(child.m_type & ~SpecRegExpObject)) {
1233 setConstant(node, jsBoolean(true));
1234 constantWasSet = true;
1237 if (!(child.m_type & SpecObject)) {
1238 setConstant(node, jsBoolean(false));
1239 constantWasSet = true;
1250 forNode(node).setType(SpecBoolean);
1255 VM* vm = m_codeBlock->vm();
1256 JSValue child = forNode(node->child1()).value();
1257 AbstractValue& abstractChild = forNode(node->child1());
1259 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1260 setConstant(node, *m_graph.freeze(typeString));
1264 if (isFullNumberSpeculation(abstractChild.m_type)) {
1265 setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
1269 if (isStringSpeculation(abstractChild.m_type)) {
1270 setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
1274 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1275 // https://bugs.webkit.org/show_bug.cgi?id=144456
1276 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1277 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
1281 if (isFunctionSpeculation(abstractChild.m_type)) {
1282 setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
1286 if (isBooleanSpeculation(abstractChild.m_type)) {
1287 setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
1291 if (isSymbolSpeculation(abstractChild.m_type)) {
1292 setConstant(node, *m_graph.freeze(vm->smallStrings.symbolString()));
1296 forNode(node).setType(m_graph, SpecStringIdent);
1302 case CompareGreater:
1303 case CompareGreaterEq:
1305 JSValue leftConst = forNode(node->child1()).value();
1306 JSValue rightConst = forNode(node->child2()).value();
1307 if (leftConst && rightConst) {
1308 if (leftConst.isNumber() && rightConst.isNumber()) {
1309 double a = leftConst.asNumber();
1310 double b = rightConst.asNumber();
1311 switch (node->op()) {
1313 setConstant(node, jsBoolean(a < b));
1316 setConstant(node, jsBoolean(a <= b));
1318 case CompareGreater:
1319 setConstant(node, jsBoolean(a > b));
1321 case CompareGreaterEq:
1322 setConstant(node, jsBoolean(a >= b));
1325 setConstant(node, jsBoolean(a == b));
1328 RELEASE_ASSERT_NOT_REACHED();
1334 if (leftConst.isString() && rightConst.isString()) {
1335 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1336 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1339 if (node->op() == CompareEq)
1340 result = WTF::equal(a, b);
1341 else if (node->op() == CompareLess)
1342 result = codePointCompare(a, b) < 0;
1343 else if (node->op() == CompareLessEq)
1344 result = codePointCompare(a, b) <= 0;
1345 else if (node->op() == CompareGreater)
1346 result = codePointCompare(a, b) > 0;
1347 else if (node->op() == CompareGreaterEq)
1348 result = codePointCompare(a, b) >= 0;
1350 RELEASE_ASSERT_NOT_REACHED();
1351 setConstant(node, jsBoolean(result));
1356 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1357 setConstant(node, jsBoolean(asSymbol(leftConst)->privateName() == asSymbol(rightConst)->privateName()));
1362 if (node->op() == CompareEq) {
1363 SpeculatedType leftType = forNode(node->child1()).m_type;
1364 SpeculatedType rightType = forNode(node->child2()).m_type;
1365 if (!valuesCouldBeEqual(leftType, rightType)) {
1366 setConstant(node, jsBoolean(false));
1370 if (leftType == SpecOther)
1371 std::swap(leftType, rightType);
1372 if (rightType == SpecOther) {
1373 // Undefined and Null are always equal when compared to eachother.
1374 if (!(leftType & ~SpecOther)) {
1375 setConstant(node, jsBoolean(true));
1379 // Any other type compared to Null or Undefined is always false
1380 // as long as the MasqueradesAsUndefined watchpoint is valid.
1382 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1383 // cases are always "false".
1384 if (!(leftType & (SpecObjectOther | SpecOther))) {
1385 setConstant(node, jsBoolean(false));
1389 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1390 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1391 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1392 setConstant(node, jsBoolean(false));
1398 if (node->child1() == node->child2()) {
1399 if (node->isBinaryUseKind(Int32Use) ||
1400 node->isBinaryUseKind(Int52RepUse) ||
1401 node->isBinaryUseKind(StringUse) ||
1402 node->isBinaryUseKind(BooleanUse) ||
1403 node->isBinaryUseKind(SymbolUse) ||
1404 node->isBinaryUseKind(StringIdentUse) ||
1405 node->isBinaryUseKind(ObjectUse) ||
1406 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1407 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1408 switch (node->op()) {
1410 case CompareGreater:
1411 setConstant(node, jsBoolean(false));
1414 case CompareGreaterEq:
1416 setConstant(node, jsBoolean(true));
1419 DFG_CRASH(m_graph, node, "Unexpected node type");
1426 forNode(node).setType(SpecBoolean);
1430 case CompareStrictEq: {
1431 Node* leftNode = node->child1().node();
1432 Node* rightNode = node->child2().node();
1433 JSValue left = forNode(leftNode).value();
1434 JSValue right = forNode(rightNode).value();
1435 if (left && right) {
1436 if (left.isString() && right.isString()) {
1437 // We need this case because JSValue::strictEqual is otherwise too racy for
1438 // string comparisons.
1439 const StringImpl* a = asString(left)->tryGetValueImpl();
1440 const StringImpl* b = asString(right)->tryGetValueImpl();
1442 setConstant(node, jsBoolean(WTF::equal(a, b)));
1446 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1451 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1452 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1453 if (!(leftLUB & rightLUB)) {
1454 setConstant(node, jsBoolean(false));
1458 if (node->child1() == node->child2()) {
1459 if (node->isBinaryUseKind(BooleanUse) ||
1460 node->isBinaryUseKind(Int32Use) ||
1461 node->isBinaryUseKind(Int52RepUse) ||
1462 node->isBinaryUseKind(StringUse) ||
1463 node->isBinaryUseKind(StringIdentUse) ||
1464 node->isBinaryUseKind(SymbolUse) ||
1465 node->isBinaryUseKind(ObjectUse) ||
1466 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1467 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1468 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1469 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1470 node->isBinaryUseKind(StringUse, UntypedUse) ||
1471 node->isBinaryUseKind(UntypedUse, StringUse)) {
1472 setConstant(node, jsBoolean(true));
1477 forNode(node).setType(SpecBoolean);
1481 case StringCharCodeAt:
1482 forNode(node).setType(SpecInt32Only);
1485 case StringFromCharCode:
1486 forNode(node).setType(m_graph, SpecString);
1490 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1494 switch (node->arrayMode().type()) {
1495 case Array::SelectUsingPredictions:
1496 case Array::Unprofiled:
1497 case Array::SelectUsingArguments:
1498 RELEASE_ASSERT_NOT_REACHED();
1500 case Array::ForceExit:
1501 m_state.setIsValid(false);
1503 case Array::Undecided: {
1504 JSValue index = forNode(node->child2()).value();
1505 if (index && index.isInt32() && index.asInt32() >= 0) {
1506 setConstant(node, jsUndefined());
1509 forNode(node).setType(SpecOther);
1512 case Array::Generic:
1513 clobberWorld(node->origin.semantic, clobberLimit);
1514 forNode(node).makeHeapTop();
1517 if (node->arrayMode().isOutOfBounds()) {
1518 // If the watchpoint was still valid we could totally set this to be
1519 // SpecString | SpecOther. Except that we'd have to be careful. If we
1520 // tested the watchpoint state here then it could change by the time
1521 // we got to the backend. So to do this right, we'd have to get the
1522 // fixup phase to check the watchpoint state and then bake into the
1523 // GetByVal operation the fact that we're using a watchpoint, using
1524 // something like Array::SaneChain (except not quite, because that
1525 // implies an in-bounds access). None of this feels like it's worth it,
1526 // so we're going with TOP for now. The same thing applies to
1527 // clobbering the world.
1528 clobberWorld(node->origin.semantic, clobberLimit);
1529 forNode(node).makeHeapTop();
1531 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1533 case Array::DirectArguments:
1534 case Array::ScopedArguments:
1535 forNode(node).makeHeapTop();
1538 if (node->arrayMode().isOutOfBounds()) {
1539 clobberWorld(node->origin.semantic, clobberLimit);
1540 forNode(node).makeHeapTop();
1542 forNode(node).setType(SpecInt32Only);
1545 if (node->arrayMode().isOutOfBounds()) {
1546 clobberWorld(node->origin.semantic, clobberLimit);
1547 forNode(node).makeHeapTop();
1548 } else if (node->arrayMode().isSaneChain())
1549 forNode(node).setType(SpecBytecodeDouble);
1551 forNode(node).setType(SpecDoubleReal);
1553 case Array::Contiguous:
1554 case Array::ArrayStorage:
1555 case Array::SlowPutArrayStorage:
1556 if (node->arrayMode().isOutOfBounds())
1557 clobberWorld(node->origin.semantic, clobberLimit);
1558 forNode(node).makeHeapTop();
1560 case Array::Int8Array:
1561 forNode(node).setType(SpecInt32Only);
1563 case Array::Int16Array:
1564 forNode(node).setType(SpecInt32Only);
1566 case Array::Int32Array:
1567 forNode(node).setType(SpecInt32Only);
1569 case Array::Uint8Array:
1570 forNode(node).setType(SpecInt32Only);
1572 case Array::Uint8ClampedArray:
1573 forNode(node).setType(SpecInt32Only);
1575 case Array::Uint16Array:
1576 forNode(node).setType(SpecInt32Only);
1578 case Array::Uint32Array:
1579 if (node->shouldSpeculateInt32())
1580 forNode(node).setType(SpecInt32Only);
1581 else if (enableInt52() && node->shouldSpeculateAnyInt())
1582 forNode(node).setType(SpecAnyInt);
1584 forNode(node).setType(SpecAnyIntAsDouble);
1586 case Array::Float32Array:
1587 forNode(node).setType(SpecFullDouble);
1589 case Array::Float64Array:
1590 forNode(node).setType(SpecFullDouble);
1593 RELEASE_ASSERT_NOT_REACHED();
1599 case PutByValDirect:
1601 case PutByValAlias: {
1602 switch (node->arrayMode().modeForPut().type()) {
1603 case Array::ForceExit:
1604 m_state.setIsValid(false);
1606 case Array::Generic:
1607 clobberWorld(node->origin.semantic, clobberLimit);
1610 if (node->arrayMode().isOutOfBounds())
1611 clobberWorld(node->origin.semantic, clobberLimit);
1614 if (node->arrayMode().isOutOfBounds())
1615 clobberWorld(node->origin.semantic, clobberLimit);
1617 case Array::Contiguous:
1618 case Array::ArrayStorage:
1619 if (node->arrayMode().isOutOfBounds())
1620 clobberWorld(node->origin.semantic, clobberLimit);
1622 case Array::SlowPutArrayStorage:
1623 if (node->arrayMode().mayStoreToHole())
1624 clobberWorld(node->origin.semantic, clobberLimit);
1633 clobberWorld(node->origin.semantic, clobberLimit);
1634 forNode(node).setType(SpecBytecodeNumber);
1638 clobberWorld(node->origin.semantic, clobberLimit);
1639 forNode(node).makeHeapTop();
1642 case GetMyArgumentByVal:
1643 case GetMyArgumentByValOutOfBounds: {
1644 JSValue index = forNode(node->child2()).m_value;
1645 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1647 if (index && index.isInt32()) {
1648 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1649 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1650 // paths as unreachable, or to return undefined. We could implement that eventually.
1652 if (inlineCallFrame) {
1653 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
1654 forNode(node) = m_state.variables().operand(
1655 virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
1656 m_state.setFoundConstants(true);
1660 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
1661 forNode(node) = m_state.variables().argument(index.asInt32() + 1);
1662 m_state.setFoundConstants(true);
1668 if (inlineCallFrame) {
1669 // We have a bound on the types even though it's random access. Take advantage of this.
1671 AbstractValue result;
1672 for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
1674 m_state.variables().operand(
1675 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1678 if (node->op() == GetMyArgumentByValOutOfBounds)
1679 result.merge(SpecOther);
1682 m_state.setFoundConstants(true);
1684 forNode(node) = result;
1688 forNode(node).makeHeapTop();
1693 if (node->child2().useKind() == RegExpObjectUse
1694 && node->child3().useKind() == StringUse) {
1695 // This doesn't clobber the world since there are no conversions to perform.
1697 clobberWorld(node->origin.semantic, clobberLimit);
1698 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
1699 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(globalObjectValue)) {
1700 if (!globalObject->isHavingABadTime()) {
1701 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1702 Structure* structure = globalObject->regExpMatchesArrayStructure();
1703 m_graph.registerStructure(structure);
1704 forNode(node).set(m_graph, structure);
1705 forNode(node).merge(SpecOther);
1710 forNode(node).setType(m_graph, SpecOther | SpecArray);
1714 if (node->child2().useKind() == RegExpObjectUse
1715 && node->child3().useKind() == StringUse) {
1716 // This doesn't clobber the world since there are no conversions to perform.
1718 clobberWorld(node->origin.semantic, clobberLimit);
1719 forNode(node).setType(SpecBoolean);
1723 if (node->child1().useKind() == StringUse
1724 && node->child2().useKind() == RegExpObjectUse
1725 && node->child3().useKind() == StringUse) {
1726 // This doesn't clobber the world. It just reads and writes regexp state.
1728 clobberWorld(node->origin.semantic, clobberLimit);
1729 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1736 Node* child = node->child1().node();
1737 BooleanResult result = booleanResult(node, forNode(child));
1738 if (result == DefinitelyTrue) {
1739 m_state.setBranchDirection(TakeTrue);
1742 if (result == DefinitelyFalse) {
1743 m_state.setBranchDirection(TakeFalse);
1746 // FIXME: The above handles the trivial cases of sparse conditional
1747 // constant propagation, but we can do better:
1748 // We can specialize the source variable's value on each direction of
1750 m_state.setBranchDirection(TakeBoth);
1755 // Nothing to do for now.
1756 // FIXME: Do sparse conditional things.
1761 m_state.setIsValid(false);
1765 case TailCallVarargs:
1766 case TailCallForwardVarargs:
1767 clobberWorld(node->origin.semantic, clobberLimit);
1768 m_state.setIsValid(false);
1772 case ThrowReferenceError:
1773 m_state.setIsValid(false);
1777 JSValue childConst = forNode(node->child1()).value();
1778 if (childConst && childConst.isNumber()) {
1779 setConstant(node, childConst);
1783 ASSERT(node->child1().useKind() == UntypedUse);
1785 if (!forNode(node->child1()).m_type) {
1786 m_state.setIsValid(false);
1790 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
1791 m_state.setFoundConstants(true);
1792 forNode(node) = forNode(node->child1());
1796 clobberWorld(node->origin.semantic, clobberLimit);
1798 forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
1803 case CallStringConstructor: {
1804 switch (node->child1().useKind()) {
1805 case StringObjectUse:
1806 // This also filters that the StringObject has the primordial StringObject
1810 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
1812 case StringOrStringObjectUse:
1816 clobberWorld(node->origin.semantic, clobberLimit);
1819 RELEASE_ASSERT_NOT_REACHED();
1822 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1826 case NewStringObject: {
1827 ASSERT(node->structure()->classInfo() == StringObject::info());
1828 forNode(node).set(m_graph, node->structure());
1835 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1838 case NewArrayBuffer:
1841 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1844 case NewArrayWithSize:
1845 forNode(node).setType(m_graph, SpecArray);
1849 switch (node->child1().useKind()) {
1853 clobberWorld(node->origin.semantic, clobberLimit);
1856 RELEASE_ASSERT_NOT_REACHED();
1861 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
1862 node->typedArrayType()));
1866 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
1870 AbstractValue& source = forNode(node->child1());
1871 AbstractValue& destination = forNode(node);
1873 if (source.m_type == SpecStringObject) {
1874 m_state.setFoundConstants(true);
1875 destination = source;
1879 if (m_graph.executableFor(node->origin.semantic)->isStrictMode()) {
1880 if (!(source.m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
1881 m_state.setFoundConstants(true);
1882 destination = source;
1885 destination.makeHeapTop();
1887 destination = source;
1888 destination.merge(SpecObject);
1894 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
1895 forNode(node).setType(m_graph, SpecFinalObject);
1900 ASSERT(node->structure());
1901 forNode(node).set(m_graph, node->structure());
1904 case CallObjectConstructor: {
1905 AbstractValue& source = forNode(node->child1());
1906 AbstractValue& destination = forNode(node);
1908 if (!(source.m_type & ~SpecObject)) {
1909 m_state.setFoundConstants(true);
1910 destination = source;
1914 forNode(node).setType(m_graph, SpecObject);
1918 case PhantomNewObject:
1919 case PhantomNewFunction:
1920 case PhantomNewGeneratorFunction:
1921 case PhantomCreateActivation:
1922 case PhantomDirectArguments:
1923 case PhantomClonedArguments:
1925 m_state.setDidClobber(true); // Prevent constant folding.
1926 // This claims to return bottom.
1932 case MaterializeNewObject: {
1935 m_phiChildren->forAllTransitiveIncomingValues(
1936 m_graph.varArgChild(node, 0).node(),
1937 [&] (Node* incoming) {
1938 set.add(incoming->castConstant<Structure*>());
1941 forNode(node).set(m_graph, set);
1945 case CreateActivation:
1946 case MaterializeCreateActivation:
1948 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
1951 case CreateDirectArguments:
1952 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
1955 case CreateScopedArguments:
1956 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
1959 case CreateClonedArguments:
1960 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
1963 case NewGeneratorFunction:
1965 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
1970 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
1974 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
1975 InferredValue* singleton = executable->singletonFunction();
1976 if (JSValue value = singleton->inferredValue()) {
1977 m_graph.watchpoints().addLazily(singleton);
1978 JSFunction* function = jsCast<JSFunction*>(value);
1979 setConstant(node, *m_graph.freeze(function));
1983 forNode(node).setType(m_graph, SpecFunction);
1986 case GetArgumentCount:
1987 forNode(node).setType(SpecInt32Only);
1991 forNode(node).setType(SpecInt32Only);
1995 JSValue base = forNode(node->child1()).m_value;
1997 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
1998 if (!getterSetter->isGetterNull()) {
1999 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
2004 forNode(node).setType(m_graph, SpecObject);
2009 JSValue base = forNode(node->child1()).m_value;
2011 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2012 if (!getterSetter->isSetterNull()) {
2013 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
2018 forNode(node).setType(m_graph, SpecObject);
2023 if (JSValue base = forNode(node->child1()).m_value) {
2024 if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
2025 setConstant(node, *m_graph.freeze(function->scope()));
2029 forNode(node).setType(m_graph, SpecObjectOther);
2033 JSValue child = forNode(node->child1()).value();
2035 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
2038 forNode(node).setType(m_graph, SpecObjectOther);
2042 case GetGlobalObject: {
2043 JSValue child = forNode(node->child1()).value();
2045 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
2049 if (forNode(node->child1()).m_structure.isFinite()) {
2050 JSGlobalObject* globalObject = nullptr;
2052 forNode(node->child1()).m_structure.forEach(
2053 [&] (Structure* structure) {
2055 globalObject = structure->globalObject();
2056 else if (globalObject != structure->globalObject())
2059 if (globalObject && ok) {
2060 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2065 forNode(node).setType(m_graph, SpecObjectOther);
2070 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
2071 setConstant(node, *m_graph.freeze(value));
2074 forNode(node).makeBytecodeTop();
2080 case GetRegExpObjectLastIndex:
2081 forNode(node).makeHeapTop();
2084 case SetRegExpObjectLastIndex:
2085 case RecordRegExpCachedResult:
2088 case GetFromArguments:
2089 forNode(node).makeHeapTop();
2092 case PutToArguments:
2096 // FIXME: This should constant fold at least as well as the normal GetById case.
2097 // https://bugs.webkit.org/show_bug.cgi?id=156422
2098 forNode(node).makeHeapTop();
2102 case GetByIdFlush: {
2103 if (!node->prediction()) {
2104 m_state.setIsValid(false);
2108 AbstractValue& value = forNode(node->child1());
2109 if (value.m_structure.isFinite()
2110 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
2111 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2112 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
2113 if (status.isSimple()) {
2114 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2115 // something more subtle?
2116 AbstractValue result;
2117 for (unsigned i = status.numVariants(); i--;) {
2118 // This thing won't give us a variant that involves prototypes. If it did, we'd
2119 // have more work to do here.
2120 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
2123 m_graph.inferredValueForProperty(
2124 value, uid, status[i].offset(), m_state.structureClobberState()));
2126 m_state.setFoundConstants(true);
2127 forNode(node) = result;
2132 clobberWorld(node->origin.semantic, clobberLimit);
2133 forNode(node).makeHeapTop();
2137 case GetArrayLength: {
2138 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2139 forNode(node->child1()).m_value, node->arrayMode());
2141 setConstant(node, jsNumber(view->length()));
2144 forNode(node).setType(SpecInt32Only);
2149 // FIXME: This could decide if the delete will be successful based on the set of structures that
2150 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2151 clobberWorld(node->origin.semantic, clobberLimit);
2152 forNode(node).setType(SpecBoolean);
2156 case CheckStructure: {
2157 AbstractValue& value = forNode(node->child1());
2159 StructureSet& set = node->structureSet();
2161 // It's interesting that we could have proven that the object has a larger structure set
2162 // that includes the set we're testing. In that case we could make the structure check
2163 // more efficient. We currently don't.
2165 if (value.m_structure.isSubsetOf(set))
2166 m_state.setFoundConstants(true);
2168 SpeculatedType admittedTypes = SpecNone;
2169 switch (node->child1().useKind()) {
2172 admittedTypes = SpecNone;
2174 case CellOrOtherUse:
2175 admittedTypes = SpecOther;
2178 DFG_CRASH(m_graph, node, "Bad use kind");
2182 filter(value, set, admittedTypes);
2186 case CheckStructureImmediate: {
2187 // FIXME: This currently can only reason about one structure at a time.
2188 // https://bugs.webkit.org/show_bug.cgi?id=136988
2190 AbstractValue& value = forNode(node->child1());
2191 StructureSet& set = node->structureSet();
2193 if (value.value()) {
2194 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
2195 if (set.contains(structure)) {
2196 m_state.setFoundConstants(true);
2200 m_state.setIsValid(false);
2204 if (m_phiChildren) {
2205 bool allGood = true;
2206 m_phiChildren->forAllTransitiveIncomingValues(
2208 [&] (Node* incoming) {
2209 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
2210 if (set.contains(structure))
2216 m_state.setFoundConstants(true);
2221 if (Structure* structure = set.onlyStructure()) {
2222 filterByValue(node->child1(), *m_graph.freeze(structure));
2226 // Aw shucks, we can't do anything!
2231 if (!forNode(node->child1()).m_structure.isClear()) {
2232 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
2233 m_state.setFoundConstants(true);
2236 clobberLimit, node->transition()->previous, node->transition()->next);
2237 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
2242 case AllocatePropertyStorage:
2243 case ReallocatePropertyStorage:
2244 forNode(node).clear(); // The result is not a JS value.
2247 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2248 m_state.setFoundConstants(true);
2251 switch (node->arrayMode().type()) {
2253 filter(node->child1(), SpecString);
2257 case Array::Contiguous:
2258 case Array::Undecided:
2259 case Array::ArrayStorage:
2260 case Array::SlowPutArrayStorage:
2262 case Array::DirectArguments:
2263 filter(node->child1(), SpecDirectArguments);
2265 case Array::ScopedArguments:
2266 filter(node->child1(), SpecScopedArguments);
2268 case Array::Int8Array:
2269 filter(node->child1(), SpecInt8Array);
2271 case Array::Int16Array:
2272 filter(node->child1(), SpecInt16Array);
2274 case Array::Int32Array:
2275 filter(node->child1(), SpecInt32Array);
2277 case Array::Uint8Array:
2278 filter(node->child1(), SpecUint8Array);
2280 case Array::Uint8ClampedArray:
2281 filter(node->child1(), SpecUint8ClampedArray);
2283 case Array::Uint16Array:
2284 filter(node->child1(), SpecUint16Array);
2286 case Array::Uint32Array:
2287 filter(node->child1(), SpecUint32Array);
2289 case Array::Float32Array:
2290 filter(node->child1(), SpecFloat32Array);
2292 case Array::Float64Array:
2293 filter(node->child1(), SpecFloat64Array);
2295 case Array::AnyTypedArray:
2296 filter(node->child1(), SpecTypedArrayView);
2299 RELEASE_ASSERT_NOT_REACHED();
2302 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2306 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2307 m_state.setFoundConstants(true);
2310 ASSERT(node->arrayMode().conversion() == Array::Convert);
2311 clobberStructures(clobberLimit);
2312 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2315 case ArrayifyToStructure: {
2316 AbstractValue& value = forNode(node->child1());
2317 if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
2318 m_state.setFoundConstants(true);
2319 clobberStructures(clobberLimit);
2321 // We have a bunch of options of how to express the abstract set at this point. Let set S
2322 // be the set of structures that the value had before clobbering and assume that all of
2323 // them are watchable. The new value should be the least expressible upper bound of the
2324 // intersection of "values that currently have structure = node->structure()" and "values
2325 // that have structure in S plus any structure transition-reachable from S". Assume that
2326 // node->structure() is not in S but it is transition-reachable from S. Then we would
2327 // like to say that the result is "values that have structure = node->structure() until
2328 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
2329 // we must choose between:
2331 // 1) "values that currently have structure = node->structure()". This is a valid
2332 // superset of the value that we really want, and it's specific enough to satisfy the
2333 // preconditions of the array access that this is guarding. It's also specific enough
2334 // to allow relevant optimizations in the case that we didn't have a contradiction
2335 // like in this example. Notice that in the abscence of any contradiction, this result
2336 // is precise rather than being a conservative LUB.
2338 // 2) "values that currently hava structure in S plus any structure transition-reachable
2339 // from S". This is also a valid superset of the value that we really want, but it's
2340 // not specific enough to satisfy the preconditions of the array access that this is
2341 // guarding - so playing such shenanigans would preclude us from having assertions on
2342 // the typing preconditions of any array accesses. This would also not be a desirable
2343 // answer in the absence of a contradiction.
2345 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
2346 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
2348 value.set(m_graph, node->structure());
2351 case GetIndexedPropertyStorage: {
2352 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2353 forNode(node->child1()).m_value, node->arrayMode());
2355 m_state.setFoundConstants(true);
2356 forNode(node).clear();
2359 case ConstantStoragePointer: {
2360 forNode(node).clear();
2364 case GetTypedArrayByteOffset: {
2365 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
2367 setConstant(node, jsNumber(view->byteOffset()));
2370 forNode(node).setType(SpecInt32Only);
2375 StorageAccessData& data = node->storageAccessData();
2376 UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2378 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2379 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2380 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2381 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2382 // on the type that ByteCodeParser was able to prove.
2383 AbstractValue value = m_graph.inferredValueForProperty(
2384 forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2386 // It's possible that the type that ByteCodeParser came up with is better.
2387 AbstractValue typeFromParsing;
2388 typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2389 value.filter(typeFromParsing);
2391 // If we decide that there does not exist any value that this can return, then it's probably
2392 // because the compilation was already invalidated.
2393 if (value.isClear())
2394 m_state.setIsValid(false);
2396 forNode(node) = value;
2398 m_state.setFoundConstants(true);
2402 case GetGetterSetterByOffset: {
2403 StorageAccessData& data = node->storageAccessData();
2404 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2405 if (result && jsDynamicCast<GetterSetter*>(result)) {
2406 setConstant(node, *m_graph.freeze(result));
2410 forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
2414 case MultiGetByOffset: {
2415 // This code will filter the base value in a manner that is possibly different (either more
2416 // or less precise) than the way it would be filtered if this was strength-reduced to a
2417 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2418 // different things about the code, so long as all of them are sound. That even includes
2419 // one guy proving that code should never execute (due to a contradiction) and another guy
2420 // not finding that contradiction. If someone ever proved that there would be a
2421 // contradiction then there must always be a contradiction even if subsequent passes don't
2422 // realize it. This is the case here.
2424 // Ordinarily you have to be careful with calling setFoundConstants()
2425 // because of the effect on compile times, but this node is FTL-only.
2426 m_state.setFoundConstants(true);
2428 UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2430 AbstractValue base = forNode(node->child1());
2431 StructureSet baseSet;
2432 AbstractValue result;
2433 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
2434 StructureSet set = getCase.set();
2440 switch (getCase.method().kind()) {
2441 case GetByOffsetMethod::Constant: {
2442 AbstractValue thisResult;
2445 *getCase.method().constant(),
2446 m_state.structureClobberState());
2447 result.merge(thisResult);
2451 case GetByOffsetMethod::Load: {
2453 m_graph.inferredValueForProperty(
2454 set, uid, m_state.structureClobberState()));
2459 result.makeHeapTop();
2464 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2465 m_state.setIsValid(false);
2467 forNode(node) = result;
2475 case MultiPutByOffset: {
2476 StructureSet newSet;
2477 TransitionVector transitions;
2479 // Ordinarily you have to be careful with calling setFoundConstants()
2480 // because of the effect on compile times, but this node is FTL-only.
2481 m_state.setFoundConstants(true);
2483 AbstractValue base = forNode(node->child1());
2484 AbstractValue originalValue = forNode(node->child2());
2485 AbstractValue resultingValue;
2487 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2488 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2489 StructureSet thisSet = variant.oldStructure();
2490 thisSet.filter(base);
2491 if (thisSet.isEmpty())
2494 AbstractValue thisValue = originalValue;
2495 thisValue.filter(m_graph, variant.requiredType());
2496 resultingValue.merge(thisValue);
2498 if (variant.kind() == PutByIdVariant::Transition) {
2499 if (thisSet.onlyStructure() != variant.newStructure()) {
2501 Transition(variant.oldStructureForTransition(), variant.newStructure()));
2502 } // else this is really a replace.
2503 newSet.add(variant.newStructure());
2505 ASSERT(variant.kind() == PutByIdVariant::Replace);
2506 newSet.merge(thisSet);
2510 observeTransitions(clobberLimit, transitions);
2511 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2512 m_state.setIsValid(false);
2513 forNode(node->child2()) = resultingValue;
2514 if (!!originalValue && !resultingValue)
2515 m_state.setIsValid(false);
2519 case GetExecutable: {
2520 JSValue value = forNode(node->child1()).value();
2522 JSFunction* function = jsDynamicCast<JSFunction*>(value);
2524 setConstant(node, *m_graph.freeze(function->executable()));
2528 forNode(node).setType(m_graph, SpecCellOther);
2533 JSValue value = forNode(node->child1()).value();
2534 if (value == node->cellOperand()->value()) {
2535 m_state.setFoundConstants(true);
2539 filterByValue(node->child1(), *node->cellOperand());
2543 case CheckNotEmpty: {
2544 AbstractValue& value = forNode(node->child1());
2545 if (!(value.m_type & SpecEmpty)) {
2546 m_state.setFoundConstants(true);
2550 filter(value, ~SpecEmpty);
2555 AbstractValue& value = forNode(node->child1());
2556 UniquedStringImpl* uid = node->uidOperand();
2557 ASSERT(uid->isSymbol() ? !(value.m_type & ~SpecSymbol) : !(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
2559 JSValue childConstant = value.value();
2560 if (childConstant) {
2561 if (uid->isSymbol()) {
2562 ASSERT(childConstant.isSymbol());
2563 if (asSymbol(childConstant)->privateName().uid() == uid) {
2564 m_state.setFoundConstants(true);
2568 ASSERT(childConstant.isString());
2569 if (asString(childConstant)->tryGetValueImpl() == uid) {
2570 m_state.setFoundConstants(true);
2576 filter(value, uid->isSymbol() ? SpecSymbol : SpecStringIdent);
2580 case CheckInBounds: {
2581 JSValue left = forNode(node->child1()).value();
2582 JSValue right = forNode(node->child2()).value();
2583 if (left && right && left.isInt32() && right.isInt32()
2584 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2585 m_state.setFoundConstants(true);
2593 case PutByIdDirect: {
2594 AbstractValue& value = forNode(node->child1());
2595 if (value.m_structure.isFinite()) {
2596 PutByIdStatus status = PutByIdStatus::computeFor(
2597 m_graph.globalObjectFor(node->origin.semantic),
2598 value.m_structure.set(),
2599 m_graph.identifiers()[node->identifierNumber()],
2600 node->op() == PutByIdDirect);
2602 if (status.isSimple()) {
2603 StructureSet newSet;
2604 TransitionVector transitions;
2606 for (unsigned i = status.numVariants(); i--;) {
2607 const PutByIdVariant& variant = status[i];
2608 if (variant.kind() == PutByIdVariant::Transition) {
2611 variant.oldStructureForTransition(), variant.newStructure()));
2612 m_graph.registerStructure(variant.newStructure());
2613 newSet.add(variant.newStructure());
2615 ASSERT(variant.kind() == PutByIdVariant::Replace);
2616 newSet.merge(variant.oldStructure());
2620 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
2621 m_state.setFoundConstants(true);
2623 observeTransitions(clobberLimit, transitions);
2624 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2625 m_state.setIsValid(false);
2630 clobberWorld(node->origin.semantic, clobberLimit);
2636 case PutGetterSetterById:
2637 case PutGetterByVal:
2638 case PutSetterByVal: {
2639 clobberWorld(node->origin.semantic, clobberLimit);
2644 // FIXME: We can determine when the property definitely exists based on abstract
2645 // value information.
2646 clobberWorld(node->origin.semantic, clobberLimit);
2647 forNode(node).setType(SpecBoolean);
2651 case GetEnumerableLength: {
2652 forNode(node).setType(SpecInt32Only);
2655 case HasGenericProperty: {
2656 forNode(node).setType(SpecBoolean);
2659 case HasStructureProperty: {
2660 forNode(node).setType(SpecBoolean);
2663 case HasIndexedProperty: {
2664 ArrayMode mode = node->arrayMode();
2665 switch (mode.type()) {
2668 case Array::Contiguous:
2669 case Array::ArrayStorage: {
2673 clobberWorld(node->origin.semantic, clobberLimit);
2677 forNode(node).setType(SpecBoolean);
2680 case GetDirectPname: {
2681 clobberWorld(node->origin.semantic, clobberLimit);
2682 forNode(node).makeHeapTop();
2685 case GetPropertyEnumerator: {
2686 forNode(node).setType(m_graph, SpecCell);
2689 case GetEnumeratorStructurePname: {
2690 forNode(node).setType(m_graph, SpecString | SpecOther);
2693 case GetEnumeratorGenericPname: {
2694 forNode(node).setType(m_graph, SpecString | SpecOther);
2697 case ToIndexString: {
2698 forNode(node).setType(m_graph, SpecString);
2703 forNode(node).makeHeapTop();
2706 case GetGlobalLexicalVariable:
2707 forNode(node).makeBytecodeTop();
2711 clobberWorld(node->origin.semantic, clobberLimit);
2712 forNode(node).makeBytecodeTop();
2716 clobberWorld(node->origin.semantic, clobberLimit);
2720 clobberWorld(node->origin.semantic, clobberLimit);
2721 forNode(node).setType(m_graph, SpecObject);
2724 case VarInjectionWatchpoint:
2725 case PutGlobalVariable:
2729 case OverridesHasInstance:
2730 forNode(node).setType(SpecBoolean);
2734 // Sadly, we don't propagate the fact that we've done InstanceOf
2735 forNode(node).setType(SpecBoolean);
2738 case InstanceOfCustom:
2739 clobberWorld(node->origin.semantic, clobberLimit);
2740 forNode(node).setType(SpecBoolean);
2744 RELEASE_ASSERT(m_graph.m_form == SSA);
2745 // The state of this node would have already been decided, but it may have become a
2746 // constant, in which case we'd like to know.
2747 if (forNode(node).m_value)
2748 m_state.setFoundConstants(true);
2752 m_state.createValueForNode(node->phi());
2753 forNode(node->phi()) = forNode(node->child1());
2762 case TailCallInlinedCaller:
2765 case CallForwardVarargs:
2766 case TailCallVarargsInlinedCaller:
2767 case ConstructVarargs:
2768 case ConstructForwardVarargs:
2769 case TailCallForwardVarargsInlinedCaller:
2770 clobberWorld(node->origin.semantic, clobberLimit);
2771 forNode(node).makeHeapTop();
2776 m_state.setIsValid(false);
2779 case InvalidationPoint:
2780 forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2781 m_state.setStructureClobberState(StructuresAreWatched);
2784 case CheckWatchdogTimer:
2785 case LogShadowChickenPrologue:
2786 case LogShadowChickenTail:
2789 case ProfileWillCall:
2790 case ProfileDidCall:
2792 case ProfileControlFlow:
2794 case CountExecution:
2795 case CheckTierUpInLoop:
2796 case CheckTierUpAtReturn:
2797 case CheckTypeInfoFlags:
2804 // Simplify out checks that don't actually do checking.
2805 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2806 Edge edge = node->children.child(i);
2809 if (edge.isProved() || edge.willNotHaveCheck()) {
2810 m_state.setFoundConstants(true);
2817 case SetFunctionName: {
2818 clobberWorld(node->origin.semantic, clobberLimit);
2822 case StoreBarrier: {
2823 filter(node->child1(), SpecCell);
2827 case CheckTierUpAndOSREnter:
2837 DFG_CRASH(m_graph, node, "Unexpected node type");
2841 return m_state.isValid();
2844 template<typename AbstractStateType>
2845 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
2847 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
2850 template<typename AbstractStateType>
2851 bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
2853 Node* node = m_state.block()->at(indexInBlock);
2857 return executeEffects(indexInBlock, node);
2860 template<typename AbstractStateType>
2861 bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2865 return executeEffects(UINT_MAX, node);
2868 template<typename AbstractStateType>
2869 void AbstractInterpreter<AbstractStateType>::clobberWorld(
2870 const CodeOrigin&, unsigned clobberLimit)
2872 clobberStructures(clobberLimit);
2875 template<typename AbstractStateType>
2876 template<typename Functor>
2877 void AbstractInterpreter<AbstractStateType>::forAllValues(
2878 unsigned clobberLimit, Functor& functor)
2880 if (clobberLimit >= m_state.block()->size())
2881 clobberLimit = m_state.block()->size();
2884 ASSERT(clobberLimit <= m_state.block()->size());
2885 for (size_t i = clobberLimit; i--;)
2886 functor(forNode(m_state.block()->at(i)));
2887 if (m_graph.m_form == SSA) {
2888 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2889 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2890 for (; iter != end; ++iter)
2891 functor(forNode(*iter));
2893 for (size_t i = m_state.variables().numberOfArguments(); i--;)
2894 functor(m_state.variables().argument(i));
2895 for (size_t i = m_state.variables().numberOfLocals(); i--;)
2896 functor(m_state.variables().local(i));
2899 template<typename AbstractStateType>
2900 void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
2902 forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
2906 template<typename AbstractStateType>
2907 void AbstractInterpreter<AbstractStateType>::observeTransition(
2908 unsigned clobberLimit, Structure* from, Structure* to)
2910 AbstractValue::TransitionObserver transitionObserver(from, to);
2911 forAllValues(clobberLimit, transitionObserver);
2913 ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
2916 template<typename AbstractStateType>
2917 void AbstractInterpreter<AbstractStateType>::observeTransitions(
2918 unsigned clobberLimit, const TransitionVector& vector)
2920 AbstractValue::TransitionsObserver transitionsObserver(vector);
2921 forAllValues(clobberLimit, transitionsObserver);
2923 if (!ASSERT_DISABLED) {
2924 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2925 for (unsigned i = vector.size(); i--;)
2926 ASSERT(!vector[i].previous->dfgShouldWatch());
2930 template<typename AbstractStateType>
2931 void AbstractInterpreter<AbstractStateType>::setDidClobber()
2933 m_state.setDidClobber(true);
2934 m_state.setStructureClobberState(StructuresAreClobbered);
2937 template<typename AbstractStateType>
2938 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
2940 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
2943 template<typename AbstractStateType>
2944 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
2946 CommaPrinter comma(" ");
2947 HashSet<Node*> seen;
2948 if (m_graph.m_form == SSA) {
2949 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2950 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2951 for (; iter != end; ++iter) {
2954 AbstractValue& value = forNode(node);
2955 if (value.isClear())
2957 out.print(comma, node, ":", value);
2960 for (size_t i = 0; i < m_state.block()->size(); ++i) {
2961 Node* node = m_state.block()->at(i);
2963 AbstractValue& value = forNode(node);
2964 if (value.isClear())
2966 out.print(comma, node, ":", value);
2968 if (m_graph.m_form == SSA) {
2969 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtTail.begin();
2970 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtTail.end();
2971 for (; iter != end; ++iter) {
2973 if (seen.contains(node))
2975 AbstractValue& value = forNode(node);
2976 if (value.isClear())
2978 out.print(comma, node, ":", value);
2983 template<typename AbstractStateType>
2984 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2985 AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
2987 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
2988 return FiltrationOK;
2989 m_state.setIsValid(false);
2990 return Contradiction;
2993 template<typename AbstractStateType>
2994 FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
2995 AbstractValue& value, ArrayModes arrayModes)
2997 if (value.filterArrayModes(arrayModes) == FiltrationOK)
2998 return FiltrationOK;
2999 m_state.setIsValid(false);
3000 return Contradiction;
3003 template<typename AbstractStateType>
3004 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3005 AbstractValue& value, SpeculatedType type)
3007 if (value.filter(type) == FiltrationOK)
3008 return FiltrationOK;
3009 m_state.setIsValid(false);
3010 return Contradiction;
3013 template<typename AbstractStateType>
3014 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
3015 AbstractValue& abstractValue, FrozenValue concreteValue)
3017 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
3018 return FiltrationOK;
3019 m_state.setIsValid(false);
3020 return Contradiction;
3023 } } // namespace JSC::DFG
3025 #endif // ENABLE(DFG_JIT)
3027 #endif // DFGAbstractInterpreterInlines_h