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>::executeKnownEdgeTypes(Node* node)
110 // Some use kinds are required to not have checks, because we know somehow that the incoming
111 // value will already have the type we want. In those cases, AI may not be smart enough to
112 // prove that this is indeed the case. But the existance of the edge is enough to prove that
113 // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
114 // and FTL backends may emit checks in a node that lacks a valid exit origin.
115 m_graph.doToChildren(
118 if (mayHaveTypeCheck(edge.useKind()))
121 filterEdgeByUse(edge);
125 template<typename AbstractStateType>
126 void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
128 if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
131 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());
134 template<typename AbstractStateType>
135 void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
137 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
140 inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
142 // We look at the type first since that will cover most cases and does not require iterating all the structures.
144 if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
147 if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
151 if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
152 bool overridesToThis = false;
153 valueForNode.m_structure.forEach([&](Structure* structure) {
154 TypeInfo type = structure->typeInfo();
155 ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
157 ASSERT(type.isObject());
158 // We don't need to worry about strings/symbols here since either:
159 // 1) We are in strict mode and strings/symbols are not wrapped
160 // 2) The AI has proven that the type of this is a subtype of object
161 if (type.isObject() && type.overridesToThis())
162 overridesToThis = true;
164 return !overridesToThis;
170 template<typename AbstractStateType>
171 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
173 if (!ASSERT_DISABLED)
176 m_state.createValueForNode(node);
178 switch (node->op()) {
181 case Int52Constant: {
182 setBuiltInConstant(node, *node->constant());
186 case LazyJSConstant: {
187 LazyJSValue value = node->lazyJSValue();
188 switch (value.kind()) {
189 case LazyJSValue::KnownValue:
190 setConstant(node, value.value()->value());
192 case LazyJSValue::SingleCharacterString:
193 case LazyJSValue::KnownStringImpl:
194 case LazyJSValue::NewStringImpl:
195 forNode(node).setType(m_graph, SpecString);
202 forNode(node) = forNode(node->child1());
203 if (forNode(node).value())
204 m_state.setFoundConstants(true);
208 case ExtractOSREntryLocal: {
209 forNode(node).makeBytecodeTop();
214 VariableAccessData* variableAccessData = node->variableAccessData();
215 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
216 // The value in the local should already be checked.
217 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
219 m_state.setFoundConstants(true);
220 forNode(node) = value;
225 StackAccessData* data = node->stackAccessData();
226 AbstractValue value = m_state.variables().operand(data->local);
227 // The value in the local should already be checked.
228 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
230 m_state.setFoundConstants(true);
231 forNode(node) = value;
235 case GetLocalUnlinked: {
236 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
238 m_state.setFoundConstants(true);
239 forNode(node) = value;
244 m_state.variables().operand(node->local()) = forNode(node->child1());
249 m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
254 // Don't need to do anything. A MovHint only informs us about what would have happened
255 // in bytecode, but this code is just concerned with what is actually happening during
261 // This is just a hint telling us that the OSR state of the local is no longer inside the
267 // Assert that the state of arguments has been set. SetArgument means that someone set
268 // the argument values out-of-band, and currently this always means setting to a
270 ASSERT(!m_state.variables().operand(node->local()).isClear());
274 case ForwardVarargs: {
275 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
276 // itself into a straight-line sequence of GetStack/PutStack.
277 // https://bugs.webkit.org/show_bug.cgi?id=143071
278 clobberWorld(node->origin.semantic, clobberLimit);
279 LoadVarargsData* data = node->loadVarargsData();
280 m_state.variables().operand(data->count).setType(SpecInt32Only);
281 for (unsigned i = data->limit - 1; i--;)
282 m_state.variables().operand(data->start.offset() + i).makeHeapTop();
292 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
293 clobberWorld(node->origin.semantic, clobberLimit);
294 forNode(node).setType(m_graph, SpecInt32Only);
298 JSValue left = forNode(node->child1()).value();
299 JSValue right = forNode(node->child2()).value();
300 if (left && right && left.isInt32() && right.isInt32()) {
301 int32_t a = left.asInt32();
302 int32_t b = right.asInt32();
303 switch (node->op()) {
305 setConstant(node, JSValue(a & b));
308 setConstant(node, JSValue(a | b));
311 setConstant(node, JSValue(a ^ b));
314 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
317 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
320 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
323 RELEASE_ASSERT_NOT_REACHED();
329 if (node->op() == BitAnd
330 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
331 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
332 forNode(node).setType(SpecBoolInt32);
336 forNode(node).setType(SpecInt32Only);
340 case UInt32ToNumber: {
341 JSValue child = forNode(node->child1()).value();
342 if (doesOverflow(node->arithMode())) {
344 if (child && child.isAnyInt()) {
345 int64_t machineInt = child.asAnyInt();
346 setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
349 forNode(node).setType(SpecAnyInt);
352 if (child && child.isInt32()) {
353 uint32_t value = child.asInt32();
354 setConstant(node, jsNumber(value));
357 forNode(node).setType(SpecAnyIntAsDouble);
360 if (child && child.isInt32()) {
361 int32_t value = child.asInt32();
363 setConstant(node, jsNumber(value));
367 forNode(node).setType(SpecInt32Only);
371 case BooleanToNumber: {
372 JSValue concreteValue = forNode(node->child1()).value();
374 if (concreteValue.isBoolean())
375 setConstant(node, jsNumber(concreteValue.asBoolean()));
377 setConstant(node, *m_graph.freeze(concreteValue));
380 AbstractValue& value = forNode(node);
381 value = forNode(node->child1());
382 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
383 m_state.setFoundConstants(true);
384 if (value.m_type & SpecBoolean) {
385 value.merge(SpecBoolInt32);
386 value.filter(~SpecBoolean);
391 case DoubleAsInt32: {
392 JSValue child = forNode(node->child1()).value();
393 if (child && child.isNumber()) {
394 double asDouble = child.asNumber();
395 int32_t asInt = JSC::toInt32(asDouble);
396 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
397 setConstant(node, JSValue(asInt));
401 forNode(node).setType(SpecInt32Only);
406 JSValue child = forNode(node->child1()).value();
408 if (child.isNumber()) {
410 setConstant(node, child);
412 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
415 if (child.isBoolean()) {
416 setConstant(node, jsNumber(child.asBoolean()));
419 if (child.isUndefinedOrNull()) {
420 setConstant(node, jsNumber(0));
425 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
426 forNode(node).setType(SpecBoolInt32);
430 forNode(node).setType(SpecInt32Only);
435 JSValue child = forNode(node->child1()).value();
436 if (Optional<double> number = child.toNumberFromPrimitive()) {
437 setConstant(node, jsDoubleNumber(*number));
441 SpeculatedType type = forNode(node->child1()).m_type;
442 switch (node->child1().useKind()) {
444 if (type & SpecOther) {
446 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
448 if (type & SpecBoolean) {
449 type &= ~SpecBoolean;
450 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
452 type &= SpecBytecodeNumber;
462 RELEASE_ASSERT_NOT_REACHED();
464 forNode(node).setType(type);
465 forNode(node).fixTypeForRepresentation(m_graph, node);
470 JSValue child = forNode(node->child1()).value();
471 if (child && child.isAnyInt()) {
472 setConstant(node, child);
476 forNode(node).setType(SpecInt32Only);
481 JSValue value = forNode(node->child1()).value();
483 setConstant(node, value);
487 forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
488 forNode(node).fixTypeForRepresentation(m_graph, node);
493 ASSERT(node->binaryUseKind() == UntypedUse);
494 clobberWorld(node->origin.semantic, clobberLimit);
495 forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
500 forNode(node).setType(m_graph, SpecString);
505 JSValue left = forNode(node->child1()).value();
506 JSValue right = forNode(node->child2()).value();
507 switch (node->binaryUseKind()) {
509 if (left && right && left.isInt32() && right.isInt32()) {
510 if (!shouldCheckOverflow(node->arithMode())) {
511 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
514 JSValue result = jsNumber(left.asNumber() + right.asNumber());
515 if (result.isInt32()) {
516 setConstant(node, result);
520 forNode(node).setType(SpecInt32Only);
523 if (left && right && left.isAnyInt() && right.isAnyInt()) {
524 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
525 if (result.isAnyInt()) {
526 setConstant(node, result);
530 forNode(node).setType(SpecAnyInt);
533 if (left && right && left.isNumber() && right.isNumber()) {
534 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
537 forNode(node).setType(
539 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
542 RELEASE_ASSERT_NOT_REACHED();
549 JSValue operand = forNode(node->child1()).value();
550 if (Optional<double> number = operand.toNumberFromPrimitive()) {
551 uint32_t value = toUInt32(*number);
552 setConstant(node, jsNumber(clz32(value)));
555 forNode(node).setType(SpecInt32Only);
560 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
565 JSValue left = forNode(node->child1()).value();
566 JSValue right = forNode(node->child2()).value();
567 switch (node->binaryUseKind()) {
569 if (left && right && left.isInt32() && right.isInt32()) {
570 if (!shouldCheckOverflow(node->arithMode())) {
571 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
574 JSValue result = jsNumber(left.asNumber() - right.asNumber());
575 if (result.isInt32()) {
576 setConstant(node, result);
580 forNode(node).setType(SpecInt32Only);
583 if (left && right && left.isAnyInt() && right.isAnyInt()) {
584 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
585 if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
586 setConstant(node, result);
590 forNode(node).setType(SpecAnyInt);
593 if (left && right && left.isNumber() && right.isNumber()) {
594 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
597 forNode(node).setType(
598 typeOfDoubleDifference(
599 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
602 clobberWorld(node->origin.semantic, clobberLimit);
603 forNode(node).setType(m_graph, SpecBytecodeNumber);
606 RELEASE_ASSERT_NOT_REACHED();
613 JSValue child = forNode(node->child1()).value();
614 switch (node->child1().useKind()) {
616 if (child && child.isInt32()) {
617 if (!shouldCheckOverflow(node->arithMode())) {
618 setConstant(node, jsNumber(-child.asInt32()));
622 if (shouldCheckNegativeZero(node->arithMode()))
623 doubleResult = -child.asNumber();
625 doubleResult = 0 - child.asNumber();
626 JSValue valueResult = jsNumber(doubleResult);
627 if (valueResult.isInt32()) {
628 setConstant(node, valueResult);
632 forNode(node).setType(SpecInt32Only);
635 if (child && child.isAnyInt()) {
637 if (shouldCheckNegativeZero(node->arithMode()))
638 doubleResult = -child.asNumber();
640 doubleResult = 0 - child.asNumber();
641 JSValue valueResult = jsNumber(doubleResult);
642 if (valueResult.isAnyInt()) {
643 setConstant(node, valueResult);
647 forNode(node).setType(SpecAnyInt);
650 if (child && child.isNumber()) {
651 setConstant(node, jsDoubleNumber(-child.asNumber()));
654 forNode(node).setType(
655 typeOfDoubleNegation(
656 forNode(node->child1()).m_type));
659 RELEASE_ASSERT_NOT_REACHED();
666 JSValue left = forNode(node->child1()).value();
667 JSValue right = forNode(node->child2()).value();
668 switch (node->binaryUseKind()) {
670 if (left && right && left.isInt32() && right.isInt32()) {
671 if (!shouldCheckOverflow(node->arithMode())) {
672 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
675 double doubleResult = left.asNumber() * right.asNumber();
676 if (!shouldCheckNegativeZero(node->arithMode()))
677 doubleResult += 0; // Sanitizes zero.
678 JSValue valueResult = jsNumber(doubleResult);
679 if (valueResult.isInt32()) {
680 setConstant(node, valueResult);
684 forNode(node).setType(SpecInt32Only);
687 if (left && right && left.isAnyInt() && right.isAnyInt()) {
688 double doubleResult = left.asNumber() * right.asNumber();
689 if (!shouldCheckNegativeZero(node->arithMode()))
691 JSValue valueResult = jsNumber(doubleResult);
692 if (valueResult.isAnyInt()) {
693 setConstant(node, valueResult);
697 forNode(node).setType(SpecAnyInt);
700 if (left && right && left.isNumber() && right.isNumber()) {
701 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
704 forNode(node).setType(
706 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
709 clobberWorld(node->origin.semantic, clobberLimit);
710 forNode(node).setType(m_graph, SpecBytecodeNumber);
713 RELEASE_ASSERT_NOT_REACHED();
720 JSValue left = forNode(node->child1()).value();
721 JSValue right = forNode(node->child2()).value();
722 switch (node->binaryUseKind()) {
724 if (left && right && left.isInt32() && right.isInt32()) {
725 double doubleResult = left.asNumber() / right.asNumber();
726 if (!shouldCheckOverflow(node->arithMode()))
727 doubleResult = toInt32(doubleResult);
728 else if (!shouldCheckNegativeZero(node->arithMode()))
729 doubleResult += 0; // Sanitizes zero.
730 JSValue valueResult = jsNumber(doubleResult);
731 if (valueResult.isInt32()) {
732 setConstant(node, valueResult);
736 forNode(node).setType(SpecInt32Only);
739 if (left && right && left.isNumber() && right.isNumber()) {
740 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
743 forNode(node).setType(
744 typeOfDoubleQuotient(
745 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
748 clobberWorld(node->origin.semantic, clobberLimit);
749 forNode(node).setType(m_graph, SpecBytecodeNumber);
752 RELEASE_ASSERT_NOT_REACHED();
759 JSValue left = forNode(node->child1()).value();
760 JSValue right = forNode(node->child2()).value();
761 switch (node->binaryUseKind()) {
763 if (left && right && left.isInt32() && right.isInt32()) {
764 double doubleResult = fmod(left.asNumber(), right.asNumber());
765 if (!shouldCheckOverflow(node->arithMode()))
766 doubleResult = toInt32(doubleResult);
767 else if (!shouldCheckNegativeZero(node->arithMode()))
768 doubleResult += 0; // Sanitizes zero.
769 JSValue valueResult = jsNumber(doubleResult);
770 if (valueResult.isInt32()) {
771 setConstant(node, valueResult);
775 forNode(node).setType(SpecInt32Only);
778 if (left && right && left.isNumber() && right.isNumber()) {
779 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
782 forNode(node).setType(
783 typeOfDoubleBinaryOp(
784 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
787 RELEASE_ASSERT_NOT_REACHED();
794 JSValue left = forNode(node->child1()).value();
795 JSValue right = forNode(node->child2()).value();
796 switch (node->binaryUseKind()) {
798 if (left && right && left.isInt32() && right.isInt32()) {
799 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
802 forNode(node).setType(SpecInt32Only);
805 if (left && right && left.isNumber() && right.isNumber()) {
806 double a = left.asNumber();
807 double b = right.asNumber();
808 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
811 forNode(node).setType(
813 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
816 RELEASE_ASSERT_NOT_REACHED();
823 JSValue left = forNode(node->child1()).value();
824 JSValue right = forNode(node->child2()).value();
825 switch (node->binaryUseKind()) {
827 if (left && right && left.isInt32() && right.isInt32()) {
828 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
831 forNode(node).setType(SpecInt32Only);
834 if (left && right && left.isNumber() && right.isNumber()) {
835 double a = left.asNumber();
836 double b = right.asNumber();
837 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
840 forNode(node).setType(
842 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
845 RELEASE_ASSERT_NOT_REACHED();
852 JSValue child = forNode(node->child1()).value();
853 switch (node->child1().useKind()) {
855 if (Optional<double> number = child.toNumberFromPrimitive()) {
856 JSValue result = jsNumber(fabs(*number));
857 if (result.isInt32()) {
858 setConstant(node, result);
862 forNode(node).setType(SpecInt32Only);
865 if (Optional<double> number = child.toNumberFromPrimitive()) {
866 setConstant(node, jsDoubleNumber(fabs(*number)));
869 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
872 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
873 forNode(node).setType(SpecFullNumber);
880 JSValue childY = forNode(node->child2()).value();
881 if (childY && childY.isNumber()) {
882 if (!childY.asNumber()) {
883 setConstant(node, jsDoubleNumber(1));
887 JSValue childX = forNode(node->child1()).value();
888 if (childX && childX.isNumber()) {
889 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
893 forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
898 forNode(node).setType(m_graph, SpecDoubleReal);
906 JSValue operand = forNode(node->child1()).value();
907 if (operand && operand.isNumber()) {
908 double roundedValue = 0;
909 if (node->op() == ArithRound)
910 roundedValue = jsRound(operand.asNumber());
911 else if (node->op() == ArithFloor)
912 roundedValue = floor(operand.asNumber());
913 else if (node->op() == ArithCeil)
914 roundedValue = ceil(operand.asNumber());
916 ASSERT(node->op() == ArithTrunc);
917 roundedValue = trunc(operand.asNumber());
920 if (producesInteger(node->arithRoundingMode())) {
921 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
922 if (roundedValueAsInt32 == roundedValue) {
923 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
924 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
925 setConstant(node, jsNumber(roundedValueAsInt32));
929 setConstant(node, jsNumber(roundedValueAsInt32));
934 setConstant(node, jsDoubleNumber(roundedValue));
938 if (producesInteger(node->arithRoundingMode()))
939 forNode(node).setType(SpecInt32Only);
941 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
946 executeDoubleUnaryOpEffects(node, sqrt);
950 executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
954 executeDoubleUnaryOpEffects(node, sin);
958 executeDoubleUnaryOpEffects(node, cos);
962 executeDoubleUnaryOpEffects(node, log);
966 switch (booleanResult(node, forNode(node->child1()))) {
968 setConstant(node, jsBoolean(false));
970 case DefinitelyFalse:
971 setConstant(node, jsBoolean(true));
974 forNode(node).setType(SpecBoolean);
990 case IsTypedArrayView: {
991 AbstractValue child = forNode(node->child1());
993 bool constantWasSet = true;
994 switch (node->op()) {
996 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
999 setConstant(node, jsBoolean(
1000 child.value().isCell()
1001 ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1002 : child.value().isUndefined()));
1005 setConstant(node, jsBoolean(child.value().isBoolean()));
1008 setConstant(node, jsBoolean(child.value().isNumber()));
1011 setConstant(node, jsBoolean(isJSString(child.value())));
1014 setConstant(node, jsBoolean(child.value().isObject()));
1016 case IsObjectOrNull:
1017 if (child.value().isObject()) {
1018 JSObject* object = asObject(child.value());
1019 if (object->type() == JSFunctionType)
1020 setConstant(node, jsBoolean(false));
1021 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1022 setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1024 // FIXME: This could just call getCallData.
1025 // https://bugs.webkit.org/show_bug.cgi?id=144457
1026 constantWasSet = false;
1029 setConstant(node, jsBoolean(child.value().isNull()));
1032 if (child.value().isObject()) {
1033 JSObject* object = asObject(child.value());
1034 if (object->type() == JSFunctionType)
1035 setConstant(node, jsBoolean(true));
1036 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
1037 setConstant(node, jsBoolean(false));
1039 // FIXME: This could just call getCallData.
1040 // https://bugs.webkit.org/show_bug.cgi?id=144457
1041 constantWasSet = false;
1044 setConstant(node, jsBoolean(false));
1046 case IsRegExpObject:
1047 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
1050 setConstant(node, jsBoolean(child.value().isEmpty()));
1052 case IsTypedArrayView:
1053 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo()->typedArrayStorageType)));
1056 constantWasSet = false;
1063 // FIXME: This code should really use AbstractValue::isType() and
1064 // AbstractValue::couldBeType().
1065 // https://bugs.webkit.org/show_bug.cgi?id=146870
1067 bool constantWasSet = false;
1068 switch (node->op()) {
1070 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1071 if (!(child.m_type & ~SpecArray)) {
1072 setConstant(node, jsBoolean(true));
1073 constantWasSet = true;
1077 if (!(child.m_type & SpecObject)) {
1078 setConstant(node, jsBoolean(false));
1079 constantWasSet = true;
1085 if (child.m_type && !(child.m_type & SpecEmpty)) {
1086 setConstant(node, jsBoolean(false));
1087 constantWasSet = true;
1091 if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1092 setConstant(node, jsBoolean(true));
1093 constantWasSet = true;
1100 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1101 // https://bugs.webkit.org/show_bug.cgi?id=144456
1103 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1104 setConstant(node, jsBoolean(false));
1105 constantWasSet = true;
1111 if (!(child.m_type & ~SpecBoolean)) {
1112 setConstant(node, jsBoolean(true));
1113 constantWasSet = true;
1117 if (!(child.m_type & SpecBoolean)) {
1118 setConstant(node, jsBoolean(false));
1119 constantWasSet = true;
1125 if (!(child.m_type & ~SpecFullNumber)) {
1126 setConstant(node, jsBoolean(true));
1127 constantWasSet = true;
1131 if (!(child.m_type & SpecFullNumber)) {
1132 setConstant(node, jsBoolean(false));
1133 constantWasSet = true;
1139 if (!(child.m_type & ~SpecString)) {
1140 setConstant(node, jsBoolean(true));
1141 constantWasSet = true;
1145 if (!(child.m_type & SpecString)) {
1146 setConstant(node, jsBoolean(false));
1147 constantWasSet = true;
1153 if (!(child.m_type & ~SpecObject)) {
1154 setConstant(node, jsBoolean(true));
1155 constantWasSet = true;
1159 if (!(child.m_type & SpecObject)) {
1160 setConstant(node, jsBoolean(false));
1161 constantWasSet = true;
1166 case IsObjectOrNull:
1167 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1168 // https://bugs.webkit.org/show_bug.cgi?id=144456
1170 // These expressions are complicated to parse. A helpful way to parse this is that
1171 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1172 // disjoint set from S". Things like "T - S" means that, provided that S is a
1173 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1174 // mean the "union of T and S".
1176 // Is the child's type an object that isn't an other-object (i.e. object that could
1177 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1179 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1180 setConstant(node, jsBoolean(true));
1181 constantWasSet = true;
1185 // Is the child's type definitely not either of: an object that isn't a function,
1186 // or either undefined or null? Then: we should fold this to false. This means
1187 // for example that if it's any non-function object, including those that have
1188 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1189 // if it's undefined-or-null, since the type bits don't distinguish between
1190 // undefined (which should fold to false) and null (which should fold to true).
1191 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1192 setConstant(node, jsBoolean(false));
1193 constantWasSet = true;
1199 if (!(child.m_type & ~SpecFunction)) {
1200 setConstant(node, jsBoolean(true));
1201 constantWasSet = true;
1205 if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
1206 setConstant(node, jsBoolean(false));
1207 constantWasSet = true;
1212 case IsRegExpObject:
1213 // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
1214 if (!(child.m_type & ~SpecRegExpObject)) {
1215 setConstant(node, jsBoolean(true));
1216 constantWasSet = true;
1219 if (!(child.m_type & SpecObject)) {
1220 setConstant(node, jsBoolean(false));
1221 constantWasSet = true;
1226 case IsTypedArrayView:
1227 if (!(child.m_type & ~SpecTypedArrayView)) {
1228 setConstant(node, jsBoolean(true));
1229 constantWasSet = true;
1232 if (!(child.m_type & SpecTypedArrayView)) {
1233 setConstant(node, jsBoolean(false));
1234 constantWasSet = true;
1245 forNode(node).setType(SpecBoolean);
1250 VM* vm = m_codeBlock->vm();
1251 JSValue child = forNode(node->child1()).value();
1252 AbstractValue& abstractChild = forNode(node->child1());
1254 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1255 setConstant(node, *m_graph.freeze(typeString));
1259 if (isFullNumberSpeculation(abstractChild.m_type)) {
1260 setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
1264 if (isStringSpeculation(abstractChild.m_type)) {
1265 setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
1269 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1270 // https://bugs.webkit.org/show_bug.cgi?id=144456
1271 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1272 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
1276 if (isFunctionSpeculation(abstractChild.m_type)) {
1277 setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
1281 if (isBooleanSpeculation(abstractChild.m_type)) {
1282 setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
1286 if (isSymbolSpeculation(abstractChild.m_type)) {
1287 setConstant(node, *m_graph.freeze(vm->smallStrings.symbolString()));
1291 forNode(node).setType(m_graph, SpecStringIdent);
1297 case CompareGreater:
1298 case CompareGreaterEq:
1300 JSValue leftConst = forNode(node->child1()).value();
1301 JSValue rightConst = forNode(node->child2()).value();
1302 if (leftConst && rightConst) {
1303 if (leftConst.isNumber() && rightConst.isNumber()) {
1304 double a = leftConst.asNumber();
1305 double b = rightConst.asNumber();
1306 switch (node->op()) {
1308 setConstant(node, jsBoolean(a < b));
1311 setConstant(node, jsBoolean(a <= b));
1313 case CompareGreater:
1314 setConstant(node, jsBoolean(a > b));
1316 case CompareGreaterEq:
1317 setConstant(node, jsBoolean(a >= b));
1320 setConstant(node, jsBoolean(a == b));
1323 RELEASE_ASSERT_NOT_REACHED();
1329 if (leftConst.isString() && rightConst.isString()) {
1330 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1331 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1334 if (node->op() == CompareEq)
1335 result = WTF::equal(a, b);
1336 else if (node->op() == CompareLess)
1337 result = codePointCompare(a, b) < 0;
1338 else if (node->op() == CompareLessEq)
1339 result = codePointCompare(a, b) <= 0;
1340 else if (node->op() == CompareGreater)
1341 result = codePointCompare(a, b) > 0;
1342 else if (node->op() == CompareGreaterEq)
1343 result = codePointCompare(a, b) >= 0;
1345 RELEASE_ASSERT_NOT_REACHED();
1346 setConstant(node, jsBoolean(result));
1351 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1352 setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
1357 if (node->op() == CompareEq) {
1358 SpeculatedType leftType = forNode(node->child1()).m_type;
1359 SpeculatedType rightType = forNode(node->child2()).m_type;
1360 if (!valuesCouldBeEqual(leftType, rightType)) {
1361 setConstant(node, jsBoolean(false));
1365 if (leftType == SpecOther)
1366 std::swap(leftType, rightType);
1367 if (rightType == SpecOther) {
1368 // Undefined and Null are always equal when compared to eachother.
1369 if (!(leftType & ~SpecOther)) {
1370 setConstant(node, jsBoolean(true));
1374 // Any other type compared to Null or Undefined is always false
1375 // as long as the MasqueradesAsUndefined watchpoint is valid.
1377 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1378 // cases are always "false".
1379 if (!(leftType & (SpecObjectOther | SpecOther))) {
1380 setConstant(node, jsBoolean(false));
1384 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1385 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1386 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1387 setConstant(node, jsBoolean(false));
1393 if (node->child1() == node->child2()) {
1394 if (node->isBinaryUseKind(Int32Use) ||
1395 node->isBinaryUseKind(Int52RepUse) ||
1396 node->isBinaryUseKind(StringUse) ||
1397 node->isBinaryUseKind(BooleanUse) ||
1398 node->isBinaryUseKind(SymbolUse) ||
1399 node->isBinaryUseKind(StringIdentUse) ||
1400 node->isBinaryUseKind(ObjectUse) ||
1401 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1402 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1403 switch (node->op()) {
1405 case CompareGreater:
1406 setConstant(node, jsBoolean(false));
1409 case CompareGreaterEq:
1411 setConstant(node, jsBoolean(true));
1414 DFG_CRASH(m_graph, node, "Unexpected node type");
1421 forNode(node).setType(SpecBoolean);
1425 case CompareStrictEq: {
1426 Node* leftNode = node->child1().node();
1427 Node* rightNode = node->child2().node();
1428 JSValue left = forNode(leftNode).value();
1429 JSValue right = forNode(rightNode).value();
1430 if (left && right) {
1431 if (left.isString() && right.isString()) {
1432 // We need this case because JSValue::strictEqual is otherwise too racy for
1433 // string comparisons.
1434 const StringImpl* a = asString(left)->tryGetValueImpl();
1435 const StringImpl* b = asString(right)->tryGetValueImpl();
1437 setConstant(node, jsBoolean(WTF::equal(a, b)));
1441 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1446 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1447 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1448 if (!(leftLUB & rightLUB)) {
1449 setConstant(node, jsBoolean(false));
1453 if (node->child1() == node->child2()) {
1454 if (node->isBinaryUseKind(BooleanUse) ||
1455 node->isBinaryUseKind(Int32Use) ||
1456 node->isBinaryUseKind(Int52RepUse) ||
1457 node->isBinaryUseKind(StringUse) ||
1458 node->isBinaryUseKind(StringIdentUse) ||
1459 node->isBinaryUseKind(SymbolUse) ||
1460 node->isBinaryUseKind(ObjectUse) ||
1461 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1462 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1463 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1464 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1465 node->isBinaryUseKind(StringUse, UntypedUse) ||
1466 node->isBinaryUseKind(UntypedUse, StringUse)) {
1467 setConstant(node, jsBoolean(true));
1472 forNode(node).setType(SpecBoolean);
1476 case CompareEqPtr: {
1477 Node* childNode = node->child1().node();
1478 JSValue childValue = forNode(childNode).value();
1480 setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
1484 forNode(node).setType(SpecBoolean);
1488 case StringCharCodeAt:
1489 forNode(node).setType(SpecInt32Only);
1492 case StringFromCharCode:
1493 forNode(node).setType(m_graph, SpecString);
1497 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1501 switch (node->arrayMode().type()) {
1502 case Array::SelectUsingPredictions:
1503 case Array::Unprofiled:
1504 case Array::SelectUsingArguments:
1505 RELEASE_ASSERT_NOT_REACHED();
1507 case Array::ForceExit:
1508 m_state.setIsValid(false);
1510 case Array::Undecided: {
1511 JSValue index = forNode(node->child2()).value();
1512 if (index && index.isInt32() && index.asInt32() >= 0) {
1513 setConstant(node, jsUndefined());
1516 forNode(node).setType(SpecOther);
1519 case Array::Generic:
1520 clobberWorld(node->origin.semantic, clobberLimit);
1521 forNode(node).makeHeapTop();
1524 if (node->arrayMode().isOutOfBounds()) {
1525 // If the watchpoint was still valid we could totally set this to be
1526 // SpecString | SpecOther. Except that we'd have to be careful. If we
1527 // tested the watchpoint state here then it could change by the time
1528 // we got to the backend. So to do this right, we'd have to get the
1529 // fixup phase to check the watchpoint state and then bake into the
1530 // GetByVal operation the fact that we're using a watchpoint, using
1531 // something like Array::SaneChain (except not quite, because that
1532 // implies an in-bounds access). None of this feels like it's worth it,
1533 // so we're going with TOP for now. The same thing applies to
1534 // clobbering the world.
1535 clobberWorld(node->origin.semantic, clobberLimit);
1536 forNode(node).makeHeapTop();
1538 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1540 case Array::DirectArguments:
1541 case Array::ScopedArguments:
1542 forNode(node).makeHeapTop();
1545 if (node->arrayMode().isOutOfBounds()) {
1546 clobberWorld(node->origin.semantic, clobberLimit);
1547 forNode(node).makeHeapTop();
1549 forNode(node).setType(SpecInt32Only);
1552 if (node->arrayMode().isOutOfBounds()) {
1553 clobberWorld(node->origin.semantic, clobberLimit);
1554 forNode(node).makeHeapTop();
1555 } else if (node->arrayMode().isSaneChain())
1556 forNode(node).setType(SpecBytecodeDouble);
1558 forNode(node).setType(SpecDoubleReal);
1560 case Array::Contiguous:
1561 case Array::ArrayStorage:
1562 case Array::SlowPutArrayStorage:
1563 if (node->arrayMode().isOutOfBounds())
1564 clobberWorld(node->origin.semantic, clobberLimit);
1565 forNode(node).makeHeapTop();
1567 case Array::Int8Array:
1568 forNode(node).setType(SpecInt32Only);
1570 case Array::Int16Array:
1571 forNode(node).setType(SpecInt32Only);
1573 case Array::Int32Array:
1574 forNode(node).setType(SpecInt32Only);
1576 case Array::Uint8Array:
1577 forNode(node).setType(SpecInt32Only);
1579 case Array::Uint8ClampedArray:
1580 forNode(node).setType(SpecInt32Only);
1582 case Array::Uint16Array:
1583 forNode(node).setType(SpecInt32Only);
1585 case Array::Uint32Array:
1586 if (node->shouldSpeculateInt32())
1587 forNode(node).setType(SpecInt32Only);
1588 else if (enableInt52() && node->shouldSpeculateAnyInt())
1589 forNode(node).setType(SpecAnyInt);
1591 forNode(node).setType(SpecAnyIntAsDouble);
1593 case Array::Float32Array:
1594 forNode(node).setType(SpecFullDouble);
1596 case Array::Float64Array:
1597 forNode(node).setType(SpecFullDouble);
1600 RELEASE_ASSERT_NOT_REACHED();
1606 case PutByValDirect:
1608 case PutByValAlias: {
1609 switch (node->arrayMode().modeForPut().type()) {
1610 case Array::ForceExit:
1611 m_state.setIsValid(false);
1613 case Array::Generic:
1614 clobberWorld(node->origin.semantic, clobberLimit);
1617 if (node->arrayMode().isOutOfBounds())
1618 clobberWorld(node->origin.semantic, clobberLimit);
1621 if (node->arrayMode().isOutOfBounds())
1622 clobberWorld(node->origin.semantic, clobberLimit);
1624 case Array::Contiguous:
1625 case Array::ArrayStorage:
1626 if (node->arrayMode().isOutOfBounds())
1627 clobberWorld(node->origin.semantic, clobberLimit);
1629 case Array::SlowPutArrayStorage:
1630 if (node->arrayMode().mayStoreToHole())
1631 clobberWorld(node->origin.semantic, clobberLimit);
1640 clobberWorld(node->origin.semantic, clobberLimit);
1641 forNode(node).setType(SpecBytecodeNumber);
1645 clobberWorld(node->origin.semantic, clobberLimit);
1646 forNode(node).makeHeapTop();
1649 case GetMyArgumentByVal:
1650 case GetMyArgumentByValOutOfBounds: {
1651 JSValue index = forNode(node->child2()).m_value;
1652 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1654 if (index && index.isInt32()) {
1655 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1656 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1657 // paths as unreachable, or to return undefined. We could implement that eventually.
1659 if (inlineCallFrame) {
1660 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
1661 forNode(node) = m_state.variables().operand(
1662 virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
1663 m_state.setFoundConstants(true);
1667 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
1668 forNode(node) = m_state.variables().argument(index.asInt32() + 1);
1669 m_state.setFoundConstants(true);
1675 if (inlineCallFrame) {
1676 // We have a bound on the types even though it's random access. Take advantage of this.
1678 AbstractValue result;
1679 for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
1681 m_state.variables().operand(
1682 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1685 if (node->op() == GetMyArgumentByValOutOfBounds)
1686 result.merge(SpecOther);
1689 m_state.setFoundConstants(true);
1691 forNode(node) = result;
1695 forNode(node).makeHeapTop();
1700 if (node->child2().useKind() == RegExpObjectUse
1701 && node->child3().useKind() == StringUse) {
1702 // This doesn't clobber the world since there are no conversions to perform.
1704 clobberWorld(node->origin.semantic, clobberLimit);
1705 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
1706 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(globalObjectValue)) {
1707 if (!globalObject->isHavingABadTime()) {
1708 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
1709 Structure* structure = globalObject->regExpMatchesArrayStructure();
1710 m_graph.registerStructure(structure);
1711 forNode(node).set(m_graph, structure);
1712 forNode(node).merge(SpecOther);
1717 forNode(node).setType(m_graph, SpecOther | SpecArray);
1721 if (node->child2().useKind() == RegExpObjectUse
1722 && node->child3().useKind() == StringUse) {
1723 // This doesn't clobber the world since there are no conversions to perform.
1725 clobberWorld(node->origin.semantic, clobberLimit);
1726 forNode(node).setType(SpecBoolean);
1730 case StringReplaceRegExp:
1731 if (node->child1().useKind() == StringUse
1732 && node->child2().useKind() == RegExpObjectUse
1733 && node->child3().useKind() == StringUse) {
1734 // This doesn't clobber the world. It just reads and writes regexp state.
1736 clobberWorld(node->origin.semantic, clobberLimit);
1737 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1744 Node* child = node->child1().node();
1745 BooleanResult result = booleanResult(node, forNode(child));
1746 if (result == DefinitelyTrue) {
1747 m_state.setBranchDirection(TakeTrue);
1750 if (result == DefinitelyFalse) {
1751 m_state.setBranchDirection(TakeFalse);
1754 // FIXME: The above handles the trivial cases of sparse conditional
1755 // constant propagation, but we can do better:
1756 // We can specialize the source variable's value on each direction of
1758 m_state.setBranchDirection(TakeBoth);
1763 // Nothing to do for now.
1764 // FIXME: Do sparse conditional things.
1769 m_state.setIsValid(false);
1773 case TailCallVarargs:
1774 case TailCallForwardVarargs:
1775 clobberWorld(node->origin.semantic, clobberLimit);
1776 m_state.setIsValid(false);
1780 case ThrowReferenceError:
1781 m_state.setIsValid(false);
1785 JSValue childConst = forNode(node->child1()).value();
1786 if (childConst && childConst.isNumber()) {
1787 setConstant(node, childConst);
1791 ASSERT(node->child1().useKind() == UntypedUse);
1793 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
1794 m_state.setFoundConstants(true);
1795 forNode(node) = forNode(node->child1());
1799 clobberWorld(node->origin.semantic, clobberLimit);
1801 forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
1806 JSValue childConst = forNode(node->child1()).value();
1807 if (childConst && childConst.isNumber()) {
1808 setConstant(node, childConst);
1812 ASSERT(node->child1().useKind() == UntypedUse);
1814 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
1815 m_state.setFoundConstants(true);
1816 forNode(node) = forNode(node->child1());
1820 clobberWorld(node->origin.semantic, clobberLimit);
1821 forNode(node).setType(m_graph, SpecBytecodeNumber);
1826 case CallStringConstructor: {
1827 switch (node->child1().useKind()) {
1828 case StringObjectUse:
1829 // This also filters that the StringObject has the primordial StringObject
1833 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
1835 case StringOrStringObjectUse:
1839 clobberWorld(node->origin.semantic, clobberLimit);
1842 RELEASE_ASSERT_NOT_REACHED();
1845 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1849 case NewStringObject: {
1850 ASSERT(node->structure()->classInfo() == StringObject::info());
1851 forNode(node).set(m_graph, node->structure());
1858 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1861 case NewArrayBuffer:
1864 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1867 case NewArrayWithSize:
1868 forNode(node).setType(m_graph, SpecArray);
1872 switch (node->child1().useKind()) {
1876 clobberWorld(node->origin.semantic, clobberLimit);
1879 RELEASE_ASSERT_NOT_REACHED();
1884 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
1885 node->typedArrayType()));
1889 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
1893 AbstractValue& source = forNode(node->child1());
1894 AbstractValue& destination = forNode(node);
1895 bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
1897 if (isToThisAnIdentity(strictMode, source)) {
1898 m_state.setFoundConstants(true);
1899 destination = source;
1904 destination.makeHeapTop();
1906 destination = source;
1907 destination.merge(SpecObject);
1913 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
1914 forNode(node).setType(m_graph, SpecFinalObject);
1919 ASSERT(node->structure());
1920 forNode(node).set(m_graph, node->structure());
1923 case CallObjectConstructor: {
1924 AbstractValue& source = forNode(node->child1());
1925 AbstractValue& destination = forNode(node);
1927 if (!(source.m_type & ~SpecObject)) {
1928 m_state.setFoundConstants(true);
1929 destination = source;
1933 forNode(node).setType(m_graph, SpecObject);
1937 case PhantomNewObject:
1938 case PhantomNewFunction:
1939 case PhantomNewGeneratorFunction:
1940 case PhantomCreateActivation:
1941 case PhantomDirectArguments:
1942 case PhantomClonedArguments:
1944 m_state.setDidClobber(true); // Prevent constant folding.
1945 // This claims to return bottom.
1951 case MaterializeNewObject: {
1954 m_phiChildren->forAllTransitiveIncomingValues(
1955 m_graph.varArgChild(node, 0).node(),
1956 [&] (Node* incoming) {
1957 set.add(incoming->castConstant<Structure*>());
1960 forNode(node).set(m_graph, set);
1964 case CreateActivation:
1965 case MaterializeCreateActivation:
1967 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
1970 case CreateDirectArguments:
1971 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
1974 case CreateScopedArguments:
1975 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
1978 case CreateClonedArguments:
1979 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
1982 case NewGeneratorFunction:
1984 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
1989 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
1993 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
1994 InferredValue* singleton = executable->singletonFunction();
1995 if (JSValue value = singleton->inferredValue()) {
1996 m_graph.watchpoints().addLazily(singleton);
1997 JSFunction* function = jsCast<JSFunction*>(value);
1998 setConstant(node, *m_graph.freeze(function));
2002 forNode(node).setType(m_graph, SpecFunction);
2005 case GetArgumentCountIncludingThis:
2006 forNode(node).setType(SpecInt32Only);
2010 forNode(node).setType(SpecInt32Only);
2014 JSValue base = forNode(node->child1()).m_value;
2016 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2017 if (!getterSetter->isGetterNull()) {
2018 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
2023 forNode(node).setType(m_graph, SpecObject);
2028 JSValue base = forNode(node->child1()).m_value;
2030 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2031 if (!getterSetter->isSetterNull()) {
2032 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
2037 forNode(node).setType(m_graph, SpecObject);
2042 if (JSValue base = forNode(node->child1()).m_value) {
2043 if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
2044 setConstant(node, *m_graph.freeze(function->scope()));
2048 forNode(node).setType(m_graph, SpecObjectOther);
2052 JSValue child = forNode(node->child1()).value();
2054 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
2057 forNode(node).setType(m_graph, SpecObjectOther);
2061 case GetGlobalObject: {
2062 JSValue child = forNode(node->child1()).value();
2064 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
2068 if (forNode(node->child1()).m_structure.isFinite()) {
2069 JSGlobalObject* globalObject = nullptr;
2071 forNode(node->child1()).m_structure.forEach(
2072 [&] (Structure* structure) {
2074 globalObject = structure->globalObject();
2075 else if (globalObject != structure->globalObject())
2078 if (globalObject && ok) {
2079 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2084 forNode(node).setType(m_graph, SpecObjectOther);
2089 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
2090 setConstant(node, *m_graph.freeze(value));
2093 forNode(node).makeBytecodeTop();
2099 case GetRegExpObjectLastIndex:
2100 forNode(node).makeHeapTop();
2103 case SetRegExpObjectLastIndex:
2104 case RecordRegExpCachedResult:
2107 case GetFromArguments:
2108 forNode(node).makeHeapTop();
2111 case PutToArguments:
2115 // FIXME: This should constant fold at least as well as the normal GetById case.
2116 // https://bugs.webkit.org/show_bug.cgi?id=156422
2117 forNode(node).makeHeapTop();
2121 case GetByIdFlush: {
2122 if (!node->prediction()) {
2123 m_state.setIsValid(false);
2127 AbstractValue& value = forNode(node->child1());
2128 if (value.m_structure.isFinite()
2129 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
2130 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2131 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
2132 if (status.isSimple()) {
2133 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2134 // something more subtle?
2135 AbstractValue result;
2136 for (unsigned i = status.numVariants(); i--;) {
2137 // This thing won't give us a variant that involves prototypes. If it did, we'd
2138 // have more work to do here.
2139 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
2142 m_graph.inferredValueForProperty(
2143 value, uid, status[i].offset(), m_state.structureClobberState()));
2145 m_state.setFoundConstants(true);
2146 forNode(node) = result;
2151 clobberWorld(node->origin.semantic, clobberLimit);
2152 forNode(node).makeHeapTop();
2156 case GetByValWithThis:
2157 case GetByIdWithThis:
2158 clobberWorld(node->origin.semantic, clobberLimit);
2159 forNode(node).makeHeapTop();
2162 case GetArrayLength: {
2163 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2164 forNode(node->child1()).m_value, node->arrayMode());
2166 setConstant(node, jsNumber(view->length()));
2169 forNode(node).setType(SpecInt32Only);
2175 // FIXME: This could decide if the delete will be successful based on the set of structures that
2176 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2177 clobberWorld(node->origin.semantic, clobberLimit);
2178 forNode(node).setType(SpecBoolean);
2182 case CheckStructure: {
2183 AbstractValue& value = forNode(node->child1());
2185 StructureSet& set = node->structureSet();
2187 // It's interesting that we could have proven that the object has a larger structure set
2188 // that includes the set we're testing. In that case we could make the structure check
2189 // more efficient. We currently don't.
2191 if (value.m_structure.isSubsetOf(set))
2192 m_state.setFoundConstants(true);
2194 SpeculatedType admittedTypes = SpecNone;
2195 switch (node->child1().useKind()) {
2198 admittedTypes = SpecNone;
2200 case CellOrOtherUse:
2201 admittedTypes = SpecOther;
2204 DFG_CRASH(m_graph, node, "Bad use kind");
2208 filter(value, set, admittedTypes);
2212 case CheckStructureImmediate: {
2213 // FIXME: This currently can only reason about one structure at a time.
2214 // https://bugs.webkit.org/show_bug.cgi?id=136988
2216 AbstractValue& value = forNode(node->child1());
2217 StructureSet& set = node->structureSet();
2219 if (value.value()) {
2220 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
2221 if (set.contains(structure)) {
2222 m_state.setFoundConstants(true);
2226 m_state.setIsValid(false);
2230 if (m_phiChildren) {
2231 bool allGood = true;
2232 m_phiChildren->forAllTransitiveIncomingValues(
2234 [&] (Node* incoming) {
2235 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
2236 if (set.contains(structure))
2242 m_state.setFoundConstants(true);
2247 if (Structure* structure = set.onlyStructure()) {
2248 filterByValue(node->child1(), *m_graph.freeze(structure));
2252 // Aw shucks, we can't do anything!
2257 if (!forNode(node->child1()).m_structure.isClear()) {
2258 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
2259 m_state.setFoundConstants(true);
2262 clobberLimit, node->transition()->previous, node->transition()->next);
2263 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
2268 case AllocatePropertyStorage:
2269 case ReallocatePropertyStorage:
2270 forNode(node).clear(); // The result is not a JS value.
2273 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2274 m_state.setFoundConstants(true);
2277 switch (node->arrayMode().type()) {
2279 filter(node->child1(), SpecString);
2283 case Array::Contiguous:
2284 case Array::Undecided:
2285 case Array::ArrayStorage:
2286 case Array::SlowPutArrayStorage:
2288 case Array::DirectArguments:
2289 filter(node->child1(), SpecDirectArguments);
2291 case Array::ScopedArguments:
2292 filter(node->child1(), SpecScopedArguments);
2294 case Array::Int8Array:
2295 filter(node->child1(), SpecInt8Array);
2297 case Array::Int16Array:
2298 filter(node->child1(), SpecInt16Array);
2300 case Array::Int32Array:
2301 filter(node->child1(), SpecInt32Array);
2303 case Array::Uint8Array:
2304 filter(node->child1(), SpecUint8Array);
2306 case Array::Uint8ClampedArray:
2307 filter(node->child1(), SpecUint8ClampedArray);
2309 case Array::Uint16Array:
2310 filter(node->child1(), SpecUint16Array);
2312 case Array::Uint32Array:
2313 filter(node->child1(), SpecUint32Array);
2315 case Array::Float32Array:
2316 filter(node->child1(), SpecFloat32Array);
2318 case Array::Float64Array:
2319 filter(node->child1(), SpecFloat64Array);
2321 case Array::AnyTypedArray:
2322 filter(node->child1(), SpecTypedArrayView);
2325 RELEASE_ASSERT_NOT_REACHED();
2328 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2332 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
2333 m_state.setFoundConstants(true);
2336 ASSERT(node->arrayMode().conversion() == Array::Convert);
2337 clobberStructures(clobberLimit);
2338 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
2341 case ArrayifyToStructure: {
2342 AbstractValue& value = forNode(node->child1());
2343 if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
2344 m_state.setFoundConstants(true);
2345 clobberStructures(clobberLimit);
2347 // We have a bunch of options of how to express the abstract set at this point. Let set S
2348 // be the set of structures that the value had before clobbering and assume that all of
2349 // them are watchable. The new value should be the least expressible upper bound of the
2350 // intersection of "values that currently have structure = node->structure()" and "values
2351 // that have structure in S plus any structure transition-reachable from S". Assume that
2352 // node->structure() is not in S but it is transition-reachable from S. Then we would
2353 // like to say that the result is "values that have structure = node->structure() until
2354 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
2355 // we must choose between:
2357 // 1) "values that currently have structure = node->structure()". This is a valid
2358 // superset of the value that we really want, and it's specific enough to satisfy the
2359 // preconditions of the array access that this is guarding. It's also specific enough
2360 // to allow relevant optimizations in the case that we didn't have a contradiction
2361 // like in this example. Notice that in the abscence of any contradiction, this result
2362 // is precise rather than being a conservative LUB.
2364 // 2) "values that currently hava structure in S plus any structure transition-reachable
2365 // from S". This is also a valid superset of the value that we really want, but it's
2366 // not specific enough to satisfy the preconditions of the array access that this is
2367 // guarding - so playing such shenanigans would preclude us from having assertions on
2368 // the typing preconditions of any array accesses. This would also not be a desirable
2369 // answer in the absence of a contradiction.
2371 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
2372 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
2374 value.set(m_graph, node->structure());
2377 case GetIndexedPropertyStorage: {
2378 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2379 forNode(node->child1()).m_value, node->arrayMode());
2381 m_state.setFoundConstants(true);
2382 forNode(node).clear();
2385 case ConstantStoragePointer: {
2386 forNode(node).clear();
2390 case GetTypedArrayByteOffset: {
2391 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
2393 setConstant(node, jsNumber(view->byteOffset()));
2396 forNode(node).setType(SpecInt32Only);
2401 StorageAccessData& data = node->storageAccessData();
2402 UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2404 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2405 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2406 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2407 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2408 // on the type that ByteCodeParser was able to prove.
2409 AbstractValue value = m_graph.inferredValueForProperty(
2410 forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2412 // It's possible that the type that ByteCodeParser came up with is better.
2413 AbstractValue typeFromParsing;
2414 typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2415 value.filter(typeFromParsing);
2417 // If we decide that there does not exist any value that this can return, then it's probably
2418 // because the compilation was already invalidated.
2419 if (value.isClear())
2420 m_state.setIsValid(false);
2422 forNode(node) = value;
2424 m_state.setFoundConstants(true);
2428 case GetGetterSetterByOffset: {
2429 StorageAccessData& data = node->storageAccessData();
2430 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2431 if (result && jsDynamicCast<GetterSetter*>(result)) {
2432 setConstant(node, *m_graph.freeze(result));
2436 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
2440 case MultiGetByOffset: {
2441 // This code will filter the base value in a manner that is possibly different (either more
2442 // or less precise) than the way it would be filtered if this was strength-reduced to a
2443 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2444 // different things about the code, so long as all of them are sound. That even includes
2445 // one guy proving that code should never execute (due to a contradiction) and another guy
2446 // not finding that contradiction. If someone ever proved that there would be a
2447 // contradiction then there must always be a contradiction even if subsequent passes don't
2448 // realize it. This is the case here.
2450 // Ordinarily you have to be careful with calling setFoundConstants()
2451 // because of the effect on compile times, but this node is FTL-only.
2452 m_state.setFoundConstants(true);
2454 UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2456 AbstractValue base = forNode(node->child1());
2457 StructureSet baseSet;
2458 AbstractValue result;
2459 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
2460 StructureSet set = getCase.set();
2466 switch (getCase.method().kind()) {
2467 case GetByOffsetMethod::Constant: {
2468 AbstractValue thisResult;
2471 *getCase.method().constant(),
2472 m_state.structureClobberState());
2473 result.merge(thisResult);
2477 case GetByOffsetMethod::Load: {
2479 m_graph.inferredValueForProperty(
2480 set, uid, m_state.structureClobberState()));
2485 result.makeHeapTop();
2490 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2491 m_state.setIsValid(false);
2493 forNode(node) = result;
2501 case MultiPutByOffset: {
2502 StructureSet newSet;
2503 TransitionVector transitions;
2505 // Ordinarily you have to be careful with calling setFoundConstants()
2506 // because of the effect on compile times, but this node is FTL-only.
2507 m_state.setFoundConstants(true);
2509 AbstractValue base = forNode(node->child1());
2510 AbstractValue originalValue = forNode(node->child2());
2511 AbstractValue resultingValue;
2513 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2514 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2515 StructureSet thisSet = variant.oldStructure();
2516 thisSet.filter(base);
2517 if (thisSet.isEmpty())
2520 AbstractValue thisValue = originalValue;
2521 thisValue.filter(m_graph, variant.requiredType());
2522 resultingValue.merge(thisValue);
2524 if (variant.kind() == PutByIdVariant::Transition) {
2525 if (thisSet.onlyStructure() != variant.newStructure()) {
2527 Transition(variant.oldStructureForTransition(), variant.newStructure()));
2528 } // else this is really a replace.
2529 newSet.add(variant.newStructure());
2531 ASSERT(variant.kind() == PutByIdVariant::Replace);
2532 newSet.merge(thisSet);
2536 observeTransitions(clobberLimit, transitions);
2537 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2538 m_state.setIsValid(false);
2539 forNode(node->child2()) = resultingValue;
2540 if (!!originalValue && !resultingValue)
2541 m_state.setIsValid(false);
2545 case GetExecutable: {
2546 JSValue value = forNode(node->child1()).value();
2548 JSFunction* function = jsDynamicCast<JSFunction*>(value);
2550 setConstant(node, *m_graph.freeze(function->executable()));
2554 forNode(node).setType(m_graph, SpecCellOther);
2559 JSValue value = forNode(node->child1()).value();
2560 if (value == node->cellOperand()->value()) {
2561 m_state.setFoundConstants(true);
2565 filterByValue(node->child1(), *node->cellOperand());
2569 case CheckNotEmpty: {
2570 AbstractValue& value = forNode(node->child1());
2571 if (!(value.m_type & SpecEmpty)) {
2572 m_state.setFoundConstants(true);
2576 filter(value, ~SpecEmpty);
2580 case CheckStringIdent: {
2581 AbstractValue& value = forNode(node->child1());
2582 UniquedStringImpl* uid = node->uidOperand();
2583 ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
2585 JSValue childConstant = value.value();
2586 if (childConstant) {
2587 ASSERT(childConstant.isString());
2588 if (asString(childConstant)->tryGetValueImpl() == uid) {
2589 m_state.setFoundConstants(true);
2594 filter(value, SpecStringIdent);
2598 case CheckInBounds: {
2599 JSValue left = forNode(node->child1()).value();
2600 JSValue right = forNode(node->child2()).value();
2601 if (left && right && left.isInt32() && right.isInt32()
2602 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2603 m_state.setFoundConstants(true);
2611 case PutByIdDirect: {
2612 AbstractValue& value = forNode(node->child1());
2613 if (value.m_structure.isFinite()) {
2614 PutByIdStatus status = PutByIdStatus::computeFor(
2615 m_graph.globalObjectFor(node->origin.semantic),
2616 value.m_structure.set(),
2617 m_graph.identifiers()[node->identifierNumber()],
2618 node->op() == PutByIdDirect);
2620 if (status.isSimple()) {
2621 StructureSet newSet;
2622 TransitionVector transitions;
2624 for (unsigned i = status.numVariants(); i--;) {
2625 const PutByIdVariant& variant = status[i];
2626 if (variant.kind() == PutByIdVariant::Transition) {
2629 variant.oldStructureForTransition(), variant.newStructure()));
2630 m_graph.registerStructure(variant.newStructure());
2631 newSet.add(variant.newStructure());
2633 ASSERT(variant.kind() == PutByIdVariant::Replace);
2634 newSet.merge(variant.oldStructure());
2638 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
2639 m_state.setFoundConstants(true);
2641 observeTransitions(clobberLimit, transitions);
2642 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2643 m_state.setIsValid(false);
2648 clobberWorld(node->origin.semantic, clobberLimit);
2652 case PutByValWithThis:
2653 case PutByIdWithThis:
2654 clobberWorld(node->origin.semantic, clobberLimit);
2659 case PutGetterSetterById:
2660 case PutGetterByVal:
2661 case PutSetterByVal: {
2662 clobberWorld(node->origin.semantic, clobberLimit);
2667 // FIXME: We can determine when the property definitely exists based on abstract
2668 // value information.
2669 clobberWorld(node->origin.semantic, clobberLimit);
2670 forNode(node).setType(SpecBoolean);
2674 case GetEnumerableLength: {
2675 forNode(node).setType(SpecInt32Only);
2678 case HasGenericProperty: {
2679 forNode(node).setType(SpecBoolean);
2682 case HasStructureProperty: {
2683 forNode(node).setType(SpecBoolean);
2686 case HasIndexedProperty: {
2687 ArrayMode mode = node->arrayMode();
2688 switch (mode.type()) {
2691 case Array::Contiguous:
2692 case Array::ArrayStorage: {
2696 clobberWorld(node->origin.semantic, clobberLimit);
2700 forNode(node).setType(SpecBoolean);
2703 case GetDirectPname: {
2704 clobberWorld(node->origin.semantic, clobberLimit);
2705 forNode(node).makeHeapTop();
2708 case GetPropertyEnumerator: {
2709 forNode(node).setType(m_graph, SpecCell);
2712 case GetEnumeratorStructurePname: {
2713 forNode(node).setType(m_graph, SpecString | SpecOther);
2716 case GetEnumeratorGenericPname: {
2717 forNode(node).setType(m_graph, SpecString | SpecOther);
2720 case ToIndexString: {
2721 forNode(node).setType(m_graph, SpecString);
2726 forNode(node).makeHeapTop();
2729 case GetGlobalLexicalVariable:
2730 forNode(node).makeBytecodeTop();
2734 clobberWorld(node->origin.semantic, clobberLimit);
2735 forNode(node).makeBytecodeTop();
2739 clobberWorld(node->origin.semantic, clobberLimit);
2743 clobberWorld(node->origin.semantic, clobberLimit);
2744 forNode(node).setType(m_graph, SpecObject);
2747 case PutGlobalVariable:
2751 case OverridesHasInstance:
2752 forNode(node).setType(SpecBoolean);
2756 // Sadly, we don't propagate the fact that we've done InstanceOf
2757 forNode(node).setType(SpecBoolean);
2760 case InstanceOfCustom:
2761 clobberWorld(node->origin.semantic, clobberLimit);
2762 forNode(node).setType(SpecBoolean);
2766 RELEASE_ASSERT(m_graph.m_form == SSA);
2767 // The state of this node would have already been decided, but it may have become a
2768 // constant, in which case we'd like to know.
2769 if (forNode(node).m_value)
2770 m_state.setFoundConstants(true);
2774 m_state.createValueForNode(node->phi());
2775 forNode(node->phi()) = forNode(node->child1());
2784 case TailCallInlinedCaller:
2787 case CallForwardVarargs:
2788 case TailCallVarargsInlinedCaller:
2789 case ConstructVarargs:
2790 case ConstructForwardVarargs:
2791 case TailCallForwardVarargsInlinedCaller:
2793 clobberWorld(node->origin.semantic, clobberLimit);
2794 forNode(node).makeHeapTop();
2799 m_state.setIsValid(false);
2802 case InvalidationPoint:
2803 forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2804 m_state.setStructureClobberState(StructuresAreWatched);
2807 case CheckWatchdogTimer:
2808 case LogShadowChickenPrologue:
2809 case LogShadowChickenTail:
2813 case ProfileControlFlow:
2815 case CountExecution:
2816 case CheckTierUpInLoop:
2817 case CheckTierUpAtReturn:
2818 case CheckTypeInfoFlags:
2822 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) // This means we're already having a bad time.
2823 clobberWorld(node->origin.semantic, clobberLimit);
2824 forNode(node).setType(m_graph, SpecArray);
2828 // Simplify out checks that don't actually do checking.
2829 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2830 Edge edge = node->children.child(i);
2833 if (edge.isProved() || edge.willNotHaveCheck()) {
2834 m_state.setFoundConstants(true);
2841 case SetFunctionName: {
2842 clobberWorld(node->origin.semantic, clobberLimit);
2846 case StoreBarrier: {
2847 filter(node->child1(), SpecCell);
2851 case CheckTierUpAndOSREnter:
2858 // It may be that during a previous run of AI we proved that something was unreachable, but
2859 // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
2860 // monotonically stronger over time. So, we don't assert that AI doesn't reach the
2861 // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
2862 // crash whenever AI fails to be as powerful on run K as it was on run K-1.
2863 m_state.setIsValid(false);
2869 DFG_CRASH(m_graph, node, "Unexpected node type");
2873 return m_state.isValid();
2876 template<typename AbstractStateType>
2877 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
2879 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
2882 template<typename AbstractStateType>
2883 bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
2885 Node* node = m_state.block()->at(indexInBlock);
2889 return executeEffects(indexInBlock, node);
2892 template<typename AbstractStateType>
2893 bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2897 return executeEffects(UINT_MAX, node);
2900 template<typename AbstractStateType>
2901 void AbstractInterpreter<AbstractStateType>::clobberWorld(
2902 const CodeOrigin&, unsigned clobberLimit)
2904 clobberStructures(clobberLimit);
2907 template<typename AbstractStateType>
2908 template<typename Functor>
2909 void AbstractInterpreter<AbstractStateType>::forAllValues(
2910 unsigned clobberLimit, Functor& functor)
2912 if (clobberLimit >= m_state.block()->size())
2913 clobberLimit = m_state.block()->size();
2916 ASSERT(clobberLimit <= m_state.block()->size());
2917 for (size_t i = clobberLimit; i--;)
2918 functor(forNode(m_state.block()->at(i)));
2919 if (m_graph.m_form == SSA) {
2920 for (Node* node : m_state.block()->ssa->liveAtHead)
2921 functor(forNode(node));
2923 for (size_t i = m_state.variables().numberOfArguments(); i--;)
2924 functor(m_state.variables().argument(i));
2925 for (size_t i = m_state.variables().numberOfLocals(); i--;)
2926 functor(m_state.variables().local(i));
2929 template<typename AbstractStateType>
2930 void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
2932 forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
2936 template<typename AbstractStateType>
2937 void AbstractInterpreter<AbstractStateType>::observeTransition(
2938 unsigned clobberLimit, Structure* from, Structure* to)
2940 AbstractValue::TransitionObserver transitionObserver(from, to);
2941 forAllValues(clobberLimit, transitionObserver);
2943 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.
2946 template<typename AbstractStateType>
2947 void AbstractInterpreter<AbstractStateType>::observeTransitions(
2948 unsigned clobberLimit, const TransitionVector& vector)
2950 AbstractValue::TransitionsObserver transitionsObserver(vector);
2951 forAllValues(clobberLimit, transitionsObserver);
2953 if (!ASSERT_DISABLED) {
2954 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2955 for (unsigned i = vector.size(); i--;)
2956 ASSERT(!vector[i].previous->dfgShouldWatch());
2960 template<typename AbstractStateType>
2961 void AbstractInterpreter<AbstractStateType>::setDidClobber()
2963 m_state.setDidClobber(true);
2964 m_state.setStructureClobberState(StructuresAreClobbered);
2967 template<typename AbstractStateType>
2968 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
2970 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
2973 template<typename AbstractStateType>
2974 void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
2976 CommaPrinter comma(" ");
2977 HashSet<Node*> seen;
2978 if (m_graph.m_form == SSA) {
2979 for (Node* node : m_state.block()->ssa->liveAtHead) {
2981 AbstractValue& value = forNode(node);
2982 if (value.isClear())
2984 out.print(comma, node, ":", value);
2987 for (size_t i = 0; i < m_state.block()->size(); ++i) {
2988 Node* node = m_state.block()->at(i);
2990 AbstractValue& value = forNode(node);
2991 if (value.isClear())
2993 out.print(comma, node, ":", value);
2995 if (m_graph.m_form == SSA) {
2996 for (Node* node : m_state.block()->ssa->liveAtTail) {
2997 if (seen.contains(node))
2999 AbstractValue& value = forNode(node);
3000 if (value.isClear())
3002 out.print(comma, node, ":", value);
3007 template<typename AbstractStateType>
3008 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3009 AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
3011 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
3012 return FiltrationOK;
3013 m_state.setIsValid(false);
3014 return Contradiction;
3017 template<typename AbstractStateType>
3018 FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
3019 AbstractValue& value, ArrayModes arrayModes)
3021 if (value.filterArrayModes(arrayModes) == FiltrationOK)
3022 return FiltrationOK;
3023 m_state.setIsValid(false);
3024 return Contradiction;
3027 template<typename AbstractStateType>
3028 FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
3029 AbstractValue& value, SpeculatedType type)
3031 if (value.filter(type) == FiltrationOK)
3032 return FiltrationOK;
3033 m_state.setIsValid(false);
3034 return Contradiction;
3037 template<typename AbstractStateType>
3038 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
3039 AbstractValue& abstractValue, FrozenValue concreteValue)
3041 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
3042 return FiltrationOK;
3043 m_state.setIsValid(false);
3044 return Contradiction;
3047 template<typename AbstractStateType>
3048 void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
3050 JSValue child = forNode(node->child1()).value();
3051 if (Optional<double> number = child.toNumberFromPrimitive()) {
3052 setConstant(node, jsDoubleNumber(equivalentFunction(*number)));