2 * Copyright (C) 2013-2015 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 "DFGAbstractInterpreter.h"
32 #include "GetByIdStatus.h"
33 #include "GetterSetter.h"
34 #include "JITOperations.h"
35 #include "MathCommon.h"
36 #include "Operations.h"
37 #include "PutByIdStatus.h"
38 #include "StringObject.h"
40 namespace JSC
{ namespace DFG
{
42 template<typename AbstractStateType
>
43 AbstractInterpreter
<AbstractStateType
>::AbstractInterpreter(Graph
& graph
, AbstractStateType
& state
)
44 : m_codeBlock(graph
.m_codeBlock
)
48 if (m_graph
.m_form
== SSA
)
49 m_phiChildren
= std::make_unique
<PhiChildren
>(m_graph
);
52 template<typename AbstractStateType
>
53 AbstractInterpreter
<AbstractStateType
>::~AbstractInterpreter()
57 template<typename AbstractStateType
>
58 typename AbstractInterpreter
<AbstractStateType
>::BooleanResult
59 AbstractInterpreter
<AbstractStateType
>::booleanResult(
60 Node
* node
, AbstractValue
& value
)
62 JSValue childConst
= value
.value();
64 if (childConst
.toBoolean(m_codeBlock
->globalObjectFor(node
->origin
.semantic
)->globalExec()))
65 return DefinitelyTrue
;
66 return DefinitelyFalse
;
69 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
70 if (isCellSpeculation(value
.m_type
) && !value
.m_structure
.isTop()) {
72 for (unsigned i
= value
.m_structure
.size(); i
--;) {
73 Structure
* structure
= value
.m_structure
[i
];
74 if (structure
->masqueradesAsUndefined(m_codeBlock
->globalObjectFor(node
->origin
.semantic
))
75 || structure
->typeInfo().type() == StringType
) {
81 return DefinitelyTrue
;
84 return UnknownBooleanResult
;
87 template<typename AbstractStateType
>
88 void AbstractInterpreter
<AbstractStateType
>::startExecuting()
90 ASSERT(m_state
.block());
91 ASSERT(m_state
.isValid());
93 m_state
.setDidClobber(false);
96 template<typename AbstractStateType
>
97 void AbstractInterpreter
<AbstractStateType
>::executeEdges(Node
* node
)
99 DFG_NODE_DO_TO_CHILDREN(m_graph
, node
, filterEdgeByUse
);
102 template<typename AbstractStateType
>
103 void AbstractInterpreter
<AbstractStateType
>::executeEdges(unsigned indexInBlock
)
105 executeEdges(m_state
.block()->at(indexInBlock
));
108 template<typename AbstractStateType
>
109 void AbstractInterpreter
<AbstractStateType
>::verifyEdge(Node
* node
, Edge edge
)
111 if (!(forNode(edge
).m_type
& ~typeFilterFor(edge
.useKind())))
114 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());
117 template<typename AbstractStateType
>
118 void AbstractInterpreter
<AbstractStateType
>::verifyEdges(Node
* node
)
120 DFG_NODE_DO_TO_CHILDREN(m_graph
, node
, verifyEdge
);
123 template<typename AbstractStateType
>
124 bool AbstractInterpreter
<AbstractStateType
>::executeEffects(unsigned clobberLimit
, Node
* node
)
126 if (!ASSERT_DISABLED
)
129 m_state
.createValueForNode(node
);
131 switch (node
->op()) {
134 case Int52Constant
: {
135 setBuiltInConstant(node
, *node
->constant());
140 forNode(node
) = forNode(node
->child1());
141 if (forNode(node
).value())
142 m_state
.setFoundConstants(true);
146 case ExtractOSREntryLocal
: {
147 forNode(node
).makeBytecodeTop();
152 VariableAccessData
* variableAccessData
= node
->variableAccessData();
153 AbstractValue value
= m_state
.variables().operand(variableAccessData
->local().offset());
154 // The value in the local should already be checked.
155 DFG_ASSERT(m_graph
, node
, value
.isType(typeFilterFor(variableAccessData
->flushFormat())));
157 m_state
.setFoundConstants(true);
158 forNode(node
) = value
;
163 StackAccessData
* data
= node
->stackAccessData();
164 AbstractValue value
= m_state
.variables().operand(data
->local
);
165 // The value in the local should already be checked.
166 DFG_ASSERT(m_graph
, node
, value
.isType(typeFilterFor(data
->format
)));
168 m_state
.setFoundConstants(true);
169 forNode(node
) = value
;
173 case GetLocalUnlinked
: {
174 AbstractValue value
= m_state
.variables().operand(node
->unlinkedLocal().offset());
176 m_state
.setFoundConstants(true);
177 forNode(node
) = value
;
182 m_state
.variables().operand(node
->local()) = forNode(node
->child1());
187 m_state
.variables().operand(node
->stackAccessData()->local
) = forNode(node
->child1());
192 // Don't need to do anything. A MovHint only informs us about what would have happened
193 // in bytecode, but this code is just concerned with what is actually happening during
199 // This is just a hint telling us that the OSR state of the local is no longer inside the
205 // Assert that the state of arguments has been set. SetArgument means that someone set
206 // the argument values out-of-band, and currently this always means setting to a
208 ASSERT(!m_state
.variables().operand(node
->local()).isClear());
212 case ForwardVarargs
: {
213 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
214 // itself into a straight-line sequence of GetStack/PutStack.
215 // https://bugs.webkit.org/show_bug.cgi?id=143071
216 clobberWorld(node
->origin
.semantic
, clobberLimit
);
217 LoadVarargsData
* data
= node
->loadVarargsData();
218 m_state
.variables().operand(data
->count
).setType(SpecInt32
);
219 for (unsigned i
= data
->limit
- 1; i
--;)
220 m_state
.variables().operand(data
->start
.offset() + i
).makeHeapTop();
230 JSValue left
= forNode(node
->child1()).value();
231 JSValue right
= forNode(node
->child2()).value();
232 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
233 int32_t a
= left
.asInt32();
234 int32_t b
= right
.asInt32();
235 switch (node
->op()) {
237 setConstant(node
, JSValue(a
& b
));
240 setConstant(node
, JSValue(a
| b
));
243 setConstant(node
, JSValue(a
^ b
));
246 setConstant(node
, JSValue(a
>> static_cast<uint32_t>(b
)));
249 setConstant(node
, JSValue(a
<< static_cast<uint32_t>(b
)));
252 setConstant(node
, JSValue(static_cast<uint32_t>(a
) >> static_cast<uint32_t>(b
)));
255 RELEASE_ASSERT_NOT_REACHED();
261 if (node
->op() == BitAnd
262 && (isBoolInt32Speculation(forNode(node
->child1()).m_type
) ||
263 isBoolInt32Speculation(forNode(node
->child2()).m_type
))) {
264 forNode(node
).setType(SpecBoolInt32
);
268 forNode(node
).setType(SpecInt32
);
272 case UInt32ToNumber
: {
273 JSValue child
= forNode(node
->child1()).value();
274 if (doesOverflow(node
->arithMode())) {
275 if (child
&& child
.isInt32()) {
276 uint32_t value
= child
.asInt32();
277 setConstant(node
, jsNumber(value
));
280 forNode(node
).setType(SpecInt52AsDouble
);
283 if (child
&& child
.isInt32()) {
284 int32_t value
= child
.asInt32();
286 setConstant(node
, jsNumber(value
));
290 forNode(node
).setType(SpecInt32
);
294 case BooleanToNumber
: {
295 JSValue concreteValue
= forNode(node
->child1()).value();
297 if (concreteValue
.isBoolean())
298 setConstant(node
, jsNumber(concreteValue
.asBoolean()));
300 setConstant(node
, *m_graph
.freeze(concreteValue
));
303 AbstractValue
& value
= forNode(node
);
304 value
= forNode(node
->child1());
305 if (node
->child1().useKind() == UntypedUse
&& !(value
.m_type
& ~SpecBoolean
))
306 m_state
.setFoundConstants(true);
307 if (value
.m_type
& SpecBoolean
) {
308 value
.merge(SpecBoolInt32
);
309 value
.filter(~SpecBoolean
);
314 case DoubleAsInt32
: {
315 JSValue child
= forNode(node
->child1()).value();
316 if (child
&& child
.isNumber()) {
317 double asDouble
= child
.asNumber();
318 int32_t asInt
= JSC::toInt32(asDouble
);
319 if (bitwise_cast
<int64_t>(static_cast<double>(asInt
)) == bitwise_cast
<int64_t>(asDouble
)) {
320 setConstant(node
, JSValue(asInt
));
324 forNode(node
).setType(SpecInt32
);
329 JSValue child
= forNode(node
->child1()).value();
331 if (child
.isNumber()) {
333 setConstant(node
, child
);
335 setConstant(node
, JSValue(JSC::toInt32(child
.asDouble())));
338 if (child
.isBoolean()) {
339 setConstant(node
, jsNumber(child
.asBoolean()));
342 if (child
.isUndefinedOrNull()) {
343 setConstant(node
, jsNumber(0));
348 if (isBooleanSpeculation(forNode(node
->child1()).m_type
)) {
349 forNode(node
).setType(SpecBoolInt32
);
353 forNode(node
).setType(SpecInt32
);
358 JSValue child
= forNode(node
->child1()).value();
359 if (child
&& child
.isNumber()) {
360 setConstant(node
, jsDoubleNumber(child
.asNumber()));
364 SpeculatedType type
= forNode(node
->child1()).m_type
;
365 switch (node
->child1().useKind()) {
367 if (type
& SpecOther
) {
369 type
|= SpecDoublePureNaN
| SpecBoolInt32
; // Null becomes zero, undefined becomes NaN.
371 if (type
& SpecBoolean
) {
372 type
&= ~SpecBoolean
;
373 type
|= SpecBoolInt32
; // True becomes 1, false becomes 0.
375 type
&= SpecBytecodeNumber
;
385 RELEASE_ASSERT_NOT_REACHED();
387 forNode(node
).setType(type
);
388 forNode(node
).fixTypeForRepresentation(m_graph
, node
);
393 JSValue child
= forNode(node
->child1()).value();
394 if (child
&& child
.isMachineInt()) {
395 setConstant(node
, child
);
399 forNode(node
).setType(SpecInt32
);
404 JSValue value
= forNode(node
->child1()).value();
406 setConstant(node
, value
);
410 forNode(node
).setType(m_graph
, forNode(node
->child1()).m_type
& ~SpecDoubleImpureNaN
);
411 forNode(node
).fixTypeForRepresentation(m_graph
, node
);
416 ASSERT(node
->binaryUseKind() == UntypedUse
);
417 clobberWorld(node
->origin
.semantic
, clobberLimit
);
418 forNode(node
).setType(m_graph
, SpecString
| SpecBytecodeNumber
);
423 JSValue left
= forNode(node
->child1()).value();
424 JSValue right
= forNode(node
->child2()).value();
425 switch (node
->binaryUseKind()) {
427 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
428 if (!shouldCheckOverflow(node
->arithMode())) {
429 setConstant(node
, jsNumber(left
.asInt32() + right
.asInt32()));
432 JSValue result
= jsNumber(left
.asNumber() + right
.asNumber());
433 if (result
.isInt32()) {
434 setConstant(node
, result
);
438 forNode(node
).setType(SpecInt32
);
441 if (left
&& right
&& left
.isMachineInt() && right
.isMachineInt()) {
442 JSValue result
= jsNumber(left
.asMachineInt() + right
.asMachineInt());
443 if (result
.isMachineInt()) {
444 setConstant(node
, result
);
448 forNode(node
).setType(SpecMachineInt
);
451 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
452 setConstant(node
, jsDoubleNumber(left
.asNumber() + right
.asNumber()));
455 forNode(node
).setType(
457 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
460 RELEASE_ASSERT_NOT_REACHED();
467 JSValue operand
= forNode(node
->child1()).value();
468 if (operand
&& operand
.isNumber()) {
469 uint32_t value
= toUInt32(operand
.asNumber());
470 setConstant(node
, jsNumber(clz32(value
)));
473 forNode(node
).setType(SpecInt32
);
478 forNode(node
).set(m_graph
, m_graph
.m_vm
.stringStructure
.get());
483 JSValue left
= forNode(node
->child1()).value();
484 JSValue right
= forNode(node
->child2()).value();
485 switch (node
->binaryUseKind()) {
487 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
488 if (!shouldCheckOverflow(node
->arithMode())) {
489 setConstant(node
, jsNumber(left
.asInt32() - right
.asInt32()));
492 JSValue result
= jsNumber(left
.asNumber() - right
.asNumber());
493 if (result
.isInt32()) {
494 setConstant(node
, result
);
498 forNode(node
).setType(SpecInt32
);
501 if (left
&& right
&& left
.isMachineInt() && right
.isMachineInt()) {
502 JSValue result
= jsNumber(left
.asMachineInt() - right
.asMachineInt());
503 if (result
.isMachineInt() || !shouldCheckOverflow(node
->arithMode())) {
504 setConstant(node
, result
);
508 forNode(node
).setType(SpecMachineInt
);
511 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
512 setConstant(node
, jsDoubleNumber(left
.asNumber() - right
.asNumber()));
515 forNode(node
).setType(
516 typeOfDoubleDifference(
517 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
520 RELEASE_ASSERT_NOT_REACHED();
527 JSValue child
= forNode(node
->child1()).value();
528 switch (node
->child1().useKind()) {
530 if (child
&& child
.isInt32()) {
531 if (!shouldCheckOverflow(node
->arithMode())) {
532 setConstant(node
, jsNumber(-child
.asInt32()));
536 if (shouldCheckNegativeZero(node
->arithMode()))
537 doubleResult
= -child
.asNumber();
539 doubleResult
= 0 - child
.asNumber();
540 JSValue valueResult
= jsNumber(doubleResult
);
541 if (valueResult
.isInt32()) {
542 setConstant(node
, valueResult
);
546 forNode(node
).setType(SpecInt32
);
549 if (child
&& child
.isMachineInt()) {
551 if (shouldCheckNegativeZero(node
->arithMode()))
552 doubleResult
= -child
.asNumber();
554 doubleResult
= 0 - child
.asNumber();
555 JSValue valueResult
= jsNumber(doubleResult
);
556 if (valueResult
.isMachineInt()) {
557 setConstant(node
, valueResult
);
561 forNode(node
).setType(SpecMachineInt
);
564 if (child
&& child
.isNumber()) {
565 setConstant(node
, jsDoubleNumber(-child
.asNumber()));
568 forNode(node
).setType(
569 typeOfDoubleNegation(
570 forNode(node
->child1()).m_type
));
573 RELEASE_ASSERT_NOT_REACHED();
580 JSValue left
= forNode(node
->child1()).value();
581 JSValue right
= forNode(node
->child2()).value();
582 switch (node
->binaryUseKind()) {
584 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
585 if (!shouldCheckOverflow(node
->arithMode())) {
586 setConstant(node
, jsNumber(left
.asInt32() * right
.asInt32()));
589 double doubleResult
= left
.asNumber() * right
.asNumber();
590 if (!shouldCheckNegativeZero(node
->arithMode()))
591 doubleResult
+= 0; // Sanitizes zero.
592 JSValue valueResult
= jsNumber(doubleResult
);
593 if (valueResult
.isInt32()) {
594 setConstant(node
, valueResult
);
598 forNode(node
).setType(SpecInt32
);
601 if (left
&& right
&& left
.isMachineInt() && right
.isMachineInt()) {
602 double doubleResult
= left
.asNumber() * right
.asNumber();
603 if (!shouldCheckNegativeZero(node
->arithMode()))
605 JSValue valueResult
= jsNumber(doubleResult
);
606 if (valueResult
.isMachineInt()) {
607 setConstant(node
, valueResult
);
611 forNode(node
).setType(SpecMachineInt
);
614 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
615 setConstant(node
, jsDoubleNumber(left
.asNumber() * right
.asNumber()));
618 forNode(node
).setType(
620 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
623 RELEASE_ASSERT_NOT_REACHED();
630 JSValue left
= forNode(node
->child1()).value();
631 JSValue right
= forNode(node
->child2()).value();
632 switch (node
->binaryUseKind()) {
634 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
635 double doubleResult
= left
.asNumber() / right
.asNumber();
636 if (!shouldCheckOverflow(node
->arithMode()))
637 doubleResult
= toInt32(doubleResult
);
638 else if (!shouldCheckNegativeZero(node
->arithMode()))
639 doubleResult
+= 0; // Sanitizes zero.
640 JSValue valueResult
= jsNumber(doubleResult
);
641 if (valueResult
.isInt32()) {
642 setConstant(node
, valueResult
);
646 forNode(node
).setType(SpecInt32
);
649 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
650 setConstant(node
, jsDoubleNumber(left
.asNumber() / right
.asNumber()));
653 forNode(node
).setType(
654 typeOfDoubleQuotient(
655 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
658 RELEASE_ASSERT_NOT_REACHED();
665 JSValue left
= forNode(node
->child1()).value();
666 JSValue right
= forNode(node
->child2()).value();
667 switch (node
->binaryUseKind()) {
669 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
670 double doubleResult
= fmod(left
.asNumber(), right
.asNumber());
671 if (!shouldCheckOverflow(node
->arithMode()))
672 doubleResult
= toInt32(doubleResult
);
673 else if (!shouldCheckNegativeZero(node
->arithMode()))
674 doubleResult
+= 0; // Sanitizes zero.
675 JSValue valueResult
= jsNumber(doubleResult
);
676 if (valueResult
.isInt32()) {
677 setConstant(node
, valueResult
);
681 forNode(node
).setType(SpecInt32
);
684 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
685 setConstant(node
, jsDoubleNumber(fmod(left
.asNumber(), right
.asNumber())));
688 forNode(node
).setType(
689 typeOfDoubleBinaryOp(
690 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
693 RELEASE_ASSERT_NOT_REACHED();
700 JSValue left
= forNode(node
->child1()).value();
701 JSValue right
= forNode(node
->child2()).value();
702 switch (node
->binaryUseKind()) {
704 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
705 setConstant(node
, jsNumber(std::min(left
.asInt32(), right
.asInt32())));
708 forNode(node
).setType(SpecInt32
);
711 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
712 double a
= left
.asNumber();
713 double b
= right
.asNumber();
714 setConstant(node
, jsDoubleNumber(a
< b
? a
: (b
<= a
? b
: a
+ b
)));
717 forNode(node
).setType(
719 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
722 RELEASE_ASSERT_NOT_REACHED();
729 JSValue left
= forNode(node
->child1()).value();
730 JSValue right
= forNode(node
->child2()).value();
731 switch (node
->binaryUseKind()) {
733 if (left
&& right
&& left
.isInt32() && right
.isInt32()) {
734 setConstant(node
, jsNumber(std::max(left
.asInt32(), right
.asInt32())));
737 forNode(node
).setType(SpecInt32
);
740 if (left
&& right
&& left
.isNumber() && right
.isNumber()) {
741 double a
= left
.asNumber();
742 double b
= right
.asNumber();
743 setConstant(node
, jsDoubleNumber(a
> b
? a
: (b
>= a
? b
: a
+ b
)));
746 forNode(node
).setType(
748 forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
751 RELEASE_ASSERT_NOT_REACHED();
758 JSValue child
= forNode(node
->child1()).value();
759 switch (node
->child1().useKind()) {
761 if (child
&& child
.isInt32()) {
762 JSValue result
= jsNumber(fabs(child
.asNumber()));
763 if (result
.isInt32()) {
764 setConstant(node
, result
);
768 forNode(node
).setType(SpecInt32
);
771 if (child
&& child
.isNumber()) {
772 setConstant(node
, jsDoubleNumber(fabs(child
.asNumber())));
775 forNode(node
).setType(typeOfDoubleAbs(forNode(node
->child1()).m_type
));
778 RELEASE_ASSERT_NOT_REACHED();
785 JSValue childY
= forNode(node
->child2()).value();
786 if (childY
&& childY
.isNumber()) {
787 if (!childY
.asNumber()) {
788 setConstant(node
, jsDoubleNumber(1));
792 JSValue childX
= forNode(node
->child1()).value();
793 if (childX
&& childX
.isNumber()) {
794 setConstant(node
, jsDoubleNumber(operationMathPow(childX
.asNumber(), childY
.asNumber())));
798 forNode(node
).setType(typeOfDoublePow(forNode(node
->child1()).m_type
, forNode(node
->child2()).m_type
));
803 JSValue operand
= forNode(node
->child1()).value();
804 if (operand
&& operand
.isNumber()) {
805 double roundedValue
= jsRound(operand
.asNumber());
807 if (producesInteger(node
->arithRoundingMode())) {
808 int32_t roundedValueAsInt32
= static_cast<int32_t>(roundedValue
);
809 if (roundedValueAsInt32
== roundedValue
) {
810 if (shouldCheckNegativeZero(node
->arithRoundingMode())) {
811 if (roundedValueAsInt32
|| !std::signbit(roundedValue
)) {
812 setConstant(node
, jsNumber(roundedValueAsInt32
));
816 setConstant(node
, jsNumber(roundedValueAsInt32
));
821 setConstant(node
, jsDoubleNumber(roundedValue
));
825 if (producesInteger(node
->arithRoundingMode()))
826 forNode(node
).setType(SpecInt32
);
828 forNode(node
).setType(typeOfDoubleRounding(forNode(node
->child1()).m_type
));
833 JSValue child
= forNode(node
->child1()).value();
834 if (child
&& child
.isNumber()) {
835 setConstant(node
, jsDoubleNumber(sqrt(child
.asNumber())));
838 forNode(node
).setType(typeOfDoubleUnaryOp(forNode(node
->child1()).m_type
));
843 JSValue child
= forNode(node
->child1()).value();
844 if (child
&& child
.isNumber()) {
845 setConstant(node
, jsDoubleNumber(static_cast<float>(child
.asNumber())));
848 forNode(node
).setType(typeOfDoubleRounding(forNode(node
->child1()).m_type
));
853 JSValue child
= forNode(node
->child1()).value();
854 if (child
&& child
.isNumber()) {
855 setConstant(node
, jsDoubleNumber(sin(child
.asNumber())));
858 forNode(node
).setType(typeOfDoubleUnaryOp(forNode(node
->child1()).m_type
));
863 JSValue child
= forNode(node
->child1()).value();
864 if (child
&& child
.isNumber()) {
865 setConstant(node
, jsDoubleNumber(cos(child
.asNumber())));
868 forNode(node
).setType(typeOfDoubleUnaryOp(forNode(node
->child1()).m_type
));
873 JSValue child
= forNode(node
->child1()).value();
874 if (child
&& child
.isNumber()) {
875 setConstant(node
, jsDoubleNumber(log(child
.asNumber())));
878 forNode(node
).setType(typeOfDoubleUnaryOp(forNode(node
->child1()).m_type
));
883 switch (booleanResult(node
, forNode(node
->child1()))) {
885 setConstant(node
, jsBoolean(false));
887 case DefinitelyFalse
:
888 setConstant(node
, jsBoolean(true));
891 forNode(node
).setType(SpecBoolean
);
904 AbstractValue child
= forNode(node
->child1());
906 bool constantWasSet
= true;
907 switch (node
->op()) {
909 setConstant(node
, jsBoolean(
910 child
.value().isCell()
911 ? child
.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock
->globalObjectFor(node
->origin
.semantic
))
912 : child
.value().isUndefined()));
915 setConstant(node
, jsBoolean(child
.value().isBoolean()));
918 setConstant(node
, jsBoolean(child
.value().isNumber()));
921 setConstant(node
, jsBoolean(isJSString(child
.value())));
924 setConstant(node
, jsBoolean(child
.value().isObject()));
927 if (child
.value().isObject()) {
928 JSObject
* object
= asObject(child
.value());
929 if (object
->type() == JSFunctionType
)
930 setConstant(node
, jsBoolean(false));
931 else if (!(object
->inlineTypeFlags() & TypeOfShouldCallGetCallData
))
932 setConstant(node
, jsBoolean(!child
.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock
->globalObjectFor(node
->origin
.semantic
))));
934 // FIXME: This could just call getCallData.
935 // https://bugs.webkit.org/show_bug.cgi?id=144457
936 constantWasSet
= false;
939 setConstant(node
, jsBoolean(child
.value().isNull()));
942 if (child
.value().isObject()) {
943 JSObject
* object
= asObject(child
.value());
944 if (object
->type() == JSFunctionType
)
945 setConstant(node
, jsBoolean(true));
946 else if (!(object
->inlineTypeFlags() & TypeOfShouldCallGetCallData
))
947 setConstant(node
, jsBoolean(false));
949 // FIXME: This could just call getCallData.
950 // https://bugs.webkit.org/show_bug.cgi?id=144457
951 constantWasSet
= false;
954 setConstant(node
, jsBoolean(false));
957 constantWasSet
= false;
964 // FIXME: This code should really use AbstractValue::isType() and
965 // AbstractValue::couldBeType().
966 // https://bugs.webkit.org/show_bug.cgi?id=146870
968 bool constantWasSet
= false;
969 switch (node
->op()) {
971 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
972 // https://bugs.webkit.org/show_bug.cgi?id=144456
974 if (!(child
.m_type
& (SpecOther
| SpecObjectOther
))) {
975 setConstant(node
, jsBoolean(false));
976 constantWasSet
= true;
982 if (!(child
.m_type
& ~SpecBoolean
)) {
983 setConstant(node
, jsBoolean(true));
984 constantWasSet
= true;
988 if (!(child
.m_type
& SpecBoolean
)) {
989 setConstant(node
, jsBoolean(false));
990 constantWasSet
= true;
996 if (!(child
.m_type
& ~SpecFullNumber
)) {
997 setConstant(node
, jsBoolean(true));
998 constantWasSet
= true;
1002 if (!(child
.m_type
& SpecFullNumber
)) {
1003 setConstant(node
, jsBoolean(false));
1004 constantWasSet
= true;
1010 if (!(child
.m_type
& ~SpecString
)) {
1011 setConstant(node
, jsBoolean(true));
1012 constantWasSet
= true;
1016 if (!(child
.m_type
& SpecString
)) {
1017 setConstant(node
, jsBoolean(false));
1018 constantWasSet
= true;
1024 if (!(child
.m_type
& ~SpecObject
)) {
1025 setConstant(node
, jsBoolean(true));
1026 constantWasSet
= true;
1030 if (!(child
.m_type
& SpecObject
)) {
1031 setConstant(node
, jsBoolean(false));
1032 constantWasSet
= true;
1037 case IsObjectOrNull
:
1038 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1039 // https://bugs.webkit.org/show_bug.cgi?id=144456
1041 // These expressions are complicated to parse. A helpful way to parse this is that
1042 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1043 // disjoint set from S". Things like "T - S" means that, provided that S is a
1044 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1045 // mean the "union of T and S".
1047 // Is the child's type an object that isn't an other-object (i.e. object that could
1048 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1050 if (!(child
.m_type
& ~(SpecObject
- SpecObjectOther
- SpecFunction
))) {
1051 setConstant(node
, jsBoolean(true));
1052 constantWasSet
= true;
1056 // Is the child's type definitely not either of: an object that isn't a function,
1057 // or either undefined or null? Then: we should fold this to false. This means
1058 // for example that if it's any non-function object, including those that have
1059 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1060 // if it's undefined-or-null, since the type bits don't distinguish between
1061 // undefined (which should fold to false) and null (which should fold to true).
1062 if (!(child
.m_type
& ((SpecObject
- SpecFunction
) | SpecOther
))) {
1063 setConstant(node
, jsBoolean(false));
1064 constantWasSet
= true;
1070 if (!(child
.m_type
& ~SpecFunction
)) {
1071 setConstant(node
, jsBoolean(true));
1072 constantWasSet
= true;
1076 if (!(child
.m_type
& (SpecFunction
| SpecObjectOther
))) {
1077 setConstant(node
, jsBoolean(false));
1078 constantWasSet
= true;
1088 forNode(node
).setType(SpecBoolean
);
1093 VM
* vm
= m_codeBlock
->vm();
1094 JSValue child
= forNode(node
->child1()).value();
1095 AbstractValue
& abstractChild
= forNode(node
->child1());
1097 JSValue typeString
= jsTypeStringForValue(*vm
, m_codeBlock
->globalObjectFor(node
->origin
.semantic
), child
);
1098 setConstant(node
, *m_graph
.freeze(typeString
));
1102 if (isFullNumberSpeculation(abstractChild
.m_type
)) {
1103 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.numberString()));
1107 if (isStringSpeculation(abstractChild
.m_type
)) {
1108 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.stringString()));
1112 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1113 // https://bugs.webkit.org/show_bug.cgi?id=144456
1114 if (!(abstractChild
.m_type
& ~(SpecObject
- SpecObjectOther
))) {
1115 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.objectString()));
1119 if (isFunctionSpeculation(abstractChild
.m_type
)) {
1120 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.functionString()));
1124 if (isBooleanSpeculation(abstractChild
.m_type
)) {
1125 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.booleanString()));
1129 if (isSymbolSpeculation(abstractChild
.m_type
)) {
1130 setConstant(node
, *m_graph
.freeze(vm
->smallStrings
.symbolString()));
1134 forNode(node
).setType(m_graph
, SpecStringIdent
);
1140 case CompareGreater
:
1141 case CompareGreaterEq
:
1143 case CompareEqConstant
: {
1144 JSValue leftConst
= forNode(node
->child1()).value();
1145 JSValue rightConst
= forNode(node
->child2()).value();
1146 if (leftConst
&& rightConst
) {
1147 if (leftConst
.isNumber() && rightConst
.isNumber()) {
1148 double a
= leftConst
.asNumber();
1149 double b
= rightConst
.asNumber();
1150 switch (node
->op()) {
1152 setConstant(node
, jsBoolean(a
< b
));
1155 setConstant(node
, jsBoolean(a
<= b
));
1157 case CompareGreater
:
1158 setConstant(node
, jsBoolean(a
> b
));
1160 case CompareGreaterEq
:
1161 setConstant(node
, jsBoolean(a
>= b
));
1164 setConstant(node
, jsBoolean(a
== b
));
1167 RELEASE_ASSERT_NOT_REACHED();
1173 if (node
->op() == CompareEq
&& leftConst
.isString() && rightConst
.isString()) {
1174 const StringImpl
* a
= asString(leftConst
)->tryGetValueImpl();
1175 const StringImpl
* b
= asString(rightConst
)->tryGetValueImpl();
1177 setConstant(node
, jsBoolean(WTF::equal(a
, b
)));
1183 if (node
->op() == CompareEqConstant
|| node
->op() == CompareEq
) {
1184 SpeculatedType leftType
= forNode(node
->child1()).m_type
;
1185 SpeculatedType rightType
= forNode(node
->child2()).m_type
;
1186 if (!valuesCouldBeEqual(leftType
, rightType
)) {
1187 setConstant(node
, jsBoolean(false));
1192 forNode(node
).setType(SpecBoolean
);
1196 case CompareStrictEq
: {
1197 Node
* leftNode
= node
->child1().node();
1198 Node
* rightNode
= node
->child2().node();
1199 JSValue left
= forNode(leftNode
).value();
1200 JSValue right
= forNode(rightNode
).value();
1201 if (left
&& right
) {
1202 if (left
.isString() && right
.isString()) {
1203 // We need this case because JSValue::strictEqual is otherwise too racy for
1204 // string comparisons.
1205 const StringImpl
* a
= asString(left
)->tryGetValueImpl();
1206 const StringImpl
* b
= asString(right
)->tryGetValueImpl();
1208 setConstant(node
, jsBoolean(WTF::equal(a
, b
)));
1212 setConstant(node
, jsBoolean(JSValue::strictEqual(0, left
, right
)));
1217 SpeculatedType leftLUB
= leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode
).m_type
);
1218 SpeculatedType rightLUB
= leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode
).m_type
);
1219 if (!(leftLUB
& rightLUB
)) {
1220 setConstant(node
, jsBoolean(false));
1224 forNode(node
).setType(SpecBoolean
);
1228 case StringCharCodeAt
:
1229 forNode(node
).setType(SpecInt32
);
1232 case StringFromCharCode
:
1233 forNode(node
).setType(m_graph
, SpecString
);
1237 forNode(node
).set(m_graph
, m_graph
.m_vm
.stringStructure
.get());
1241 switch (node
->arrayMode().type()) {
1242 case Array::SelectUsingPredictions
:
1243 case Array::Unprofiled
:
1244 case Array::Undecided
:
1245 RELEASE_ASSERT_NOT_REACHED();
1247 case Array::ForceExit
:
1248 m_state
.setIsValid(false);
1250 case Array::Generic
:
1251 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1252 forNode(node
).makeHeapTop();
1255 if (node
->arrayMode().isOutOfBounds()) {
1256 // If the watchpoint was still valid we could totally set this to be
1257 // SpecString | SpecOther. Except that we'd have to be careful. If we
1258 // tested the watchpoint state here then it could change by the time
1259 // we got to the backend. So to do this right, we'd have to get the
1260 // fixup phase to check the watchpoint state and then bake into the
1261 // GetByVal operation the fact that we're using a watchpoint, using
1262 // something like Array::SaneChain (except not quite, because that
1263 // implies an in-bounds access). None of this feels like it's worth it,
1264 // so we're going with TOP for now. The same thing applies to
1265 // clobbering the world.
1266 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1267 forNode(node
).makeHeapTop();
1269 forNode(node
).set(m_graph
, m_graph
.m_vm
.stringStructure
.get());
1271 case Array::DirectArguments
:
1272 case Array::ScopedArguments
:
1273 forNode(node
).makeHeapTop();
1276 if (node
->arrayMode().isOutOfBounds()) {
1277 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1278 forNode(node
).makeHeapTop();
1280 forNode(node
).setType(SpecInt32
);
1283 if (node
->arrayMode().isOutOfBounds()) {
1284 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1285 forNode(node
).makeHeapTop();
1286 } else if (node
->arrayMode().isSaneChain())
1287 forNode(node
).setType(SpecBytecodeDouble
);
1289 forNode(node
).setType(SpecDoubleReal
);
1291 case Array::Contiguous
:
1292 case Array::ArrayStorage
:
1293 case Array::SlowPutArrayStorage
:
1294 if (node
->arrayMode().isOutOfBounds())
1295 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1296 forNode(node
).makeHeapTop();
1298 case Array::Int8Array
:
1299 forNode(node
).setType(SpecInt32
);
1301 case Array::Int16Array
:
1302 forNode(node
).setType(SpecInt32
);
1304 case Array::Int32Array
:
1305 forNode(node
).setType(SpecInt32
);
1307 case Array::Uint8Array
:
1308 forNode(node
).setType(SpecInt32
);
1310 case Array::Uint8ClampedArray
:
1311 forNode(node
).setType(SpecInt32
);
1313 case Array::Uint16Array
:
1314 forNode(node
).setType(SpecInt32
);
1316 case Array::Uint32Array
:
1317 if (node
->shouldSpeculateInt32())
1318 forNode(node
).setType(SpecInt32
);
1319 else if (enableInt52() && node
->shouldSpeculateMachineInt())
1320 forNode(node
).setType(SpecInt52
);
1322 forNode(node
).setType(SpecInt52AsDouble
);
1324 case Array::Float32Array
:
1325 forNode(node
).setType(SpecFullDouble
);
1327 case Array::Float64Array
:
1328 forNode(node
).setType(SpecFullDouble
);
1331 RELEASE_ASSERT_NOT_REACHED();
1337 case PutByValDirect
:
1339 case PutByValAlias
: {
1340 switch (node
->arrayMode().modeForPut().type()) {
1341 case Array::ForceExit
:
1342 m_state
.setIsValid(false);
1344 case Array::Generic
:
1345 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1348 if (node
->arrayMode().isOutOfBounds())
1349 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1352 if (node
->arrayMode().isOutOfBounds())
1353 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1355 case Array::Contiguous
:
1356 case Array::ArrayStorage
:
1357 if (node
->arrayMode().isOutOfBounds())
1358 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1360 case Array::SlowPutArrayStorage
:
1361 if (node
->arrayMode().mayStoreToHole())
1362 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1371 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1372 forNode(node
).setType(SpecBytecodeNumber
);
1376 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1377 forNode(node
).makeHeapTop();
1380 case GetMyArgumentByVal
: {
1381 JSValue index
= forNode(node
->child2()).m_value
;
1382 InlineCallFrame
* inlineCallFrame
= node
->child1()->origin
.semantic
.inlineCallFrame
;
1384 if (index
&& index
.isInt32()) {
1385 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1386 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1387 // paths as unreachable, and it's almost certainly not worth the effort.
1389 if (inlineCallFrame
) {
1390 if (index
.asUInt32() < inlineCallFrame
->arguments
.size() - 1) {
1391 forNode(node
) = m_state
.variables().operand(
1392 virtualRegisterForArgument(index
.asInt32() + 1) + inlineCallFrame
->stackOffset
);
1393 m_state
.setFoundConstants(true);
1397 if (index
.asUInt32() < m_state
.variables().numberOfArguments() - 1) {
1398 forNode(node
) = m_state
.variables().argument(index
.asInt32() + 1);
1399 m_state
.setFoundConstants(true);
1405 if (inlineCallFrame
) {
1406 // We have a bound on the types even though it's random access. Take advantage of this.
1408 AbstractValue result
;
1409 for (unsigned i
= inlineCallFrame
->arguments
.size(); i
-- > 1;) {
1411 m_state
.variables().operand(
1412 virtualRegisterForArgument(i
) + inlineCallFrame
->stackOffset
));
1416 m_state
.setFoundConstants(true);
1417 forNode(node
) = result
;
1421 forNode(node
).makeHeapTop();
1426 forNode(node
).makeHeapTop();
1430 forNode(node
).setType(SpecBoolean
);
1437 Node
* child
= node
->child1().node();
1438 BooleanResult result
= booleanResult(node
, forNode(child
));
1439 if (result
== DefinitelyTrue
) {
1440 m_state
.setBranchDirection(TakeTrue
);
1443 if (result
== DefinitelyFalse
) {
1444 m_state
.setBranchDirection(TakeFalse
);
1447 // FIXME: The above handles the trivial cases of sparse conditional
1448 // constant propagation, but we can do better:
1449 // We can specialize the source variable's value on each direction of
1451 m_state
.setBranchDirection(TakeBoth
);
1456 // Nothing to do for now.
1457 // FIXME: Do sparse conditional things.
1462 m_state
.setIsValid(false);
1466 case ThrowReferenceError
:
1467 m_state
.setIsValid(false);
1471 JSValue childConst
= forNode(node
->child1()).value();
1472 if (childConst
&& childConst
.isNumber()) {
1473 setConstant(node
, childConst
);
1477 ASSERT(node
->child1().useKind() == UntypedUse
);
1479 if (!forNode(node
->child1()).m_type
) {
1480 m_state
.setIsValid(false);
1484 if (!(forNode(node
->child1()).m_type
& ~(SpecFullNumber
| SpecBoolean
| SpecString
| SpecSymbol
))) {
1485 m_state
.setFoundConstants(true);
1486 forNode(node
) = forNode(node
->child1());
1490 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1492 forNode(node
).setType(m_graph
, (SpecHeapTop
& ~SpecCell
) | SpecString
| SpecSymbol
);
1497 case CallStringConstructor
: {
1498 switch (node
->child1().useKind()) {
1499 case StringObjectUse
:
1500 // This also filters that the StringObject has the primordial StringObject
1504 m_graph
.globalObjectFor(node
->origin
.semantic
)->stringObjectStructure());
1506 case StringOrStringObjectUse
:
1510 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1513 RELEASE_ASSERT_NOT_REACHED();
1516 forNode(node
).set(m_graph
, m_graph
.m_vm
.stringStructure
.get());
1520 case NewStringObject
: {
1521 ASSERT(node
->structure()->classInfo() == StringObject::info());
1522 forNode(node
).set(m_graph
, node
->structure());
1529 m_graph
.globalObjectFor(node
->origin
.semantic
)->arrayStructureForIndexingTypeDuringAllocation(node
->indexingType()));
1532 case NewArrayBuffer
:
1535 m_graph
.globalObjectFor(node
->origin
.semantic
)->arrayStructureForIndexingTypeDuringAllocation(node
->indexingType()));
1538 case NewArrayWithSize
:
1539 forNode(node
).setType(m_graph
, SpecArray
);
1543 switch (node
->child1().useKind()) {
1547 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1550 RELEASE_ASSERT_NOT_REACHED();
1555 m_graph
.globalObjectFor(node
->origin
.semantic
)->typedArrayStructure(
1556 node
->typedArrayType()));
1560 forNode(node
).set(m_graph
, m_graph
.globalObjectFor(node
->origin
.semantic
)->regExpStructure());
1564 AbstractValue
& source
= forNode(node
->child1());
1565 AbstractValue
& destination
= forNode(node
);
1567 if (m_graph
.executableFor(node
->origin
.semantic
)->isStrictMode())
1568 destination
.makeHeapTop();
1570 destination
= source
;
1571 destination
.merge(SpecObject
);
1577 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
1578 forNode(node
).setType(m_graph
, SpecFinalObject
);
1583 ASSERT(node
->structure());
1584 forNode(node
).set(m_graph
, node
->structure());
1587 case PhantomNewObject
:
1588 case PhantomNewFunction
:
1589 case PhantomCreateActivation
:
1590 case PhantomDirectArguments
:
1591 case PhantomClonedArguments
:
1593 m_state
.setDidClobber(true); // Prevent constant folding.
1594 // This claims to return bottom.
1600 case MaterializeNewObject
: {
1603 m_phiChildren
->forAllTransitiveIncomingValues(
1604 m_graph
.varArgChild(node
, 0).node(),
1605 [&] (Node
* incoming
) {
1606 set
.add(incoming
->castConstant
<Structure
*>());
1609 forNode(node
).set(m_graph
, set
);
1613 case CreateActivation
:
1614 case MaterializeCreateActivation
:
1616 m_graph
, m_codeBlock
->globalObjectFor(node
->origin
.semantic
)->activationStructure());
1619 case CreateDirectArguments
:
1620 forNode(node
).set(m_graph
, m_codeBlock
->globalObjectFor(node
->origin
.semantic
)->directArgumentsStructure());
1623 case CreateScopedArguments
:
1624 forNode(node
).set(m_graph
, m_codeBlock
->globalObjectFor(node
->origin
.semantic
)->scopedArgumentsStructure());
1627 case CreateClonedArguments
:
1628 forNode(node
).setType(m_graph
, SpecObjectOther
);
1633 m_graph
, m_codeBlock
->globalObjectFor(node
->origin
.semantic
)->functionStructure());
1637 if (FunctionExecutable
* executable
= jsDynamicCast
<FunctionExecutable
*>(m_codeBlock
->ownerExecutable())) {
1638 InferredValue
* singleton
= executable
->singletonFunction();
1639 if (JSValue value
= singleton
->inferredValue()) {
1640 m_graph
.watchpoints().addLazily(singleton
);
1641 JSFunction
* function
= jsCast
<JSFunction
*>(value
);
1642 setConstant(node
, *m_graph
.freeze(function
));
1646 forNode(node
).setType(m_graph
, SpecFunction
);
1649 case GetArgumentCount
:
1650 forNode(node
).setType(SpecInt32
);
1654 JSValue base
= forNode(node
->child1()).m_value
;
1656 GetterSetter
* getterSetter
= jsCast
<GetterSetter
*>(base
);
1657 if (!getterSetter
->isGetterNull()) {
1658 setConstant(node
, *m_graph
.freeze(getterSetter
->getterConcurrently()));
1663 forNode(node
).setType(m_graph
, SpecObject
);
1668 JSValue base
= forNode(node
->child1()).m_value
;
1670 GetterSetter
* getterSetter
= jsCast
<GetterSetter
*>(base
);
1671 if (!getterSetter
->isSetterNull()) {
1672 setConstant(node
, *m_graph
.freeze(getterSetter
->setterConcurrently()));
1677 forNode(node
).setType(m_graph
, SpecObject
);
1682 if (JSValue base
= forNode(node
->child1()).m_value
) {
1683 if (JSFunction
* function
= jsDynamicCast
<JSFunction
*>(base
)) {
1684 setConstant(node
, *m_graph
.freeze(function
->scope()));
1688 forNode(node
).setType(m_graph
, SpecObjectOther
);
1692 JSValue child
= forNode(node
->child1()).value();
1694 setConstant(node
, *m_graph
.freeze(JSValue(jsCast
<JSScope
*>(child
.asCell())->next())));
1697 forNode(node
).setType(m_graph
, SpecObjectOther
);
1702 if (JSValue value
= m_graph
.tryGetConstantClosureVar(forNode(node
->child1()), node
->scopeOffset())) {
1703 setConstant(node
, *m_graph
.freeze(value
));
1706 forNode(node
).makeHeapTop();
1712 case GetFromArguments
:
1713 forNode(node
).makeHeapTop();
1716 case PutToArguments
:
1720 case GetByIdFlush
: {
1721 if (!node
->prediction()) {
1722 m_state
.setIsValid(false);
1726 AbstractValue
& value
= forNode(node
->child1());
1727 if (!value
.m_structure
.isTop() && !value
.m_structure
.isClobbered()
1728 && (node
->child1().useKind() == CellUse
|| !(value
.m_type
& ~SpecCell
))) {
1729 GetByIdStatus status
= GetByIdStatus::computeFor(
1730 value
.m_structure
.set(), m_graph
.identifiers()[node
->identifierNumber()]);
1731 if (status
.isSimple()) {
1732 // Figure out what the result is going to be - is it TOP, a constant, or maybe
1733 // something more subtle?
1734 AbstractValue result
;
1735 for (unsigned i
= status
.numVariants(); i
--;) {
1736 DFG_ASSERT(m_graph
, node
, !status
[i
].alternateBase());
1737 JSValue constantResult
=
1738 m_graph
.tryGetConstantProperty(value
, status
[i
].offset());
1739 if (!constantResult
) {
1740 result
.makeHeapTop();
1744 AbstractValue thisResult
;
1746 m_graph
, *m_graph
.freeze(constantResult
),
1747 m_state
.structureClobberState());
1748 result
.merge(thisResult
);
1750 if (status
.numVariants() == 1 || isFTL(m_graph
.m_plan
.mode
))
1751 m_state
.setFoundConstants(true);
1752 forNode(node
) = result
;
1757 clobberWorld(node
->origin
.semantic
, clobberLimit
);
1758 forNode(node
).makeHeapTop();
1762 case GetArrayLength
: {
1763 JSArrayBufferView
* view
= m_graph
.tryGetFoldableView(
1764 forNode(node
->child1()).m_value
, node
->arrayMode());
1766 setConstant(node
, jsNumber(view
->length()));
1769 forNode(node
).setType(SpecInt32
);
1773 case CheckStructure
: {
1774 AbstractValue
& value
= forNode(node
->child1());
1775 ASSERT(!(value
.m_type
& ~SpecCell
)); // Edge filtering should have already ensured this.
1777 StructureSet
& set
= node
->structureSet();
1779 // It's interesting that we could have proven that the object has a larger structure set
1780 // that includes the set we're testing. In that case we could make the structure check
1781 // more efficient. We currently don't.
1783 if (value
.m_structure
.isSubsetOf(set
)) {
1784 m_state
.setFoundConstants(true);
1792 case CheckStructureImmediate
: {
1793 // FIXME: This currently can only reason about one structure at a time.
1794 // https://bugs.webkit.org/show_bug.cgi?id=136988
1796 AbstractValue
& value
= forNode(node
->child1());
1797 StructureSet
& set
= node
->structureSet();
1799 if (value
.value()) {
1800 if (Structure
* structure
= jsDynamicCast
<Structure
*>(value
.value())) {
1801 if (set
.contains(structure
)) {
1802 m_state
.setFoundConstants(true);
1806 m_state
.setIsValid(false);
1810 if (m_phiChildren
) {
1811 bool allGood
= true;
1812 m_phiChildren
->forAllTransitiveIncomingValues(
1814 [&] (Node
* incoming
) {
1815 if (Structure
* structure
= incoming
->dynamicCastConstant
<Structure
*>()) {
1816 if (set
.contains(structure
))
1822 m_state
.setFoundConstants(true);
1827 if (Structure
* structure
= set
.onlyStructure()) {
1828 filterByValue(node
->child1(), *m_graph
.freeze(structure
));
1832 // Aw shucks, we can't do anything!
1837 if (!forNode(node
->child1()).m_structure
.isClear()) {
1838 if (forNode(node
->child1()).m_structure
.onlyStructure() == node
->transition()->next
)
1839 m_state
.setFoundConstants(true);
1842 clobberLimit
, node
->transition()->previous
, node
->transition()->next
);
1843 forNode(node
->child1()).changeStructure(m_graph
, node
->transition()->next
);
1848 case AllocatePropertyStorage
:
1849 case ReallocatePropertyStorage
:
1850 forNode(node
).clear(); // The result is not a JS value.
1853 if (node
->arrayMode().alreadyChecked(m_graph
, node
, forNode(node
->child1()))) {
1854 m_state
.setFoundConstants(true);
1857 switch (node
->arrayMode().type()) {
1859 filter(node
->child1(), SpecString
);
1863 case Array::Contiguous
:
1864 case Array::ArrayStorage
:
1865 case Array::SlowPutArrayStorage
:
1867 case Array::DirectArguments
:
1868 filter(node
->child1(), SpecDirectArguments
);
1870 case Array::ScopedArguments
:
1871 filter(node
->child1(), SpecScopedArguments
);
1873 case Array::Int8Array
:
1874 filter(node
->child1(), SpecInt8Array
);
1876 case Array::Int16Array
:
1877 filter(node
->child1(), SpecInt16Array
);
1879 case Array::Int32Array
:
1880 filter(node
->child1(), SpecInt32Array
);
1882 case Array::Uint8Array
:
1883 filter(node
->child1(), SpecUint8Array
);
1885 case Array::Uint8ClampedArray
:
1886 filter(node
->child1(), SpecUint8ClampedArray
);
1888 case Array::Uint16Array
:
1889 filter(node
->child1(), SpecUint16Array
);
1891 case Array::Uint32Array
:
1892 filter(node
->child1(), SpecUint32Array
);
1894 case Array::Float32Array
:
1895 filter(node
->child1(), SpecFloat32Array
);
1897 case Array::Float64Array
:
1898 filter(node
->child1(), SpecFloat64Array
);
1901 RELEASE_ASSERT_NOT_REACHED();
1904 filterArrayModes(node
->child1(), node
->arrayMode().arrayModesThatPassFiltering());
1908 if (node
->arrayMode().alreadyChecked(m_graph
, node
, forNode(node
->child1()))) {
1909 m_state
.setFoundConstants(true);
1912 ASSERT(node
->arrayMode().conversion() == Array::Convert
);
1913 clobberStructures(clobberLimit
);
1914 filterArrayModes(node
->child1(), node
->arrayMode().arrayModesThatPassFiltering());
1917 case ArrayifyToStructure
: {
1918 AbstractValue
& value
= forNode(node
->child1());
1919 if (value
.m_structure
.isSubsetOf(StructureSet(node
->structure())))
1920 m_state
.setFoundConstants(true);
1921 clobberStructures(clobberLimit
);
1923 // We have a bunch of options of how to express the abstract set at this point. Let set S
1924 // be the set of structures that the value had before clobbering and assume that all of
1925 // them are watchable. The new value should be the least expressible upper bound of the
1926 // intersection of "values that currently have structure = node->structure()" and "values
1927 // that have structure in S plus any structure transition-reachable from S". Assume that
1928 // node->structure() is not in S but it is transition-reachable from S. Then we would
1929 // like to say that the result is "values that have structure = node->structure() until
1930 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
1931 // we must choose between:
1933 // 1) "values that currently have structure = node->structure()". This is a valid
1934 // superset of the value that we really want, and it's specific enough to satisfy the
1935 // preconditions of the array access that this is guarding. It's also specific enough
1936 // to allow relevant optimizations in the case that we didn't have a contradiction
1937 // like in this example. Notice that in the abscence of any contradiction, this result
1938 // is precise rather than being a conservative LUB.
1940 // 2) "values that currently hava structure in S plus any structure transition-reachable
1941 // from S". This is also a valid superset of the value that we really want, but it's
1942 // not specific enough to satisfy the preconditions of the array access that this is
1943 // guarding - so playing such shenanigans would preclude us from having assertions on
1944 // the typing preconditions of any array accesses. This would also not be a desirable
1945 // answer in the absence of a contradiction.
1947 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
1948 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
1950 value
.set(m_graph
, node
->structure());
1953 case GetIndexedPropertyStorage
: {
1954 JSArrayBufferView
* view
= m_graph
.tryGetFoldableView(
1955 forNode(node
->child1()).m_value
, node
->arrayMode());
1957 m_state
.setFoundConstants(true);
1958 forNode(node
).clear();
1961 case ConstantStoragePointer
: {
1962 forNode(node
).clear();
1966 case GetTypedArrayByteOffset
: {
1967 JSArrayBufferView
* view
= m_graph
.tryGetFoldableView(forNode(node
->child1()).m_value
);
1969 setConstant(node
, jsNumber(view
->byteOffset()));
1972 forNode(node
).setType(SpecInt32
);
1977 StorageAccessData
& data
= node
->storageAccessData();
1978 JSValue result
= m_graph
.tryGetConstantProperty(forNode(node
->child2()), data
.offset
);
1980 setConstant(node
, *m_graph
.freeze(result
));
1984 forNode(node
).makeHeapTop();
1988 case GetGetterSetterByOffset
: {
1989 StorageAccessData
& data
= node
->storageAccessData();
1990 JSValue result
= m_graph
.tryGetConstantProperty(forNode(node
->child2()), data
.offset
);
1991 if (result
&& jsDynamicCast
<GetterSetter
*>(result
)) {
1992 setConstant(node
, *m_graph
.freeze(result
));
1996 forNode(node
).set(m_graph
, m_graph
.m_vm
.getterSetterStructure
.get());
2000 case MultiGetByOffset
: {
2001 // This code will filter the base value in a manner that is possibly different (either more
2002 // or less precise) than the way it would be filtered if this was strength-reduced to a
2003 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2004 // different things about the code, so long as all of them are sound. That even includes
2005 // one guy proving that code should never execute (due to a contradiction) and another guy
2006 // not finding that contradiction. If someone ever proved that there would be a
2007 // contradiction then there must always be a contradiction even if subsequent passes don't
2008 // realize it. This is the case here.
2010 // Ordinarily you have to be careful with calling setFoundConstants()
2011 // because of the effect on compile times, but this node is FTL-only.
2012 m_state
.setFoundConstants(true);
2014 AbstractValue base
= forNode(node
->child1());
2015 StructureSet baseSet
;
2016 AbstractValue result
;
2017 for (unsigned i
= node
->multiGetByOffsetData().variants
.size(); i
--;) {
2018 GetByIdVariant
& variant
= node
->multiGetByOffsetData().variants
[i
];
2019 StructureSet set
= variant
.structureSet();
2025 JSValue baseForLoad
;
2026 if (variant
.alternateBase())
2027 baseForLoad
= variant
.alternateBase();
2029 baseForLoad
= base
.m_value
;
2030 JSValue constantResult
=
2031 m_graph
.tryGetConstantProperty(
2032 baseForLoad
, variant
.baseStructure(), variant
.offset());
2033 if (!constantResult
) {
2034 result
.makeHeapTop();
2037 AbstractValue thisResult
;
2040 *m_graph
.freeze(constantResult
),
2041 m_state
.structureClobberState());
2042 result
.merge(thisResult
);
2045 if (forNode(node
->child1()).changeStructure(m_graph
, baseSet
) == Contradiction
)
2046 m_state
.setIsValid(false);
2048 forNode(node
) = result
;
2056 case MultiPutByOffset
: {
2057 StructureSet newSet
;
2058 TransitionVector transitions
;
2060 // Ordinarily you have to be careful with calling setFoundConstants()
2061 // because of the effect on compile times, but this node is FTL-only.
2062 m_state
.setFoundConstants(true);
2064 AbstractValue base
= forNode(node
->child1());
2066 for (unsigned i
= node
->multiPutByOffsetData().variants
.size(); i
--;) {
2067 const PutByIdVariant
& variant
= node
->multiPutByOffsetData().variants
[i
];
2068 StructureSet thisSet
= variant
.oldStructure();
2069 thisSet
.filter(base
);
2070 if (thisSet
.isEmpty())
2072 if (variant
.kind() == PutByIdVariant::Transition
) {
2073 if (thisSet
.onlyStructure() != variant
.newStructure()) {
2075 Transition(variant
.oldStructureForTransition(), variant
.newStructure()));
2076 } // else this is really a replace.
2077 newSet
.add(variant
.newStructure());
2079 ASSERT(variant
.kind() == PutByIdVariant::Replace
);
2080 newSet
.merge(thisSet
);
2084 observeTransitions(clobberLimit
, transitions
);
2085 if (forNode(node
->child1()).changeStructure(m_graph
, newSet
) == Contradiction
)
2086 m_state
.setIsValid(false);
2090 case GetExecutable
: {
2091 JSValue value
= forNode(node
->child1()).value();
2093 JSFunction
* function
= jsDynamicCast
<JSFunction
*>(value
);
2095 setConstant(node
, *m_graph
.freeze(function
->executable()));
2099 forNode(node
).setType(m_graph
, SpecCellOther
);
2104 JSValue value
= forNode(node
->child1()).value();
2105 if (value
== node
->cellOperand()->value()) {
2106 m_state
.setFoundConstants(true);
2110 filterByValue(node
->child1(), *node
->cellOperand());
2114 case CheckNotEmpty
: {
2115 AbstractValue
& value
= forNode(node
->child1());
2116 if (!(value
.m_type
& SpecEmpty
)) {
2117 m_state
.setFoundConstants(true);
2121 filter(value
, ~SpecEmpty
);
2125 case CheckInBounds
: {
2126 JSValue left
= forNode(node
->child1()).value();
2127 JSValue right
= forNode(node
->child2()).value();
2128 if (left
&& right
&& left
.isInt32() && right
.isInt32()
2129 && static_cast<uint32_t>(left
.asInt32()) < static_cast<uint32_t>(right
.asInt32())) {
2130 m_state
.setFoundConstants(true);
2138 case PutByIdDirect
: {
2139 AbstractValue
& value
= forNode(node
->child1());
2140 if (!value
.m_structure
.isTop() && !value
.m_structure
.isClobbered()) {
2141 PutByIdStatus status
= PutByIdStatus::computeFor(
2142 m_graph
.globalObjectFor(node
->origin
.semantic
),
2143 value
.m_structure
.set(),
2144 m_graph
.identifiers()[node
->identifierNumber()],
2145 node
->op() == PutByIdDirect
);
2147 if (status
.isSimple()) {
2148 StructureSet newSet
;
2149 TransitionVector transitions
;
2151 for (unsigned i
= status
.numVariants(); i
--;) {
2152 const PutByIdVariant
& variant
= status
[i
];
2153 if (variant
.kind() == PutByIdVariant::Transition
) {
2156 variant
.oldStructureForTransition(), variant
.newStructure()));
2157 m_graph
.registerStructure(variant
.newStructure());
2158 newSet
.add(variant
.newStructure());
2160 ASSERT(variant
.kind() == PutByIdVariant::Replace
);
2161 newSet
.merge(variant
.oldStructure());
2165 if (status
.numVariants() == 1 || isFTL(m_graph
.m_plan
.mode
))
2166 m_state
.setFoundConstants(true);
2168 observeTransitions(clobberLimit
, transitions
);
2169 if (forNode(node
->child1()).changeStructure(m_graph
, newSet
) == Contradiction
)
2170 m_state
.setIsValid(false);
2175 clobberWorld(node
->origin
.semantic
, clobberLimit
);
2180 // FIXME: We can determine when the property definitely exists based on abstract
2181 // value information.
2182 clobberWorld(node
->origin
.semantic
, clobberLimit
);
2183 forNode(node
).setType(SpecBoolean
);
2187 case GetEnumerableLength
: {
2188 forNode(node
).setType(SpecInt32
);
2191 case HasGenericProperty
: {
2192 forNode(node
).setType(SpecBoolean
);
2195 case HasStructureProperty
: {
2196 forNode(node
).setType(SpecBoolean
);
2199 case HasIndexedProperty
: {
2200 ArrayMode mode
= node
->arrayMode();
2201 switch (mode
.type()) {
2204 case Array::Contiguous
:
2205 case Array::ArrayStorage
: {
2209 clobberWorld(node
->origin
.semantic
, clobberLimit
);
2213 forNode(node
).setType(SpecBoolean
);
2216 case GetDirectPname
: {
2217 clobberWorld(node
->origin
.semantic
, clobberLimit
);
2218 forNode(node
).makeHeapTop();
2221 case GetPropertyEnumerator
: {
2222 forNode(node
).setType(m_graph
, SpecCell
);
2225 case GetEnumeratorStructurePname
: {
2226 forNode(node
).setType(m_graph
, SpecString
| SpecOther
);
2229 case GetEnumeratorGenericPname
: {
2230 forNode(node
).setType(m_graph
, SpecString
| SpecOther
);
2233 case ToIndexString
: {
2234 forNode(node
).setType(m_graph
, SpecString
);
2239 forNode(node
).makeHeapTop();
2242 case VarInjectionWatchpoint
:
2247 case CheckHasInstance
:
2248 // Sadly, we don't propagate the fact that we've done CheckHasInstance
2252 // Again, sadly, we don't propagate the fact that we've done InstanceOf
2253 forNode(node
).setType(SpecBoolean
);
2257 RELEASE_ASSERT(m_graph
.m_form
== SSA
);
2258 // The state of this node would have already been decided, but it may have become a
2259 // constant, in which case we'd like to know.
2260 if (forNode(node
).m_value
)
2261 m_state
.setFoundConstants(true);
2265 m_state
.createValueForNode(node
->phi());
2266 forNode(node
->phi()) = forNode(node
->child1());
2277 case NativeConstruct
:
2279 case CallForwardVarargs
:
2280 case ConstructVarargs
:
2281 case ConstructForwardVarargs
:
2282 clobberWorld(node
->origin
.semantic
, clobberLimit
);
2283 forNode(node
).makeHeapTop();
2288 m_state
.setIsValid(false);
2291 case InvalidationPoint
:
2292 forAllValues(clobberLimit
, AbstractValue::observeInvalidationPointFor
);
2293 m_state
.setStructureClobberState(StructuresAreWatched
);
2296 case CheckWatchdogTimer
:
2300 case ProfileWillCall
:
2301 case ProfileDidCall
:
2303 case ProfileControlFlow
:
2305 case CountExecution
:
2306 case CheckTierUpInLoop
:
2307 case CheckTierUpAtReturn
:
2311 // Simplify out checks that don't actually do checking.
2312 for (unsigned i
= 0; i
< AdjacencyList::Size
; ++i
) {
2313 Edge edge
= node
->children
.child(i
);
2316 if (edge
.isProved() || edge
.willNotHaveCheck()) {
2317 m_state
.setFoundConstants(true);
2324 case StoreBarrier
: {
2325 filter(node
->child1(), SpecCell
);
2329 case CheckTierUpAndOSREnter
:
2330 case CheckTierUpWithNestedTriggerAndOSREnter
:
2339 DFG_CRASH(m_graph
, node
, "Unexpected node type");
2343 return m_state
.isValid();
2346 template<typename AbstractStateType
>
2347 bool AbstractInterpreter
<AbstractStateType
>::executeEffects(unsigned indexInBlock
)
2349 return executeEffects(indexInBlock
, m_state
.block()->at(indexInBlock
));
2352 template<typename AbstractStateType
>
2353 bool AbstractInterpreter
<AbstractStateType
>::execute(unsigned indexInBlock
)
2355 Node
* node
= m_state
.block()->at(indexInBlock
);
2359 return executeEffects(indexInBlock
, node
);
2362 template<typename AbstractStateType
>
2363 bool AbstractInterpreter
<AbstractStateType
>::execute(Node
* node
)
2367 return executeEffects(UINT_MAX
, node
);
2370 template<typename AbstractStateType
>
2371 void AbstractInterpreter
<AbstractStateType
>::clobberWorld(
2372 const CodeOrigin
&, unsigned clobberLimit
)
2374 clobberStructures(clobberLimit
);
2377 template<typename AbstractStateType
>
2378 template<typename Functor
>
2379 void AbstractInterpreter
<AbstractStateType
>::forAllValues(
2380 unsigned clobberLimit
, Functor
& functor
)
2382 SamplingRegion
samplingRegion("DFG AI For All Values");
2383 if (clobberLimit
>= m_state
.block()->size())
2384 clobberLimit
= m_state
.block()->size();
2387 ASSERT(clobberLimit
<= m_state
.block()->size());
2388 for (size_t i
= clobberLimit
; i
--;)
2389 functor(forNode(m_state
.block()->at(i
)));
2390 if (m_graph
.m_form
== SSA
) {
2391 HashSet
<Node
*>::iterator iter
= m_state
.block()->ssa
->liveAtHead
.begin();
2392 HashSet
<Node
*>::iterator end
= m_state
.block()->ssa
->liveAtHead
.end();
2393 for (; iter
!= end
; ++iter
)
2394 functor(forNode(*iter
));
2396 for (size_t i
= m_state
.variables().numberOfArguments(); i
--;)
2397 functor(m_state
.variables().argument(i
));
2398 for (size_t i
= m_state
.variables().numberOfLocals(); i
--;)
2399 functor(m_state
.variables().local(i
));
2402 template<typename AbstractStateType
>
2403 void AbstractInterpreter
<AbstractStateType
>::clobberStructures(unsigned clobberLimit
)
2405 SamplingRegion
samplingRegion("DFG AI Clobber Structures");
2406 forAllValues(clobberLimit
, AbstractValue::clobberStructuresFor
);
2410 template<typename AbstractStateType
>
2411 void AbstractInterpreter
<AbstractStateType
>::observeTransition(
2412 unsigned clobberLimit
, Structure
* from
, Structure
* to
)
2414 AbstractValue::TransitionObserver
transitionObserver(from
, to
);
2415 forAllValues(clobberLimit
, transitionObserver
);
2417 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.
2420 template<typename AbstractStateType
>
2421 void AbstractInterpreter
<AbstractStateType
>::observeTransitions(
2422 unsigned clobberLimit
, const TransitionVector
& vector
)
2424 AbstractValue::TransitionsObserver
transitionsObserver(vector
);
2425 forAllValues(clobberLimit
, transitionsObserver
);
2427 if (!ASSERT_DISABLED
) {
2428 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2429 for (unsigned i
= vector
.size(); i
--;)
2430 ASSERT(!vector
[i
].previous
->dfgShouldWatch());
2434 template<typename AbstractStateType
>
2435 void AbstractInterpreter
<AbstractStateType
>::setDidClobber()
2437 m_state
.setDidClobber(true);
2438 m_state
.setStructureClobberState(StructuresAreClobbered
);
2441 template<typename AbstractStateType
>
2442 void AbstractInterpreter
<AbstractStateType
>::dump(PrintStream
& out
) const
2444 const_cast<AbstractInterpreter
<AbstractStateType
>*>(this)->dump(out
);
2447 template<typename AbstractStateType
>
2448 void AbstractInterpreter
<AbstractStateType
>::dump(PrintStream
& out
)
2450 CommaPrinter
comma(" ");
2451 HashSet
<Node
*> seen
;
2452 if (m_graph
.m_form
== SSA
) {
2453 HashSet
<Node
*>::iterator iter
= m_state
.block()->ssa
->liveAtHead
.begin();
2454 HashSet
<Node
*>::iterator end
= m_state
.block()->ssa
->liveAtHead
.end();
2455 for (; iter
!= end
; ++iter
) {
2458 AbstractValue
& value
= forNode(node
);
2459 if (value
.isClear())
2461 out
.print(comma
, node
, ":", value
);
2464 for (size_t i
= 0; i
< m_state
.block()->size(); ++i
) {
2465 Node
* node
= m_state
.block()->at(i
);
2467 AbstractValue
& value
= forNode(node
);
2468 if (value
.isClear())
2470 out
.print(comma
, node
, ":", value
);
2472 if (m_graph
.m_form
== SSA
) {
2473 HashSet
<Node
*>::iterator iter
= m_state
.block()->ssa
->liveAtTail
.begin();
2474 HashSet
<Node
*>::iterator end
= m_state
.block()->ssa
->liveAtTail
.end();
2475 for (; iter
!= end
; ++iter
) {
2477 if (seen
.contains(node
))
2479 AbstractValue
& value
= forNode(node
);
2480 if (value
.isClear())
2482 out
.print(comma
, node
, ":", value
);
2487 template<typename AbstractStateType
>
2488 FiltrationResult AbstractInterpreter
<AbstractStateType
>::filter(
2489 AbstractValue
& value
, const StructureSet
& set
)
2491 if (value
.filter(m_graph
, set
) == FiltrationOK
)
2492 return FiltrationOK
;
2493 m_state
.setIsValid(false);
2494 return Contradiction
;
2497 template<typename AbstractStateType
>
2498 FiltrationResult AbstractInterpreter
<AbstractStateType
>::filterArrayModes(
2499 AbstractValue
& value
, ArrayModes arrayModes
)
2501 if (value
.filterArrayModes(arrayModes
) == FiltrationOK
)
2502 return FiltrationOK
;
2503 m_state
.setIsValid(false);
2504 return Contradiction
;
2507 template<typename AbstractStateType
>
2508 FiltrationResult AbstractInterpreter
<AbstractStateType
>::filter(
2509 AbstractValue
& value
, SpeculatedType type
)
2511 if (value
.filter(type
) == FiltrationOK
)
2512 return FiltrationOK
;
2513 m_state
.setIsValid(false);
2514 return Contradiction
;
2517 template<typename AbstractStateType
>
2518 FiltrationResult AbstractInterpreter
<AbstractStateType
>::filterByValue(
2519 AbstractValue
& abstractValue
, FrozenValue concreteValue
)
2521 if (abstractValue
.filterByValue(concreteValue
) == FiltrationOK
)
2522 return FiltrationOK
;
2523 m_state
.setIsValid(false);
2524 return Contradiction
;
2527 } } // namespace JSC::DFG
2529 #endif // ENABLE(DFG_JIT)
2531 #endif // DFGAbstractInterpreterInlines_h