1/*
2 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "ArrayConstructor.h"
31#include "ArrayPrototype.h"
32#include "DFGAbstractInterpreter.h"
33#include "DFGAbstractInterpreterClobberState.h"
34#include "DOMJITGetterSetter.h"
35#include "DOMJITSignature.h"
36#include "GetByIdStatus.h"
37#include "GetterSetter.h"
38#include "HashMapImpl.h"
39#include "JITOperations.h"
40#include "JSImmutableButterfly.h"
41#include "MathCommon.h"
42#include "NumberConstructor.h"
43#include "Operations.h"
44#include "PutByIdStatus.h"
45#include "StringObject.h"
46#include "StructureCache.h"
47#include "StructureRareDataInlines.h"
48#include <wtf/BooleanLattice.h>
49#include <wtf/CheckedArithmetic.h>
50
51namespace JSC { namespace DFG {
52
53template<typename AbstractStateType>
54AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
55 : m_codeBlock(graph.m_codeBlock)
56 , m_graph(graph)
57 , m_vm(m_graph.m_vm)
58 , m_state(state)
59{
60 if (m_graph.m_form == SSA)
61 m_phiChildren = std::make_unique<PhiChildren>(m_graph);
62}
63
64template<typename AbstractStateType>
65AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
66{
67}
68
69template<typename AbstractStateType>
70typename AbstractInterpreter<AbstractStateType>::BooleanResult
71AbstractInterpreter<AbstractStateType>::booleanResult(
72 Node* node, AbstractValue& value)
73{
74 JSValue childConst = value.value();
75 if (childConst) {
76 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
77 return DefinitelyTrue;
78 return DefinitelyFalse;
79 }
80
81 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
82 if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
83 bool allTrue = true;
84 for (unsigned i = value.m_structure.size(); i--;) {
85 RegisteredStructure structure = value.m_structure[i];
86 if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
87 || structure->typeInfo().type() == StringType) {
88 allTrue = false;
89 break;
90 }
91 }
92 if (allTrue)
93 return DefinitelyTrue;
94 }
95
96 return UnknownBooleanResult;
97}
98
99template<typename AbstractStateType>
100void AbstractInterpreter<AbstractStateType>::startExecuting()
101{
102 ASSERT(m_state.block());
103 ASSERT(m_state.isValid());
104
105 m_state.setClobberState(AbstractInterpreterClobberState::NotClobbered);
106}
107
108template<typename AbstractStateType>
109class AbstractInterpreterExecuteEdgesFunc {
110public:
111 AbstractInterpreterExecuteEdgesFunc(AbstractInterpreter<AbstractStateType>& interpreter)
112 : m_interpreter(interpreter)
113 {
114 }
115
116 // This func is manually written out so that we can put ALWAYS_INLINE on it.
117 ALWAYS_INLINE void operator()(Edge& edge) const
118 {
119 m_interpreter.filterEdgeByUse(edge);
120 }
121
122private:
123 AbstractInterpreter<AbstractStateType>& m_interpreter;
124};
125
126template<typename AbstractStateType>
127void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
128{
129 m_graph.doToChildren(node, AbstractInterpreterExecuteEdgesFunc<AbstractStateType>(*this));
130}
131
132template<typename AbstractStateType>
133void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
134{
135 // Some use kinds are required to not have checks, because we know somehow that the incoming
136 // value will already have the type we want. In those cases, AI may not be smart enough to
137 // prove that this is indeed the case. But the existance of the edge is enough to prove that
138 // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
139 // and FTL backends may emit checks in a node that lacks a valid exit origin.
140 m_graph.doToChildren(
141 node,
142 [&] (Edge& edge) {
143 if (mayHaveTypeCheck(edge.useKind()))
144 return;
145
146 filterEdgeByUse(edge);
147 });
148}
149
150template<typename AbstractStateType>
151ALWAYS_INLINE void AbstractInterpreter<AbstractStateType>::filterByType(Edge& edge, SpeculatedType type)
152{
153 AbstractValue& value = m_state.forNodeWithoutFastForward(edge);
154 if (value.isType(type)) {
155 m_state.setProofStatus(edge, IsProved);
156 return;
157 }
158 m_state.setProofStatus(edge, NeedsCheck);
159 m_state.fastForwardAndFilterUnproven(value, type);
160}
161
162template<typename AbstractStateType>
163void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
164{
165 if (!(m_state.forNodeWithoutFastForward(edge).m_type & ~typeFilterFor(edge.useKind())))
166 return;
167
168 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(), AbstractInterpreterInvalidType, node->op(), edge->op(), edge.useKind(), forNode(edge).m_type);
169}
170
171template<typename AbstractStateType>
172void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
173{
174 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
175}
176
177enum class ToThisResult {
178 Identity,
179 Undefined,
180 GlobalThis,
181 Dynamic,
182};
183inline ToThisResult isToThisAnIdentity(VM& vm, bool isStrictMode, AbstractValue& valueForNode)
184{
185 // We look at the type first since that will cover most cases and does not require iterating all the structures.
186 if (isStrictMode) {
187 if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
188 return ToThisResult::Identity;
189 } else {
190 if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
191 return ToThisResult::Identity;
192 }
193
194 if (JSValue value = valueForNode.value()) {
195 if (value.isCell()) {
196 auto* toThisMethod = value.asCell()->classInfo(vm)->methodTable.toThis;
197 if (toThisMethod == &JSObject::toThis)
198 return ToThisResult::Identity;
199 if (toThisMethod == &JSScope::toThis) {
200 if (isStrictMode)
201 return ToThisResult::Undefined;
202 return ToThisResult::GlobalThis;
203 }
204 }
205 }
206
207 if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
208 bool allStructuresAreJSScope = !valueForNode.m_structure.isClear();
209 bool overridesToThis = false;
210 valueForNode.m_structure.forEach([&](RegisteredStructure structure) {
211 TypeInfo type = structure->typeInfo();
212 ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType || type.type() == BigIntType);
213 if (!isStrictMode)
214 ASSERT(type.isObject());
215 // We don't need to worry about strings/symbols here since either:
216 // 1) We are in strict mode and strings/symbols are not wrapped
217 // 2) The AI has proven that the type of this is a subtype of object
218 if (type.isObject() && type.overridesToThis())
219 overridesToThis = true;
220
221 // If all the structures are JSScope's ones, we know the details of JSScope::toThis() operation.
222 allStructuresAreJSScope &= structure->classInfo()->methodTable.toThis == JSScope::info()->methodTable.toThis;
223 });
224 if (!overridesToThis)
225 return ToThisResult::Identity;
226 if (allStructuresAreJSScope) {
227 if (isStrictMode)
228 return ToThisResult::Undefined;
229 return ToThisResult::GlobalThis;
230 }
231 }
232
233 return ToThisResult::Dynamic;
234}
235
236template<typename AbstractStateType>
237bool AbstractInterpreter<AbstractStateType>::handleConstantDivOp(Node* node)
238{
239 JSValue left = forNode(node->child1()).value();
240 JSValue right = forNode(node->child2()).value();
241
242 if (left && right) {
243 NodeType op = node->op();
244 bool isDivOperation = op == ValueDiv || op == ArithDiv;
245
246 // Only possible case of ValueOp below is UntypedUse,
247 // so we need to reflect clobberize rules.
248 bool isClobbering = op == ValueDiv || op == ValueMod;
249
250 if (left.isInt32() && right.isInt32()) {
251 double doubleResult;
252 if (isDivOperation)
253 doubleResult = left.asNumber() / right.asNumber();
254 else
255 doubleResult = fmod(left.asNumber(), right.asNumber());
256
257 if (node->hasArithMode()) {
258 if (!shouldCheckOverflow(node->arithMode()))
259 doubleResult = toInt32(doubleResult);
260 else if (!shouldCheckNegativeZero(node->arithMode()))
261 doubleResult += 0; // Sanitizes zero.
262 }
263
264 JSValue valueResult = jsNumber(doubleResult);
265 if (valueResult.isInt32()) {
266 if (isClobbering)
267 didFoldClobberWorld();
268 setConstant(node, valueResult);
269 return true;
270 }
271 } else if (left.isNumber() && right.isNumber()) {
272 if (isClobbering)
273 didFoldClobberWorld();
274
275 if (isDivOperation)
276 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
277 else
278 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
279
280 return true;
281 }
282 }
283
284 return false;
285}
286
287template<typename AbstractStateType>
288bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
289{
290 verifyEdges(node);
291
292 m_state.createValueForNode(node);
293
294 switch (node->op()) {
295 case JSConstant:
296 case DoubleConstant:
297 case Int52Constant: {
298 setBuiltInConstant(node, *node->constant());
299 break;
300 }
301
302 case LazyJSConstant: {
303 LazyJSValue value = node->lazyJSValue();
304 switch (value.kind()) {
305 case LazyJSValue::KnownValue:
306 setConstant(node, value.value()->value());
307 break;
308 case LazyJSValue::SingleCharacterString:
309 case LazyJSValue::KnownStringImpl:
310 case LazyJSValue::NewStringImpl:
311 setTypeForNode(node, SpecString);
312 break;
313 }
314 break;
315 }
316
317 case IdentityWithProfile:
318 case Identity: {
319 setForNode(node, forNode(node->child1()));
320 if (forNode(node).value())
321 m_state.setFoundConstants(true);
322 break;
323 }
324
325 case ExtractCatchLocal:
326 case ExtractOSREntryLocal: {
327 makeBytecodeTopForNode(node);
328 break;
329 }
330
331 case GetLocal: {
332 VariableAccessData* variableAccessData = node->variableAccessData();
333 AbstractValue value = m_state.operand(variableAccessData->local().offset());
334 // The value in the local should already be checked.
335 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
336 if (value.value())
337 m_state.setFoundConstants(true);
338 setForNode(node, value);
339 break;
340 }
341
342 case GetStack: {
343 StackAccessData* data = node->stackAccessData();
344 AbstractValue value = m_state.operand(data->local);
345 // The value in the local should already be checked.
346 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
347 if (value.value())
348 m_state.setFoundConstants(true);
349 setForNode(node, value);
350 break;
351 }
352
353 case SetLocal: {
354 m_state.operand(node->local()) = forNode(node->child1());
355 break;
356 }
357
358 case PutStack: {
359 m_state.operand(node->stackAccessData()->local) = forNode(node->child1());
360 break;
361 }
362
363 case MovHint: {
364 // Don't need to do anything. A MovHint only informs us about what would have happened
365 // in bytecode, but this code is just concerned with what is actually happening during
366 // DFG execution.
367 break;
368 }
369
370 case KillStack: {
371 // This is just a hint telling us that the OSR state of the local is no longer inside the
372 // flushed data.
373 break;
374 }
375
376 case SetArgumentDefinitely:
377 case SetArgumentMaybe:
378 // Assert that the state of arguments has been set. SetArgumentDefinitely/SetArgumentMaybe means
379 // that someone set the argument values out-of-band, and currently this always means setting to a
380 // non-clear value.
381 ASSERT(!m_state.operand(node->local()).isClear());
382 break;
383
384 case InitializeEntrypointArguments: {
385 unsigned entrypointIndex = node->entrypointIndex();
386 const Vector<FlushFormat>& argumentFormats = m_graph.m_argumentFormats[entrypointIndex];
387 for (unsigned argument = 0; argument < argumentFormats.size(); ++argument) {
388 AbstractValue& value = m_state.argument(argument);
389 switch (argumentFormats[argument]) {
390 case FlushedInt32:
391 value.setNonCellType(SpecInt32Only);
392 break;
393 case FlushedBoolean:
394 value.setNonCellType(SpecBoolean);
395 break;
396 case FlushedCell:
397 value.setType(m_graph, SpecCellCheck);
398 break;
399 case FlushedJSValue:
400 value.makeBytecodeTop();
401 break;
402 default:
403 DFG_CRASH(m_graph, node, "Bad flush format for argument");
404 break;
405 }
406 }
407 break;
408 }
409
410 case LoadVarargs:
411 case ForwardVarargs: {
412 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
413 // itself into a straight-line sequence of GetStack/PutStack.
414 // https://bugs.webkit.org/show_bug.cgi?id=143071
415 switch (node->op()) {
416 case LoadVarargs:
417 clobberWorld();
418 break;
419 case ForwardVarargs:
420 break;
421 default:
422 DFG_CRASH(m_graph, node, "Bad opcode");
423 break;
424 }
425 LoadVarargsData* data = node->loadVarargsData();
426 m_state.operand(data->count).setNonCellType(SpecInt32Only);
427 for (unsigned i = data->limit - 1; i--;)
428 m_state.operand(data->start.offset() + i).makeHeapTop();
429 break;
430 }
431
432 case ValueBitNot: {
433 JSValue operand = forNode(node->child1()).value();
434 if (operand && operand.isInt32()) {
435 didFoldClobberWorld();
436 int32_t a = operand.asInt32();
437 setConstant(node, JSValue(~a));
438 break;
439 }
440
441 if (node->child1().useKind() == BigIntUse)
442 setTypeForNode(node, SpecBigInt);
443 else {
444 clobberWorld();
445 setTypeForNode(node, SpecInt32Only | SpecBigInt);
446 }
447
448 break;
449 }
450
451 case ArithBitNot: {
452 JSValue operand = forNode(node->child1()).value();
453 if (operand && operand.isInt32()) {
454 int32_t a = operand.asInt32();
455 setConstant(node, JSValue(~a));
456 break;
457 }
458
459 setNonCellTypeForNode(node, SpecInt32Only);
460 break;
461 }
462
463 case ValueBitXor:
464 case ValueBitAnd:
465 case ValueBitOr:
466 if (node->binaryUseKind() == BigIntUse)
467 setTypeForNode(node, SpecBigInt);
468 else {
469 clobberWorld();
470 setTypeForNode(node, SpecInt32Only | SpecBigInt);
471 }
472 break;
473
474 case ArithBitAnd:
475 case ArithBitOr:
476 case ArithBitXor:
477 case BitRShift:
478 case BitLShift:
479 case BitURShift: {
480 if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
481 clobberWorld();
482 setNonCellTypeForNode(node, SpecInt32Only);
483 break;
484 }
485
486 JSValue left = forNode(node->child1()).value();
487 JSValue right = forNode(node->child2()).value();
488 if (left && right && left.isInt32() && right.isInt32()) {
489 int32_t a = left.asInt32();
490 int32_t b = right.asInt32();
491 switch (node->op()) {
492 case ArithBitAnd:
493 setConstant(node, JSValue(a & b));
494 break;
495 case ArithBitOr:
496 setConstant(node, JSValue(a | b));
497 break;
498 case ArithBitXor:
499 setConstant(node, JSValue(a ^ b));
500 break;
501 case BitRShift:
502 setConstant(node, JSValue(a >> (static_cast<uint32_t>(b) & 0x1f)));
503 break;
504 case BitLShift:
505 setConstant(node, JSValue(a << (static_cast<uint32_t>(b) & 0x1f)));
506 break;
507 case BitURShift:
508 setConstant(node, JSValue(static_cast<int32_t>(static_cast<uint32_t>(a) >> (static_cast<uint32_t>(b) & 0x1f))));
509 break;
510 default:
511 RELEASE_ASSERT_NOT_REACHED();
512 break;
513 }
514 break;
515 }
516
517 if (node->op() == ArithBitAnd
518 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
519 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
520 setNonCellTypeForNode(node, SpecBoolInt32);
521 break;
522 }
523
524 setNonCellTypeForNode(node, SpecInt32Only);
525 break;
526 }
527
528 case UInt32ToNumber: {
529 JSValue child = forNode(node->child1()).value();
530 if (doesOverflow(node->arithMode())) {
531 if (enableInt52()) {
532 if (child && child.isAnyInt()) {
533 int64_t machineInt = child.asAnyInt();
534 setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
535 break;
536 }
537 setNonCellTypeForNode(node, SpecInt52Any);
538 break;
539 }
540 if (child && child.isInt32()) {
541 uint32_t value = child.asInt32();
542 setConstant(node, jsNumber(value));
543 break;
544 }
545 setNonCellTypeForNode(node, SpecAnyIntAsDouble);
546 break;
547 }
548 if (child && child.isInt32()) {
549 int32_t value = child.asInt32();
550 if (value >= 0) {
551 setConstant(node, jsNumber(value));
552 break;
553 }
554 }
555 setNonCellTypeForNode(node, SpecInt32Only);
556 break;
557 }
558
559 case BooleanToNumber: {
560 JSValue concreteValue = forNode(node->child1()).value();
561 if (concreteValue) {
562 if (concreteValue.isBoolean())
563 setConstant(node, jsNumber(concreteValue.asBoolean()));
564 else
565 setConstant(node, *m_graph.freeze(concreteValue));
566 break;
567 }
568 AbstractValue& value = forNode(node);
569 value = forNode(node->child1());
570 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
571 m_state.setFoundConstants(true);
572 if (value.m_type & SpecBoolean) {
573 value.merge(SpecBoolInt32);
574 value.filter(~SpecBoolean);
575 }
576 break;
577 }
578
579 case DoubleAsInt32: {
580 JSValue child = forNode(node->child1()).value();
581 if (child && child.isNumber()) {
582 double asDouble = child.asNumber();
583 int32_t asInt = JSC::toInt32(asDouble);
584 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
585 setConstant(node, JSValue(asInt));
586 break;
587 }
588 }
589 setNonCellTypeForNode(node, SpecInt32Only);
590 break;
591 }
592
593 case ValueToInt32: {
594 JSValue child = forNode(node->child1()).value();
595 if (child) {
596 if (child.isNumber()) {
597 if (child.isInt32())
598 setConstant(node, child);
599 else
600 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
601 break;
602 }
603 if (child.isBoolean()) {
604 setConstant(node, jsNumber(child.asBoolean()));
605 break;
606 }
607 if (child.isUndefinedOrNull()) {
608 setConstant(node, jsNumber(0));
609 break;
610 }
611 }
612
613 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
614 setNonCellTypeForNode(node, SpecBoolInt32);
615 break;
616 }
617
618 setNonCellTypeForNode(node, SpecInt32Only);
619 break;
620 }
621
622 case DoubleRep: {
623 JSValue child = forNode(node->child1()).value();
624 if (Optional<double> number = child.toNumberFromPrimitive()) {
625 setConstant(node, jsDoubleNumber(*number));
626 break;
627 }
628
629 SpeculatedType type = forNode(node->child1()).m_type;
630 switch (node->child1().useKind()) {
631 case NotCellUse: {
632 if (type & SpecOther) {
633 type &= ~SpecOther;
634 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
635 }
636 if (type & SpecBoolean) {
637 type &= ~SpecBoolean;
638 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
639 }
640 type &= SpecBytecodeNumber;
641 break;
642 }
643
644 case Int52RepUse:
645 case NumberUse:
646 case RealNumberUse:
647 break;
648
649 default:
650 RELEASE_ASSERT_NOT_REACHED();
651 }
652 setNonCellTypeForNode(node, type);
653 forNode(node).fixTypeForRepresentation(m_graph, node);
654 break;
655 }
656
657 case Int52Rep: {
658 JSValue child = forNode(node->child1()).value();
659 if (child && child.isAnyInt()) {
660 setConstant(node, child);
661 break;
662 }
663
664 setTypeForNode(node, forNode(node->child1()).m_type);
665 forNode(node).fixTypeForRepresentation(m_graph, node);
666 break;
667 }
668
669 case ValueRep: {
670 JSValue value = forNode(node->child1()).value();
671 if (value) {
672 setConstant(node, value);
673 break;
674 }
675
676 setTypeForNode(node, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
677 forNode(node).fixTypeForRepresentation(m_graph, node);
678 break;
679 }
680
681 case ValueSub:
682 case ValueAdd: {
683 DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == BigIntUse);
684 if (node->binaryUseKind() == BigIntUse)
685 setTypeForNode(node, SpecBigInt);
686 else {
687 clobberWorld();
688 setTypeForNode(node, SpecString | SpecBytecodeNumber | SpecBigInt);
689 }
690 break;
691 }
692
693 case StrCat: {
694 setTypeForNode(node, SpecString);
695 break;
696 }
697
698 case ArithAdd: {
699 JSValue left = forNode(node->child1()).value();
700 JSValue right = forNode(node->child2()).value();
701 switch (node->binaryUseKind()) {
702 case Int32Use:
703 if (left && right && left.isInt32() && right.isInt32()) {
704 if (!shouldCheckOverflow(node->arithMode())) {
705 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
706 break;
707 }
708 JSValue result = jsNumber(left.asNumber() + right.asNumber());
709 if (result.isInt32()) {
710 setConstant(node, result);
711 break;
712 }
713 }
714 setNonCellTypeForNode(node, SpecInt32Only);
715 break;
716 case Int52RepUse:
717 if (left && right && left.isAnyInt() && right.isAnyInt()) {
718 JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
719 if (result.isAnyInt()) {
720 setConstant(node, result);
721 break;
722 }
723 }
724 setNonCellTypeForNode(node, SpecInt52Any);
725 break;
726 case DoubleRepUse:
727 if (left && right && left.isNumber() && right.isNumber()) {
728 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
729 break;
730 }
731 setNonCellTypeForNode(node,
732 typeOfDoubleSum(
733 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
734 break;
735 default:
736 RELEASE_ASSERT_NOT_REACHED();
737 break;
738 }
739 break;
740 }
741
742 case AtomicsIsLockFree: {
743 if (node->child1().useKind() != Int32Use)
744 clobberWorld();
745 setNonCellTypeForNode(node, SpecBoolInt32);
746 break;
747 }
748
749 case ArithClz32: {
750 JSValue operand = forNode(node->child1()).value();
751 if (Optional<double> number = operand.toNumberFromPrimitive()) {
752 switch (node->child1().useKind()) {
753 case Int32Use:
754 case KnownInt32Use:
755 break;
756 default:
757 didFoldClobberWorld();
758 break;
759 }
760 uint32_t value = toUInt32(*number);
761 setConstant(node, jsNumber(clz(value)));
762 break;
763 }
764 switch (node->child1().useKind()) {
765 case Int32Use:
766 case KnownInt32Use:
767 break;
768 default:
769 clobberWorld();
770 break;
771 }
772 setNonCellTypeForNode(node, SpecInt32Only);
773 break;
774 }
775
776 case MakeRope: {
777 unsigned numberOfRemovedChildren = 0;
778 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
779 Edge& edge = node->children.child(i);
780 if (!edge)
781 break;
782 JSValue childConstant = m_state.forNode(edge).value();
783 if (!childConstant)
784 continue;
785 if (!childConstant.isString())
786 continue;
787 if (asString(childConstant)->length())
788 continue;
789 ++numberOfRemovedChildren;
790 }
791
792 if (numberOfRemovedChildren)
793 m_state.setFoundConstants(true);
794 setForNode(node, m_vm.stringStructure.get());
795 break;
796 }
797
798 case ArithSub: {
799 JSValue left = forNode(node->child1()).value();
800 JSValue right = forNode(node->child2()).value();
801 switch (node->binaryUseKind()) {
802 case Int32Use:
803 if (left && right && left.isInt32() && right.isInt32()) {
804 if (!shouldCheckOverflow(node->arithMode())) {
805 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
806 break;
807 }
808 JSValue result = jsNumber(left.asNumber() - right.asNumber());
809 if (result.isInt32()) {
810 setConstant(node, result);
811 break;
812 }
813 }
814 setNonCellTypeForNode(node, SpecInt32Only);
815 break;
816 case Int52RepUse:
817 if (left && right && left.isAnyInt() && right.isAnyInt()) {
818 JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
819 if (result.isAnyInt()) {
820 setConstant(node, result);
821 break;
822 }
823 }
824 setNonCellTypeForNode(node, SpecInt52Any);
825 break;
826 case DoubleRepUse:
827 if (left && right && left.isNumber() && right.isNumber()) {
828 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
829 break;
830 }
831 setNonCellTypeForNode(node,
832 typeOfDoubleDifference(
833 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
834 break;
835 case UntypedUse:
836 clobberWorld();
837 setNonCellTypeForNode(node, SpecBytecodeNumber);
838 break;
839 default:
840 RELEASE_ASSERT_NOT_REACHED();
841 break;
842 }
843 break;
844 }
845
846 case ValueNegate: {
847 clobberWorld();
848 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
849 break;
850 }
851
852 case ArithNegate: {
853 JSValue child = forNode(node->child1()).value();
854 switch (node->child1().useKind()) {
855 case Int32Use:
856 if (child && child.isInt32()) {
857 if (!shouldCheckOverflow(node->arithMode())) {
858 setConstant(node, jsNumber(-child.asInt32()));
859 break;
860 }
861 double doubleResult;
862 if (shouldCheckNegativeZero(node->arithMode()))
863 doubleResult = -child.asNumber();
864 else
865 doubleResult = 0 - child.asNumber();
866 JSValue valueResult = jsNumber(doubleResult);
867 if (valueResult.isInt32()) {
868 setConstant(node, valueResult);
869 break;
870 }
871 }
872 setNonCellTypeForNode(node, SpecInt32Only);
873 break;
874 case Int52RepUse:
875 if (child && child.isAnyInt()) {
876 double doubleResult;
877 if (shouldCheckNegativeZero(node->arithMode()))
878 doubleResult = -child.asNumber();
879 else
880 doubleResult = 0 - child.asNumber();
881 JSValue valueResult = jsNumber(doubleResult);
882 if (valueResult.isAnyInt()) {
883 setConstant(node, valueResult);
884 break;
885 }
886 }
887 setNonCellTypeForNode(node, SpecInt52Any);
888 break;
889 case DoubleRepUse:
890 if (child && child.isNumber()) {
891 setConstant(node, jsDoubleNumber(-child.asNumber()));
892 break;
893 }
894 setNonCellTypeForNode(node,
895 typeOfDoubleNegation(
896 forNode(node->child1()).m_type));
897 break;
898 default:
899 RELEASE_ASSERT_NOT_REACHED();
900 break;
901 }
902 break;
903 }
904
905 case ValuePow: {
906 JSValue childX = forNode(node->child1()).value();
907 JSValue childY = forNode(node->child2()).value();
908 if (childX && childY && childX.isNumber() && childY.isNumber()) {
909 // We need to call `didFoldClobberWorld` here because this path is only possible
910 // when node->useKind is UntypedUse. In the case of BigIntUse, children will be
911 // cleared by `AbstractInterpreter::executeEffects`.
912 didFoldClobberWorld();
913 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
914 break;
915 }
916
917 if (node->binaryUseKind() == BigIntUse)
918 setTypeForNode(node, SpecBigInt);
919 else {
920 clobberWorld();
921 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
922 }
923 break;
924 }
925
926 case ValueMul: {
927 if (node->binaryUseKind() == BigIntUse)
928 setTypeForNode(node, SpecBigInt);
929 else {
930 clobberWorld();
931 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
932 }
933 break;
934 }
935
936 case ArithMul: {
937 JSValue left = forNode(node->child1()).value();
938 JSValue right = forNode(node->child2()).value();
939 switch (node->binaryUseKind()) {
940 case Int32Use:
941 if (left && right && left.isInt32() && right.isInt32()) {
942 if (!shouldCheckOverflow(node->arithMode())) {
943 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
944 break;
945 }
946 double doubleResult = left.asNumber() * right.asNumber();
947 if (!shouldCheckNegativeZero(node->arithMode()))
948 doubleResult += 0; // Sanitizes zero.
949 JSValue valueResult = jsNumber(doubleResult);
950 if (valueResult.isInt32()) {
951 setConstant(node, valueResult);
952 break;
953 }
954 }
955 setNonCellTypeForNode(node, SpecInt32Only);
956 break;
957 case Int52RepUse:
958 if (left && right && left.isAnyInt() && right.isAnyInt()) {
959 double doubleResult = left.asNumber() * right.asNumber();
960 if (!shouldCheckNegativeZero(node->arithMode()))
961 doubleResult += 0;
962 JSValue valueResult = jsNumber(doubleResult);
963 if (valueResult.isAnyInt()) {
964 setConstant(node, valueResult);
965 break;
966 }
967 }
968 setNonCellTypeForNode(node, SpecInt52Any);
969 break;
970 case DoubleRepUse:
971 if (left && right && left.isNumber() && right.isNumber()) {
972 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
973 break;
974 }
975 setNonCellTypeForNode(node,
976 typeOfDoubleProduct(
977 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
978 break;
979 default:
980 RELEASE_ASSERT_NOT_REACHED();
981 break;
982 }
983 break;
984 }
985
986 case ValueMod:
987 case ValueDiv: {
988 if (handleConstantDivOp(node))
989 break;
990
991 if (node->binaryUseKind() == BigIntUse)
992 setTypeForNode(node, SpecBigInt);
993 else {
994 clobberWorld();
995 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
996 }
997 break;
998 }
999
1000 case ArithMod:
1001 case ArithDiv: {
1002 if (handleConstantDivOp(node))
1003 break;
1004
1005 switch (node->binaryUseKind()) {
1006 case Int32Use:
1007 setNonCellTypeForNode(node, SpecInt32Only);
1008 break;
1009 case DoubleRepUse:
1010 if (node->op() == ArithDiv) {
1011 setNonCellTypeForNode(node,
1012 typeOfDoubleQuotient(
1013 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1014 } else {
1015 setNonCellTypeForNode(node,
1016 typeOfDoubleBinaryOp(
1017 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1018 }
1019
1020 break;
1021 default:
1022 RELEASE_ASSERT_NOT_REACHED();
1023 break;
1024 }
1025 break;
1026 }
1027
1028 case ArithMin: {
1029 JSValue left = forNode(node->child1()).value();
1030 JSValue right = forNode(node->child2()).value();
1031 switch (node->binaryUseKind()) {
1032 case Int32Use:
1033 if (left && right && left.isInt32() && right.isInt32()) {
1034 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
1035 break;
1036 }
1037 setNonCellTypeForNode(node, SpecInt32Only);
1038 break;
1039 case DoubleRepUse:
1040 if (left && right && left.isNumber() && right.isNumber()) {
1041 double a = left.asNumber();
1042 double b = right.asNumber();
1043 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
1044 break;
1045 }
1046 setNonCellTypeForNode(node,
1047 typeOfDoubleMinMax(
1048 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1049 break;
1050 default:
1051 RELEASE_ASSERT_NOT_REACHED();
1052 break;
1053 }
1054 break;
1055 }
1056
1057 case ArithMax: {
1058 JSValue left = forNode(node->child1()).value();
1059 JSValue right = forNode(node->child2()).value();
1060 switch (node->binaryUseKind()) {
1061 case Int32Use:
1062 if (left && right && left.isInt32() && right.isInt32()) {
1063 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
1064 break;
1065 }
1066 setNonCellTypeForNode(node, SpecInt32Only);
1067 break;
1068 case DoubleRepUse:
1069 if (left && right && left.isNumber() && right.isNumber()) {
1070 double a = left.asNumber();
1071 double b = right.asNumber();
1072 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
1073 break;
1074 }
1075 setNonCellTypeForNode(node,
1076 typeOfDoubleMinMax(
1077 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1078 break;
1079 default:
1080 RELEASE_ASSERT_NOT_REACHED();
1081 break;
1082 }
1083 break;
1084 }
1085
1086 case ArithAbs: {
1087 JSValue child = forNode(node->child1()).value();
1088 switch (node->child1().useKind()) {
1089 case Int32Use:
1090 if (Optional<double> number = child.toNumberFromPrimitive()) {
1091 JSValue result = jsNumber(fabs(*number));
1092 if (result.isInt32()) {
1093 setConstant(node, result);
1094 break;
1095 }
1096 }
1097 setNonCellTypeForNode(node, SpecInt32Only);
1098 break;
1099 case DoubleRepUse:
1100 if (Optional<double> number = child.toNumberFromPrimitive()) {
1101 setConstant(node, jsDoubleNumber(fabs(*number)));
1102 break;
1103 }
1104 setNonCellTypeForNode(node, typeOfDoubleAbs(forNode(node->child1()).m_type));
1105 break;
1106 default:
1107 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
1108 clobberWorld();
1109 setNonCellTypeForNode(node, SpecBytecodeNumber);
1110 break;
1111 }
1112 break;
1113 }
1114
1115 case ArithPow: {
1116 JSValue childY = forNode(node->child2()).value();
1117 if (childY && childY.isNumber()) {
1118 if (!childY.asNumber()) {
1119 setConstant(node, jsDoubleNumber(1));
1120 break;
1121 }
1122
1123 JSValue childX = forNode(node->child1()).value();
1124 if (childX && childX.isNumber()) {
1125 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
1126 break;
1127 }
1128 }
1129 setNonCellTypeForNode(node, typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1130 break;
1131 }
1132
1133 case ArithRandom: {
1134 setNonCellTypeForNode(node, SpecDoubleReal);
1135 break;
1136 }
1137
1138 case ArithRound:
1139 case ArithFloor:
1140 case ArithCeil:
1141 case ArithTrunc: {
1142 JSValue operand = forNode(node->child1()).value();
1143 if (Optional<double> number = operand.toNumberFromPrimitive()) {
1144 if (node->child1().useKind() != DoubleRepUse)
1145 didFoldClobberWorld();
1146
1147 double roundedValue = 0;
1148 if (node->op() == ArithRound)
1149 roundedValue = jsRound(*number);
1150 else if (node->op() == ArithFloor)
1151 roundedValue = floor(*number);
1152 else if (node->op() == ArithCeil)
1153 roundedValue = ceil(*number);
1154 else {
1155 ASSERT(node->op() == ArithTrunc);
1156 roundedValue = trunc(*number);
1157 }
1158
1159 if (node->child1().useKind() == UntypedUse) {
1160 setConstant(node, jsNumber(roundedValue));
1161 break;
1162 }
1163 if (producesInteger(node->arithRoundingMode())) {
1164 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
1165 if (roundedValueAsInt32 == roundedValue) {
1166 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
1167 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
1168 setConstant(node, jsNumber(roundedValueAsInt32));
1169 break;
1170 }
1171 } else {
1172 setConstant(node, jsNumber(roundedValueAsInt32));
1173 break;
1174 }
1175 }
1176 } else {
1177 setConstant(node, jsDoubleNumber(roundedValue));
1178 break;
1179 }
1180 }
1181 if (node->child1().useKind() == DoubleRepUse) {
1182 if (producesInteger(node->arithRoundingMode()))
1183 setNonCellTypeForNode(node, SpecInt32Only);
1184 else if (node->child1().useKind() == DoubleRepUse)
1185 setNonCellTypeForNode(node, typeOfDoubleRounding(forNode(node->child1()).m_type));
1186 } else {
1187 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
1188 clobberWorld();
1189 setNonCellTypeForNode(node, SpecBytecodeNumber);
1190 }
1191 break;
1192 }
1193
1194 case ArithSqrt:
1195 executeDoubleUnaryOpEffects(node, sqrt);
1196 break;
1197
1198 case ArithFRound:
1199 executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
1200 break;
1201
1202 case ArithUnary:
1203 executeDoubleUnaryOpEffects(node, arithUnaryFunction(node->arithUnaryType()));
1204 break;
1205
1206 case LogicalNot: {
1207 switch (booleanResult(node, forNode(node->child1()))) {
1208 case DefinitelyTrue:
1209 setConstant(node, jsBoolean(false));
1210 break;
1211 case DefinitelyFalse:
1212 setConstant(node, jsBoolean(true));
1213 break;
1214 default:
1215 setNonCellTypeForNode(node, SpecBoolean);
1216 break;
1217 }
1218 break;
1219 }
1220
1221 case MapHash: {
1222 if (JSValue key = forNode(node->child1()).value()) {
1223 if (Optional<uint32_t> hash = concurrentJSMapHash(key)) {
1224 // Although C++ code uses uint32_t for the hash, the closest type in DFG IR is Int32
1225 // and that's what MapHash returns. So, we have to cast to int32_t to avoid large
1226 // unsigned values becoming doubles. This casting between signed and unsigned
1227 // happens in the assembly code we emit when we don't constant fold this node.
1228 setConstant(node, jsNumber(static_cast<int32_t>(*hash)));
1229 break;
1230 }
1231 }
1232 setNonCellTypeForNode(node, SpecInt32Only);
1233 break;
1234 }
1235
1236 case NormalizeMapKey: {
1237 if (JSValue key = forNode(node->child1()).value()) {
1238 setConstant(node, *m_graph.freeze(normalizeMapKey(key)));
1239 break;
1240 }
1241
1242 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only);
1243 if (!(forNode(node->child1()).m_type & typeMaybeNormalized)) {
1244 m_state.setFoundConstants(true);
1245 forNode(node) = forNode(node->child1());
1246 break;
1247 }
1248
1249 makeHeapTopForNode(node);
1250 break;
1251 }
1252
1253 case StringValueOf: {
1254 clobberWorld();
1255 setTypeForNode(node, SpecString);
1256 break;
1257 }
1258
1259 case StringSlice: {
1260 setTypeForNode(node, SpecString);
1261 break;
1262 }
1263
1264 case ToLowerCase: {
1265 setTypeForNode(node, SpecString);
1266 break;
1267 }
1268
1269 case LoadKeyFromMapBucket:
1270 case LoadValueFromMapBucket:
1271 case ExtractValueFromWeakMapGet:
1272 makeHeapTopForNode(node);
1273 break;
1274
1275 case GetMapBucket:
1276 case GetMapBucketHead:
1277 if (node->child1().useKind() == MapObjectUse)
1278 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1279 else {
1280 ASSERT(node->child1().useKind() == SetObjectUse);
1281 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1282 }
1283 break;
1284
1285 case GetMapBucketNext:
1286 if (node->bucketOwnerType() == BucketOwnerType::Map)
1287 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1288 else {
1289 ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
1290 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1291 }
1292 break;
1293
1294 case SetAdd:
1295 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1296 break;
1297
1298 case MapSet:
1299 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1300 break;
1301
1302 case WeakSetAdd:
1303 case WeakMapSet:
1304 break;
1305
1306 case WeakMapGet:
1307 makeBytecodeTopForNode(node);
1308 break;
1309
1310 case IsEmpty:
1311 case IsUndefined:
1312 case IsUndefinedOrNull:
1313 case IsBoolean:
1314 case IsNumber:
1315 case NumberIsInteger:
1316 case IsObject:
1317 case IsObjectOrNull:
1318 case IsFunction:
1319 case IsCellWithType:
1320 case IsTypedArrayView: {
1321 AbstractValue child = forNode(node->child1());
1322 if (child.value()) {
1323 bool constantWasSet = true;
1324 switch (node->op()) {
1325 case IsCellWithType:
1326 setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
1327 break;
1328 case IsUndefined:
1329 setConstant(node, jsBoolean(
1330 child.value().isCell()
1331 ? child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1332 : child.value().isUndefined()));
1333 break;
1334 case IsUndefinedOrNull:
1335 setConstant(node, jsBoolean(child.value().isUndefinedOrNull()));
1336 break;
1337 case IsBoolean:
1338 setConstant(node, jsBoolean(child.value().isBoolean()));
1339 break;
1340 case IsNumber:
1341 setConstant(node, jsBoolean(child.value().isNumber()));
1342 break;
1343 case NumberIsInteger:
1344 setConstant(node, jsBoolean(NumberConstructor::isIntegerImpl(child.value())));
1345 break;
1346 case IsObject:
1347 setConstant(node, jsBoolean(child.value().isObject()));
1348 break;
1349 case IsObjectOrNull:
1350 if (child.value().isObject()) {
1351 JSObject* object = asObject(child.value());
1352 if (object->type() == JSFunctionType)
1353 setConstant(node, jsBoolean(false));
1354 else if (!(object->inlineTypeFlags() & OverridesGetCallData))
1355 setConstant(node, jsBoolean(!child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1356 else {
1357 // FIXME: This could just call getCallData.
1358 // https://bugs.webkit.org/show_bug.cgi?id=144457
1359 constantWasSet = false;
1360 }
1361 } else
1362 setConstant(node, jsBoolean(child.value().isNull()));
1363 break;
1364 case IsFunction:
1365 if (child.value().isObject()) {
1366 JSObject* object = asObject(child.value());
1367 if (object->type() == JSFunctionType)
1368 setConstant(node, jsBoolean(true));
1369 else if (!(object->inlineTypeFlags() & OverridesGetCallData))
1370 setConstant(node, jsBoolean(false));
1371 else {
1372 // FIXME: This could just call getCallData.
1373 // https://bugs.webkit.org/show_bug.cgi?id=144457
1374 constantWasSet = false;
1375 }
1376 } else
1377 setConstant(node, jsBoolean(false));
1378 break;
1379 case IsEmpty:
1380 setConstant(node, jsBoolean(child.value().isEmpty()));
1381 break;
1382 case IsTypedArrayView:
1383 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo(m_vm)->typedArrayStorageType)));
1384 break;
1385 default:
1386 constantWasSet = false;
1387 break;
1388 }
1389 if (constantWasSet)
1390 break;
1391 }
1392
1393 // FIXME: This code should really use AbstractValue::isType() and
1394 // AbstractValue::couldBeType().
1395 // https://bugs.webkit.org/show_bug.cgi?id=146870
1396
1397 bool constantWasSet = false;
1398 switch (node->op()) {
1399 case IsEmpty: {
1400 if (child.m_type && !(child.m_type & SpecEmpty)) {
1401 setConstant(node, jsBoolean(false));
1402 constantWasSet = true;
1403 break;
1404 }
1405
1406 if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1407 setConstant(node, jsBoolean(true));
1408 constantWasSet = true;
1409 break;
1410 }
1411
1412 break;
1413 }
1414 case IsUndefined:
1415 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1416 // https://bugs.webkit.org/show_bug.cgi?id=144456
1417
1418 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1419 setConstant(node, jsBoolean(false));
1420 constantWasSet = true;
1421 break;
1422 }
1423
1424 break;
1425 case IsUndefinedOrNull:
1426 if (!(child.m_type & ~SpecOther)) {
1427 setConstant(node, jsBoolean(true));
1428 constantWasSet = true;
1429 break;
1430 }
1431
1432 if (!(child.m_type & SpecOther)) {
1433 setConstant(node, jsBoolean(false));
1434 constantWasSet = true;
1435 break;
1436 }
1437 break;
1438 case IsBoolean:
1439 if (!(child.m_type & ~SpecBoolean)) {
1440 setConstant(node, jsBoolean(true));
1441 constantWasSet = true;
1442 break;
1443 }
1444
1445 if (!(child.m_type & SpecBoolean)) {
1446 setConstant(node, jsBoolean(false));
1447 constantWasSet = true;
1448 break;
1449 }
1450
1451 break;
1452 case IsNumber:
1453 if (!(child.m_type & ~SpecFullNumber)) {
1454 setConstant(node, jsBoolean(true));
1455 constantWasSet = true;
1456 break;
1457 }
1458
1459 if (!(child.m_type & SpecFullNumber)) {
1460 setConstant(node, jsBoolean(false));
1461 constantWasSet = true;
1462 break;
1463 }
1464
1465 break;
1466
1467 case NumberIsInteger:
1468 if (!(child.m_type & ~SpecInt32Only)) {
1469 setConstant(node, jsBoolean(true));
1470 constantWasSet = true;
1471 break;
1472 }
1473
1474 if (!(child.m_type & SpecFullNumber)) {
1475 setConstant(node, jsBoolean(false));
1476 constantWasSet = true;
1477 break;
1478 }
1479
1480 break;
1481
1482 case IsObject:
1483 if (!(child.m_type & ~SpecObject)) {
1484 setConstant(node, jsBoolean(true));
1485 constantWasSet = true;
1486 break;
1487 }
1488
1489 if (!(child.m_type & SpecObject)) {
1490 setConstant(node, jsBoolean(false));
1491 constantWasSet = true;
1492 break;
1493 }
1494
1495 break;
1496 case IsObjectOrNull:
1497 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1498 // https://bugs.webkit.org/show_bug.cgi?id=144456
1499
1500 // These expressions are complicated to parse. A helpful way to parse this is that
1501 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1502 // disjoint set from S". Things like "T - S" means that, provided that S is a
1503 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1504 // mean the "union of T and S".
1505
1506 // Is the child's type an object that isn't an other-object (i.e. object that could
1507 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1508 // this to true.
1509 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1510 setConstant(node, jsBoolean(true));
1511 constantWasSet = true;
1512 break;
1513 }
1514
1515 // Is the child's type definitely not either of: an object that isn't a function,
1516 // or either undefined or null? Then: we should fold this to false. This means
1517 // for example that if it's any non-function object, including those that have
1518 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1519 // if it's undefined-or-null, since the type bits don't distinguish between
1520 // undefined (which should fold to false) and null (which should fold to true).
1521 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1522 setConstant(node, jsBoolean(false));
1523 constantWasSet = true;
1524 break;
1525 }
1526
1527 break;
1528 case IsFunction:
1529 if (!(child.m_type & ~SpecFunction)) {
1530 setConstant(node, jsBoolean(true));
1531 constantWasSet = true;
1532 break;
1533 }
1534
1535 if (!(child.m_type & (SpecFunction | SpecObjectOther | SpecProxyObject))) {
1536 setConstant(node, jsBoolean(false));
1537 constantWasSet = true;
1538 break;
1539 }
1540 break;
1541
1542 case IsCellWithType:
1543 if (!(child.m_type & ~node->speculatedTypeForQuery())) {
1544 setConstant(node, jsBoolean(true));
1545 constantWasSet = true;
1546 break;
1547 }
1548 if (!(child.m_type & node->speculatedTypeForQuery())) {
1549 setConstant(node, jsBoolean(false));
1550 constantWasSet = true;
1551 break;
1552 }
1553 break;
1554
1555 case IsTypedArrayView:
1556 if (!(child.m_type & ~SpecTypedArrayView)) {
1557 setConstant(node, jsBoolean(true));
1558 constantWasSet = true;
1559 break;
1560 }
1561 if (!(child.m_type & SpecTypedArrayView)) {
1562 setConstant(node, jsBoolean(false));
1563 constantWasSet = true;
1564 break;
1565 }
1566 break;
1567
1568 default:
1569 break;
1570 }
1571 if (constantWasSet)
1572 break;
1573
1574 setNonCellTypeForNode(node, SpecBoolean);
1575 break;
1576 }
1577
1578 case TypeOf: {
1579 JSValue child = forNode(node->child1()).value();
1580 AbstractValue& abstractChild = forNode(node->child1());
1581 if (child) {
1582 JSValue typeString = jsTypeStringForValue(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1583 setConstant(node, *m_graph.freeze(typeString));
1584 break;
1585 }
1586
1587 if (isFullNumberSpeculation(abstractChild.m_type)) {
1588 setConstant(node, *m_graph.freeze(m_vm.smallStrings.numberString()));
1589 break;
1590 }
1591
1592 if (isStringSpeculation(abstractChild.m_type)) {
1593 setConstant(node, *m_graph.freeze(m_vm.smallStrings.stringString()));
1594 break;
1595 }
1596
1597 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1598 // https://bugs.webkit.org/show_bug.cgi?id=144456
1599 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1600 setConstant(node, *m_graph.freeze(m_vm.smallStrings.objectString()));
1601 break;
1602 }
1603
1604 if (isFunctionSpeculation(abstractChild.m_type)) {
1605 setConstant(node, *m_graph.freeze(m_vm.smallStrings.functionString()));
1606 break;
1607 }
1608
1609 if (isBooleanSpeculation(abstractChild.m_type)) {
1610 setConstant(node, *m_graph.freeze(m_vm.smallStrings.booleanString()));
1611 break;
1612 }
1613
1614 if (isSymbolSpeculation(abstractChild.m_type)) {
1615 setConstant(node, *m_graph.freeze(m_vm.smallStrings.symbolString()));
1616 break;
1617 }
1618
1619 if (isBigIntSpeculation(abstractChild.m_type)) {
1620 setConstant(node, *m_graph.freeze(m_vm.smallStrings.bigintString()));
1621 break;
1622 }
1623
1624 setTypeForNode(node, SpecStringIdent);
1625 break;
1626 }
1627
1628 case CompareBelow:
1629 case CompareBelowEq: {
1630 JSValue leftConst = forNode(node->child1()).value();
1631 JSValue rightConst = forNode(node->child2()).value();
1632 if (leftConst && rightConst) {
1633 if (leftConst.isInt32() && rightConst.isInt32()) {
1634 uint32_t a = static_cast<uint32_t>(leftConst.asInt32());
1635 uint32_t b = static_cast<uint32_t>(rightConst.asInt32());
1636 switch (node->op()) {
1637 case CompareBelow:
1638 setConstant(node, jsBoolean(a < b));
1639 break;
1640 case CompareBelowEq:
1641 setConstant(node, jsBoolean(a <= b));
1642 break;
1643 default:
1644 RELEASE_ASSERT_NOT_REACHED();
1645 break;
1646 }
1647 break;
1648 }
1649 }
1650
1651 if (node->child1() == node->child2()) {
1652 switch (node->op()) {
1653 case CompareBelow:
1654 setConstant(node, jsBoolean(false));
1655 break;
1656 case CompareBelowEq:
1657 setConstant(node, jsBoolean(true));
1658 break;
1659 default:
1660 DFG_CRASH(m_graph, node, "Unexpected node type");
1661 break;
1662 }
1663 break;
1664 }
1665 setNonCellTypeForNode(node, SpecBoolean);
1666 break;
1667 }
1668
1669 case CompareLess:
1670 case CompareLessEq:
1671 case CompareGreater:
1672 case CompareGreaterEq:
1673 case CompareEq: {
1674 bool isClobbering = node->isBinaryUseKind(UntypedUse);
1675
1676 if (isClobbering)
1677 didFoldClobberWorld();
1678
1679 JSValue leftConst = forNode(node->child1()).value();
1680 JSValue rightConst = forNode(node->child2()).value();
1681 if (leftConst && rightConst) {
1682 if (leftConst.isNumber() && rightConst.isNumber()) {
1683 double a = leftConst.asNumber();
1684 double b = rightConst.asNumber();
1685 switch (node->op()) {
1686 case CompareLess:
1687 setConstant(node, jsBoolean(a < b));
1688 break;
1689 case CompareLessEq:
1690 setConstant(node, jsBoolean(a <= b));
1691 break;
1692 case CompareGreater:
1693 setConstant(node, jsBoolean(a > b));
1694 break;
1695 case CompareGreaterEq:
1696 setConstant(node, jsBoolean(a >= b));
1697 break;
1698 case CompareEq:
1699 setConstant(node, jsBoolean(a == b));
1700 break;
1701 default:
1702 RELEASE_ASSERT_NOT_REACHED();
1703 break;
1704 }
1705 break;
1706 }
1707
1708 if (leftConst.isString() && rightConst.isString()) {
1709 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1710 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1711 if (a && b) {
1712 bool result;
1713 if (node->op() == CompareEq)
1714 result = WTF::equal(a, b);
1715 else if (node->op() == CompareLess)
1716 result = codePointCompare(a, b) < 0;
1717 else if (node->op() == CompareLessEq)
1718 result = codePointCompare(a, b) <= 0;
1719 else if (node->op() == CompareGreater)
1720 result = codePointCompare(a, b) > 0;
1721 else if (node->op() == CompareGreaterEq)
1722 result = codePointCompare(a, b) >= 0;
1723 else
1724 RELEASE_ASSERT_NOT_REACHED();
1725 setConstant(node, jsBoolean(result));
1726 break;
1727 }
1728 }
1729
1730 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1731 setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
1732 break;
1733 }
1734 }
1735
1736 if (node->op() == CompareEq) {
1737 SpeculatedType leftType = forNode(node->child1()).m_type;
1738 SpeculatedType rightType = forNode(node->child2()).m_type;
1739 if (!valuesCouldBeEqual(leftType, rightType)) {
1740 setConstant(node, jsBoolean(false));
1741 break;
1742 }
1743
1744 if (leftType == SpecOther)
1745 std::swap(leftType, rightType);
1746 if (rightType == SpecOther) {
1747 // Undefined and Null are always equal when compared to eachother.
1748 if (!(leftType & ~SpecOther)) {
1749 setConstant(node, jsBoolean(true));
1750 break;
1751 }
1752
1753 // Any other type compared to Null or Undefined is always false
1754 // as long as the MasqueradesAsUndefined watchpoint is valid.
1755 //
1756 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1757 // cases are always "false".
1758 if (!(leftType & (SpecObjectOther | SpecOther))) {
1759 setConstant(node, jsBoolean(false));
1760 break;
1761 }
1762
1763 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1764 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1765 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1766 setConstant(node, jsBoolean(false));
1767 break;
1768 }
1769 }
1770 }
1771
1772 if (node->child1() == node->child2()) {
1773 if (node->isBinaryUseKind(Int32Use) ||
1774 node->isBinaryUseKind(Int52RepUse) ||
1775 node->isBinaryUseKind(StringUse) ||
1776 node->isBinaryUseKind(BooleanUse) ||
1777 node->isBinaryUseKind(SymbolUse) ||
1778 node->isBinaryUseKind(StringIdentUse) ||
1779 node->isBinaryUseKind(ObjectUse) ||
1780 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1781 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1782 switch (node->op()) {
1783 case CompareLess:
1784 case CompareGreater:
1785 setConstant(node, jsBoolean(false));
1786 break;
1787 case CompareLessEq:
1788 case CompareGreaterEq:
1789 case CompareEq:
1790 setConstant(node, jsBoolean(true));
1791 break;
1792 default:
1793 DFG_CRASH(m_graph, node, "Unexpected node type");
1794 break;
1795 }
1796 break;
1797 }
1798 }
1799
1800 if (isClobbering)
1801 clobberWorld();
1802 setNonCellTypeForNode(node, SpecBoolean);
1803 break;
1804 }
1805
1806 case CompareStrictEq:
1807 case SameValue: {
1808 Node* leftNode = node->child1().node();
1809 Node* rightNode = node->child2().node();
1810 JSValue left = forNode(leftNode).value();
1811 JSValue right = forNode(rightNode).value();
1812 if (left && right) {
1813 if (left.isString() && right.isString()) {
1814 // We need this case because JSValue::strictEqual is otherwise too racy for
1815 // string comparisons.
1816 const StringImpl* a = asString(left)->tryGetValueImpl();
1817 const StringImpl* b = asString(right)->tryGetValueImpl();
1818 if (a && b) {
1819 setConstant(node, jsBoolean(WTF::equal(a, b)));
1820 break;
1821 }
1822 } else {
1823 if (node->op() == CompareStrictEq)
1824 setConstant(node, jsBoolean(JSValue::strictEqual(nullptr, left, right)));
1825 else
1826 setConstant(node, jsBoolean(sameValue(nullptr, left, right)));
1827 break;
1828 }
1829 }
1830
1831 if (node->isBinaryUseKind(UntypedUse)) {
1832 // FIXME: Revisit this condition when introducing BigInt to JSC.
1833 auto isNonStringCellConstant = [] (JSValue value) {
1834 return value && value.isCell() && !value.isString();
1835 };
1836
1837 if (isNonStringCellConstant(left) || isNonStringCellConstant(right)) {
1838 m_state.setFoundConstants(true);
1839 setNonCellTypeForNode(node, SpecBoolean);
1840 break;
1841 }
1842 }
1843
1844 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1845 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1846 if (!(leftLUB & rightLUB)) {
1847 setConstant(node, jsBoolean(false));
1848 break;
1849 }
1850
1851 if (node->child1() == node->child2()) {
1852 if (node->isBinaryUseKind(BooleanUse) ||
1853 node->isBinaryUseKind(Int32Use) ||
1854 node->isBinaryUseKind(Int52RepUse) ||
1855 node->isBinaryUseKind(StringUse) ||
1856 node->isBinaryUseKind(StringIdentUse) ||
1857 node->isBinaryUseKind(SymbolUse) ||
1858 node->isBinaryUseKind(ObjectUse) ||
1859 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1860 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1861 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1862 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1863 node->isBinaryUseKind(StringUse, UntypedUse) ||
1864 node->isBinaryUseKind(UntypedUse, StringUse)) {
1865 setConstant(node, jsBoolean(true));
1866 break;
1867 }
1868 }
1869
1870 setNonCellTypeForNode(node, SpecBoolean);
1871 break;
1872 }
1873
1874 case CompareEqPtr: {
1875 Node* childNode = node->child1().node();
1876 JSValue childValue = forNode(childNode).value();
1877 if (childValue) {
1878 setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
1879 break;
1880 }
1881
1882 setNonCellTypeForNode(node, SpecBoolean);
1883 break;
1884 }
1885
1886 case StringCharCodeAt:
1887 setNonCellTypeForNode(node, SpecInt32Only);
1888 break;
1889
1890 case StringFromCharCode:
1891 switch (node->child1().useKind()) {
1892 case Int32Use:
1893 break;
1894 case UntypedUse:
1895 clobberWorld();
1896 break;
1897 default:
1898 DFG_CRASH(m_graph, node, "Bad use kind");
1899 break;
1900 }
1901 setTypeForNode(node, SpecString);
1902 break;
1903
1904 case StringCharAt:
1905 setForNode(node, m_vm.stringStructure.get());
1906 break;
1907
1908 case GetByVal:
1909 case AtomicsAdd:
1910 case AtomicsAnd:
1911 case AtomicsCompareExchange:
1912 case AtomicsExchange:
1913 case AtomicsLoad:
1914 case AtomicsOr:
1915 case AtomicsStore:
1916 case AtomicsSub:
1917 case AtomicsXor: {
1918 if (node->op() == GetByVal) {
1919 auto foldGetByValOnConstantProperty = [&] (Edge& arrayEdge, Edge& indexEdge) {
1920 // FIXME: We can expand this for non x86 environments.
1921 // https://bugs.webkit.org/show_bug.cgi?id=134641
1922 if (!isX86())
1923 return false;
1924
1925 AbstractValue& arrayValue = forNode(arrayEdge);
1926
1927 // Check the structure set is finite. This means that this constant's structure is watched and guaranteed the one of this set.
1928 // When the structure is changed, this code should be invalidated. This is important since the following code relies on the
1929 // constant object's is not changed.
1930 if (!arrayValue.m_structure.isFinite())
1931 return false;
1932
1933 JSValue arrayConstant = arrayValue.value();
1934 if (!arrayConstant)
1935 return false;
1936
1937 JSObject* array = jsDynamicCast<JSObject*>(m_vm, arrayConstant);
1938 if (!array)
1939 return false;
1940
1941 JSValue indexConstant = forNode(indexEdge).value();
1942 if (!indexConstant || !indexConstant.isInt32() || indexConstant.asInt32() < 0)
1943 return false;
1944 uint32_t index = indexConstant.asUInt32();
1945
1946 // Check that the early StructureID is not nuked, get the butterfly, and check the late StructureID again.
1947 // And we check the indexing mode of the structure. If the indexing mode is CoW, the butterfly is
1948 // definitely JSImmutableButterfly.
1949 StructureID structureIDEarly = array->structureID();
1950 if (isNuked(structureIDEarly))
1951 return false;
1952
1953 if (node->arrayMode().arrayClass() == Array::OriginalCopyOnWriteArray) {
1954
1955 WTF::loadLoadFence();
1956 Butterfly* butterfly = array->butterfly();
1957
1958 WTF::loadLoadFence();
1959 StructureID structureIDLate = array->structureID();
1960
1961 if (structureIDEarly != structureIDLate)
1962 return false;
1963
1964 Structure* structure = m_vm.getStructure(structureIDLate);
1965 switch (node->arrayMode().type()) {
1966 case Array::Int32:
1967 case Array::Contiguous:
1968 case Array::Double:
1969 if (structure->indexingMode() != (toIndexingShape(node->arrayMode().type()) | CopyOnWrite | IsArray))
1970 return false;
1971 break;
1972 default:
1973 return false;
1974 }
1975 ASSERT(isCopyOnWrite(structure->indexingMode()));
1976
1977 JSImmutableButterfly* immutableButterfly = JSImmutableButterfly::fromButterfly(butterfly);
1978 if (index < immutableButterfly->length()) {
1979 JSValue value = immutableButterfly->get(index);
1980 ASSERT(value);
1981 if (value.isCell())
1982 setConstant(node, *m_graph.freeze(value.asCell()));
1983 else
1984 setConstant(node, value);
1985 return true;
1986 }
1987
1988 if (node->arrayMode().isOutOfBounds()) {
1989 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1990 Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(m_vm);
1991 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(m_vm);
1992 if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
1993 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
1994 && globalObject->arrayPrototypeChainIsSane()) {
1995 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
1996 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
1997 // Note that Array::Double and Array::Int32 return JSValue if array mode is OutOfBounds.
1998 setConstant(node, jsUndefined());
1999 return true;
2000 }
2001 }
2002 return false;
2003 }
2004
2005 if (node->arrayMode().type() == Array::ArrayStorage || node->arrayMode().type() == Array::SlowPutArrayStorage) {
2006 JSValue value;
2007 {
2008 // ArrayStorage's Butterfly can be half-broken state.
2009 auto locker = holdLock(array->cellLock());
2010
2011 WTF::loadLoadFence();
2012 Butterfly* butterfly = array->butterfly();
2013
2014 WTF::loadLoadFence();
2015 StructureID structureIDLate = array->structureID();
2016
2017 if (structureIDEarly != structureIDLate)
2018 return false;
2019
2020 Structure* structure = m_vm.getStructure(structureIDLate);
2021 if (!hasAnyArrayStorage(structure->indexingMode()))
2022 return false;
2023
2024 if (structure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
2025 return false;
2026
2027 ArrayStorage* storage = butterfly->arrayStorage();
2028 if (index >= storage->length())
2029 return false;
2030
2031 if (index < storage->vectorLength())
2032 return false;
2033
2034 SparseArrayValueMap* map = storage->m_sparseMap.get();
2035 if (!map)
2036 return false;
2037
2038 value = map->getConcurrently(index);
2039 }
2040 if (!value)
2041 return false;
2042
2043 if (value.isCell())
2044 setConstant(node, *m_graph.freeze(value.asCell()));
2045 else
2046 setConstant(node, value);
2047 return true;
2048 }
2049
2050 return false;
2051 };
2052
2053 bool didFold = false;
2054 switch (node->arrayMode().type()) {
2055 case Array::Generic:
2056 case Array::Int32:
2057 case Array::Double:
2058 case Array::Contiguous:
2059 case Array::ArrayStorage:
2060 case Array::SlowPutArrayStorage:
2061 if (foldGetByValOnConstantProperty(m_graph.child(node, 0), m_graph.child(node, 1))) {
2062 if (!node->arrayMode().isInBounds())
2063 didFoldClobberWorld();
2064 didFold = true;
2065 }
2066 break;
2067 default:
2068 break;
2069 }
2070
2071 if (didFold)
2072 break;
2073 }
2074
2075 if (node->op() != GetByVal) {
2076 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
2077 Edge storageEdge = m_graph.child(node, 2 + numExtraArgs);
2078 if (!storageEdge)
2079 clobberWorld();
2080 }
2081 switch (node->arrayMode().type()) {
2082 case Array::SelectUsingPredictions:
2083 case Array::Unprofiled:
2084 case Array::SelectUsingArguments:
2085 RELEASE_ASSERT_NOT_REACHED();
2086 break;
2087 case Array::ForceExit:
2088 m_state.setIsValid(false);
2089 break;
2090 case Array::Undecided: {
2091 JSValue index = forNode(m_graph.child(node, 1)).value();
2092 if (index && index.isInt32() && index.asInt32() >= 0) {
2093 setConstant(node, jsUndefined());
2094 break;
2095 }
2096 setNonCellTypeForNode(node, SpecOther);
2097 break;
2098 }
2099 case Array::Generic:
2100 clobberWorld();
2101 makeHeapTopForNode(node);
2102 break;
2103 case Array::String:
2104 if (node->arrayMode().isOutOfBounds()) {
2105 // If the watchpoint was still valid we could totally set this to be
2106 // SpecString | SpecOther. Except that we'd have to be careful. If we
2107 // tested the watchpoint state here then it could change by the time
2108 // we got to the backend. So to do this right, we'd have to get the
2109 // fixup phase to check the watchpoint state and then bake into the
2110 // GetByVal operation the fact that we're using a watchpoint, using
2111 // something like Array::SaneChain (except not quite, because that
2112 // implies an in-bounds access). None of this feels like it's worth it,
2113 // so we're going with TOP for now. The same thing applies to
2114 // clobbering the world.
2115 clobberWorld();
2116 makeHeapTopForNode(node);
2117 } else
2118 setForNode(node, m_vm.stringStructure.get());
2119 break;
2120 case Array::DirectArguments:
2121 case Array::ScopedArguments:
2122 if (node->arrayMode().isOutOfBounds())
2123 clobberWorld();
2124 makeHeapTopForNode(node);
2125 break;
2126 case Array::Int32:
2127 if (node->arrayMode().isOutOfBounds()) {
2128 clobberWorld();
2129 makeHeapTopForNode(node);
2130 } else
2131 setNonCellTypeForNode(node, SpecInt32Only);
2132 break;
2133 case Array::Double:
2134 if (node->arrayMode().isOutOfBounds()) {
2135 clobberWorld();
2136 makeHeapTopForNode(node);
2137 } else if (node->arrayMode().isSaneChain())
2138 setNonCellTypeForNode(node, SpecBytecodeDouble);
2139 else
2140 setNonCellTypeForNode(node, SpecDoubleReal);
2141 break;
2142 case Array::Contiguous:
2143 case Array::ArrayStorage:
2144 case Array::SlowPutArrayStorage:
2145 if (node->arrayMode().isOutOfBounds())
2146 clobberWorld();
2147 makeHeapTopForNode(node);
2148 break;
2149 case Array::Int8Array:
2150 setNonCellTypeForNode(node, SpecInt32Only);
2151 break;
2152 case Array::Int16Array:
2153 setNonCellTypeForNode(node, SpecInt32Only);
2154 break;
2155 case Array::Int32Array:
2156 setNonCellTypeForNode(node, SpecInt32Only);
2157 break;
2158 case Array::Uint8Array:
2159 setNonCellTypeForNode(node, SpecInt32Only);
2160 break;
2161 case Array::Uint8ClampedArray:
2162 setNonCellTypeForNode(node, SpecInt32Only);
2163 break;
2164 case Array::Uint16Array:
2165 setNonCellTypeForNode(node, SpecInt32Only);
2166 break;
2167 case Array::Uint32Array:
2168 if (node->shouldSpeculateInt32())
2169 setNonCellTypeForNode(node, SpecInt32Only);
2170 else if (node->shouldSpeculateInt52())
2171 setNonCellTypeForNode(node, SpecInt52Any);
2172 else
2173 setNonCellTypeForNode(node, SpecAnyIntAsDouble);
2174 break;
2175 case Array::Float32Array:
2176 setNonCellTypeForNode(node, SpecFullDouble);
2177 break;
2178 case Array::Float64Array:
2179 setNonCellTypeForNode(node, SpecFullDouble);
2180 break;
2181 default:
2182 RELEASE_ASSERT_NOT_REACHED();
2183 break;
2184 }
2185 break;
2186 }
2187
2188 case PutByValDirect:
2189 case PutByVal:
2190 case PutByValAlias: {
2191 switch (node->arrayMode().modeForPut().type()) {
2192 case Array::ForceExit:
2193 m_state.setIsValid(false);
2194 break;
2195 case Array::Generic:
2196 clobberWorld();
2197 break;
2198 case Array::Int32:
2199 if (node->arrayMode().isOutOfBounds())
2200 clobberWorld();
2201 break;
2202 case Array::Double:
2203 if (node->arrayMode().isOutOfBounds())
2204 clobberWorld();
2205 break;
2206 case Array::Contiguous:
2207 case Array::ArrayStorage:
2208 if (node->arrayMode().isOutOfBounds())
2209 clobberWorld();
2210 break;
2211 case Array::SlowPutArrayStorage:
2212 if (node->arrayMode().mayStoreToHole())
2213 clobberWorld();
2214 break;
2215 default:
2216 break;
2217 }
2218 break;
2219 }
2220
2221 case ArrayPush:
2222 clobberWorld();
2223 setNonCellTypeForNode(node, SpecBytecodeNumber);
2224 break;
2225
2226 case ArraySlice: {
2227 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2228
2229 // FIXME: We could do better here if we prove that the
2230 // incoming value has only a single structure.
2231 RegisteredStructureSet structureSet;
2232 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32)));
2233 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous)));
2234 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble)));
2235
2236 setForNode(node, structureSet);
2237 break;
2238 }
2239
2240 case ArrayIndexOf: {
2241 setNonCellTypeForNode(node, SpecInt32Only);
2242 break;
2243 }
2244
2245 case ArrayPop:
2246 clobberWorld();
2247 makeHeapTopForNode(node);
2248 break;
2249
2250 case GetMyArgumentByVal:
2251 case GetMyArgumentByValOutOfBounds: {
2252 JSValue index = forNode(node->child2()).m_value;
2253 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame();
2254
2255 if (index && index.isUInt32()) {
2256 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
2257 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
2258 // paths as unreachable, or to return undefined. We could implement that eventually.
2259
2260 Checked<unsigned, RecordOverflow> argumentIndexChecked = index.asUInt32();
2261 argumentIndexChecked += node->numberOfArgumentsToSkip();
2262 unsigned argumentIndex;
2263 if (argumentIndexChecked.safeGet(argumentIndex) != CheckedState::DidOverflow) {
2264 if (inlineCallFrame) {
2265 if (argumentIndex < inlineCallFrame->argumentCountIncludingThis - 1) {
2266 setForNode(node, m_state.operand(
2267 virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset));
2268 m_state.setFoundConstants(true);
2269 break;
2270 }
2271 } else {
2272 if (argumentIndex < m_state.numberOfArguments() - 1) {
2273 setForNode(node, m_state.argument(argumentIndex + 1));
2274 m_state.setFoundConstants(true);
2275 break;
2276 }
2277 }
2278 }
2279 }
2280
2281 if (inlineCallFrame) {
2282 // We have a bound on the types even though it's random access. Take advantage of this.
2283
2284 AbstractValue result;
2285 for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->argumentCountIncludingThis; ++i) {
2286 result.merge(
2287 m_state.operand(
2288 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
2289 }
2290
2291 if (node->op() == GetMyArgumentByValOutOfBounds)
2292 result.merge(SpecOther);
2293
2294 if (result.value())
2295 m_state.setFoundConstants(true);
2296
2297 setForNode(node, result);
2298 break;
2299 }
2300
2301 makeHeapTopForNode(node);
2302 break;
2303 }
2304
2305 case RegExpExec:
2306 case RegExpExecNonGlobalOrSticky:
2307 if (node->op() == RegExpExec) {
2308 // Even if we've proven known input types as RegExpObject and String,
2309 // accessing lastIndex is effectful if it's a global regexp.
2310 clobberWorld();
2311 }
2312
2313 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
2314 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(m_vm, globalObjectValue)) {
2315 if (!globalObject->isHavingABadTime()) {
2316 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2317 RegisteredStructureSet structureSet;
2318 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure()));
2319 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayWithGroupsStructure()));
2320 setForNode(node, structureSet);
2321 forNode(node).merge(SpecOther);
2322 break;
2323 }
2324 }
2325 }
2326 setTypeForNode(node, SpecOther | SpecArray);
2327 break;
2328
2329 case RegExpTest:
2330 // Even if we've proven known input types as RegExpObject and String,
2331 // accessing lastIndex is effectful if it's a global regexp.
2332 clobberWorld();
2333 setNonCellTypeForNode(node, SpecBoolean);
2334 break;
2335
2336 case RegExpMatchFast:
2337 ASSERT(node->child2().useKind() == RegExpObjectUse);
2338 ASSERT(node->child3().useKind() == StringUse || node->child3().useKind() == KnownStringUse);
2339 setTypeForNode(node, SpecOther | SpecArray);
2340 break;
2341
2342 case RegExpMatchFastGlobal:
2343 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == KnownStringUse);
2344 setTypeForNode(node, SpecOther | SpecArray);
2345 break;
2346
2347 case StringReplace:
2348 case StringReplaceRegExp:
2349 if (node->child1().useKind() == StringUse
2350 && node->child2().useKind() == RegExpObjectUse
2351 && node->child3().useKind() == StringUse) {
2352 // This doesn't clobber the world. It just reads and writes regexp state.
2353 } else
2354 clobberWorld();
2355 setForNode(node, m_vm.stringStructure.get());
2356 break;
2357
2358 case Jump:
2359 break;
2360
2361 case Branch: {
2362 Node* child = node->child1().node();
2363 BooleanResult result = booleanResult(node, forNode(child));
2364 if (result == DefinitelyTrue) {
2365 m_state.setBranchDirection(TakeTrue);
2366 break;
2367 }
2368 if (result == DefinitelyFalse) {
2369 m_state.setBranchDirection(TakeFalse);
2370 break;
2371 }
2372 // FIXME: The above handles the trivial cases of sparse conditional
2373 // constant propagation, but we can do better:
2374 // We can specialize the source variable's value on each direction of
2375 // the branch.
2376 m_state.setBranchDirection(TakeBoth);
2377 break;
2378 }
2379
2380 case Switch: {
2381 // Nothing to do for now.
2382 // FIXME: Do sparse conditional things.
2383 break;
2384 }
2385
2386 case EntrySwitch:
2387 break;
2388
2389 case Return:
2390 m_state.setIsValid(false);
2391 break;
2392
2393 case Throw:
2394 case ThrowStaticError:
2395 case TailCall:
2396 case DirectTailCall:
2397 case TailCallVarargs:
2398 case TailCallForwardVarargs:
2399 clobberWorld();
2400 m_state.setIsValid(false);
2401 break;
2402
2403 case ToPrimitive: {
2404 JSValue childConst = forNode(node->child1()).value();
2405 if (childConst && childConst.isNumber()) {
2406 didFoldClobberWorld();
2407 setConstant(node, childConst);
2408 break;
2409 }
2410
2411 ASSERT(node->child1().useKind() == UntypedUse);
2412
2413 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))) {
2414 m_state.setFoundConstants(true);
2415 didFoldClobberWorld();
2416 setForNode(node, forNode(node->child1()));
2417 break;
2418 }
2419
2420 clobberWorld();
2421
2422 setTypeForNode(node, SpecHeapTop & ~SpecObject);
2423 break;
2424 }
2425
2426 case ToNumber: {
2427 JSValue childConst = forNode(node->child1()).value();
2428 if (childConst && childConst.isNumber()) {
2429 didFoldClobberWorld();
2430 setConstant(node, childConst);
2431 break;
2432 }
2433
2434 ASSERT(node->child1().useKind() == UntypedUse);
2435
2436 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
2437 m_state.setFoundConstants(true);
2438 didFoldClobberWorld();
2439 setForNode(node, forNode(node->child1()));
2440 break;
2441 }
2442
2443 clobberWorld();
2444 setNonCellTypeForNode(node, SpecBytecodeNumber);
2445 break;
2446 }
2447
2448 case ToString:
2449 case CallStringConstructor: {
2450 switch (node->child1().useKind()) {
2451 case StringObjectUse:
2452 case StringOrStringObjectUse:
2453 case Int32Use:
2454 case Int52RepUse:
2455 case DoubleRepUse:
2456 case NotCellUse:
2457 break;
2458 case CellUse:
2459 case UntypedUse:
2460 clobberWorld();
2461 break;
2462 default:
2463 RELEASE_ASSERT_NOT_REACHED();
2464 break;
2465 }
2466 setForNode(node, m_vm.stringStructure.get());
2467 break;
2468 }
2469
2470 case NumberToStringWithRadix: {
2471 JSValue radixValue = forNode(node->child2()).m_value;
2472 if (radixValue && radixValue.isInt32()) {
2473 int32_t radix = radixValue.asInt32();
2474 if (2 <= radix && radix <= 36) {
2475 m_state.setFoundConstants(true);
2476 didFoldClobberWorld();
2477 setForNode(node, m_graph.m_vm.stringStructure.get());
2478 break;
2479 }
2480 }
2481 clobberWorld();
2482 setForNode(node, m_graph.m_vm.stringStructure.get());
2483 break;
2484 }
2485
2486 case NumberToStringWithValidRadixConstant: {
2487 setForNode(node, m_graph.m_vm.stringStructure.get());
2488 break;
2489 }
2490
2491 case NewStringObject: {
2492 ASSERT(node->structure()->classInfo() == StringObject::info());
2493 setForNode(node, node->structure());
2494 break;
2495 }
2496
2497 case NewSymbol: {
2498 setForNode(node, m_vm.symbolStructure.get());
2499 break;
2500 }
2501
2502 case NewArray:
2503 ASSERT(node->indexingMode() == node->indexingType()); // Copy on write arrays should only be created by NewArrayBuffer.
2504 setForNode(node,
2505 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
2506 break;
2507
2508 case NewArrayWithSpread:
2509 if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2510 // We've compiled assuming we're not having a bad time, so to be consistent
2511 // with StructureRegisterationPhase we must say we produce an original array
2512 // allocation structure.
2513 setForNode(node,
2514 m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
2515 } else {
2516 setForNode(node,
2517 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
2518 }
2519
2520 break;
2521
2522 case Spread:
2523 switch (node->child1()->op()) {
2524 case PhantomNewArrayBuffer:
2525 case PhantomCreateRest:
2526 break;
2527 default:
2528 if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
2529 clobberWorld();
2530 else
2531 didFoldClobberWorld();
2532 break;
2533 }
2534
2535 setForNode(node,
2536 m_vm.fixedArrayStructure.get());
2537 break;
2538
2539 case NewArrayBuffer:
2540 setForNode(node,
2541 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingMode()));
2542 break;
2543
2544 case NewArrayWithSize:
2545 setTypeForNode(node, SpecArray);
2546 break;
2547
2548 case NewTypedArray:
2549 switch (node->child1().useKind()) {
2550 case Int32Use:
2551 break;
2552 case UntypedUse:
2553 clobberWorld();
2554 break;
2555 default:
2556 RELEASE_ASSERT_NOT_REACHED();
2557 break;
2558 }
2559 setForNode(node,
2560 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
2561 node->typedArrayType()));
2562 break;
2563
2564 case NewRegexp:
2565 setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
2566 break;
2567
2568 case ToThis: {
2569 AbstractValue& source = forNode(node->child1());
2570 AbstractValue& destination = forNode(node);
2571 bool strictMode = m_graph.isStrictModeFor(node->origin.semantic);
2572
2573 ToThisResult result = isToThisAnIdentity(m_vm, strictMode, source);
2574 switch (result) {
2575 case ToThisResult::Identity:
2576 m_state.setFoundConstants(true);
2577 destination = source;
2578 break;
2579 case ToThisResult::Undefined:
2580 setConstant(node, jsUndefined());
2581 break;
2582 case ToThisResult::GlobalThis:
2583 m_state.setFoundConstants(true);
2584 destination.setType(m_graph, SpecObject);
2585 break;
2586 case ToThisResult::Dynamic:
2587 if (strictMode)
2588 destination.makeHeapTop();
2589 else {
2590 destination = source;
2591 destination.merge(SpecObject);
2592 }
2593 break;
2594 }
2595 break;
2596 }
2597
2598 case CreateThis: {
2599 if (JSValue base = forNode(node->child1()).m_value) {
2600 if (auto* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
2601 if (FunctionRareData* rareData = function->rareData()) {
2602 if (Structure* structure = rareData->objectAllocationStructure()) {
2603 m_graph.freeze(rareData);
2604 m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
2605 m_state.setFoundConstants(true);
2606 didFoldClobberWorld();
2607 setForNode(node, structure);
2608 break;
2609 }
2610 }
2611 }
2612 }
2613 clobberWorld();
2614 setTypeForNode(node, SpecFinalObject);
2615 break;
2616 }
2617
2618 case NewObject:
2619 ASSERT(!!node->structure().get());
2620 setForNode(node, node->structure());
2621 break;
2622
2623 case ObjectCreate: {
2624 if (JSValue base = forNode(node->child1()).m_value) {
2625 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2626 Structure* structure = nullptr;
2627 if (base.isNull())
2628 structure = globalObject->nullPrototypeObjectStructure();
2629 else if (base.isObject())
2630 structure = globalObject->vm().structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
2631
2632 if (structure) {
2633 m_state.setFoundConstants(true);
2634 if (node->child1().useKind() == UntypedUse)
2635 didFoldClobberWorld();
2636 setForNode(node, structure);
2637 break;
2638 }
2639 }
2640 if (node->child1().useKind() == UntypedUse)
2641 clobberWorld();
2642 setTypeForNode(node, SpecFinalObject);
2643 break;
2644 }
2645
2646 case ObjectKeys: {
2647 if (node->child1().useKind() == ObjectUse) {
2648 auto& structureSet = forNode(node->child1()).m_structure;
2649 if (structureSet.isFinite() && structureSet.size() == 1) {
2650 RegisteredStructure structure = structureSet.onlyStructure();
2651 if (auto* rareData = structure->rareDataConcurrently()) {
2652 if (!!rareData->cachedOwnKeysConcurrently()) {
2653 if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2654 m_state.setFoundConstants(true);
2655 didFoldClobberWorld();
2656 setTypeForNode(node, SpecArray);
2657 break;
2658 }
2659 }
2660 }
2661 }
2662 }
2663
2664 clobberWorld();
2665 setTypeForNode(node, SpecArray);
2666 break;
2667 }
2668
2669 case ToObject:
2670 case CallObjectConstructor: {
2671 AbstractValue& source = forNode(node->child1());
2672 AbstractValue& destination = forNode(node);
2673
2674 if (!(source.m_type & ~SpecObject)) {
2675 m_state.setFoundConstants(true);
2676 if (node->op() == ToObject)
2677 didFoldClobberWorld();
2678 destination = source;
2679 break;
2680 }
2681
2682 if (node->op() == ToObject)
2683 clobberWorld();
2684 setTypeForNode(node, SpecObject);
2685 break;
2686 }
2687
2688 case PhantomNewObject:
2689 case PhantomNewFunction:
2690 case PhantomNewGeneratorFunction:
2691 case PhantomNewAsyncGeneratorFunction:
2692 case PhantomNewAsyncFunction:
2693 case PhantomCreateActivation:
2694 case PhantomDirectArguments:
2695 case PhantomClonedArguments:
2696 case PhantomCreateRest:
2697 case PhantomSpread:
2698 case PhantomNewArrayWithSpread:
2699 case PhantomNewArrayBuffer:
2700 case PhantomNewRegexp:
2701 case BottomValue: {
2702 clearForNode(node);
2703 break;
2704 }
2705
2706 case PutHint:
2707 break;
2708
2709 case MaterializeNewObject: {
2710 setForNode(node, node->structureSet());
2711 break;
2712 }
2713
2714 case PushWithScope:
2715 // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated.
2716 setTypeForNode(node, SpecObjectOther);
2717 break;
2718
2719 case CreateActivation:
2720 case MaterializeCreateActivation:
2721 setForNode(node,
2722 m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
2723 break;
2724
2725 case CreateDirectArguments:
2726 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
2727 break;
2728
2729 case CreateScopedArguments:
2730 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
2731 break;
2732
2733 case CreateClonedArguments:
2734 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2735 setTypeForNode(node, SpecObject);
2736 break;
2737 }
2738 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
2739 break;
2740
2741 case NewGeneratorFunction:
2742 setForNode(node,
2743 m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
2744 break;
2745
2746 case NewAsyncGeneratorFunction:
2747 setForNode(node,
2748 m_codeBlock->globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure());
2749 break;
2750
2751 case NewAsyncFunction:
2752 setForNode(node,
2753 m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
2754 break;
2755
2756 case NewFunction: {
2757 JSGlobalObject* globalObject = m_codeBlock->globalObjectFor(node->origin.semantic);
2758 Structure* structure = JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>());
2759 setForNode(node, structure);
2760 break;
2761 }
2762
2763 case GetCallee:
2764 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
2765 if (JSFunction* function = executable->singleton().inferredValue()) {
2766 m_graph.watchpoints().addLazily(executable);
2767 setConstant(node, *m_graph.freeze(function));
2768 break;
2769 }
2770 }
2771 setTypeForNode(node, SpecFunction | SpecObjectOther);
2772 break;
2773
2774 case GetArgumentCountIncludingThis:
2775 setTypeForNode(node, SpecInt32Only);
2776 break;
2777
2778 case SetCallee:
2779 case SetArgumentCountIncludingThis:
2780 break;
2781
2782 case GetRestLength:
2783 setNonCellTypeForNode(node, SpecInt32Only);
2784 break;
2785
2786 case GetGetter: {
2787 JSValue base = forNode(node->child1()).m_value;
2788 if (base) {
2789 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2790 if (!getterSetter->isGetterNull()) {
2791 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
2792 break;
2793 }
2794 }
2795
2796 setTypeForNode(node, SpecObject);
2797 break;
2798 }
2799
2800 case GetSetter: {
2801 JSValue base = forNode(node->child1()).m_value;
2802 if (base) {
2803 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2804 if (!getterSetter->isSetterNull()) {
2805 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
2806 break;
2807 }
2808 }
2809
2810 setTypeForNode(node, SpecObject);
2811 break;
2812 }
2813
2814 case GetScope:
2815 if (JSValue base = forNode(node->child1()).m_value) {
2816 if (JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
2817 setConstant(node, *m_graph.freeze(function->scope()));
2818 break;
2819 }
2820 }
2821 setTypeForNode(node, SpecObjectOther);
2822 break;
2823
2824 case SkipScope: {
2825 JSValue child = forNode(node->child1()).value();
2826 if (child) {
2827 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
2828 break;
2829 }
2830 setTypeForNode(node, SpecObjectOther);
2831 break;
2832 }
2833
2834 case GetGlobalObject: {
2835 JSValue child = forNode(node->child1()).value();
2836 if (child) {
2837 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject(m_vm))));
2838 break;
2839 }
2840
2841 if (forNode(node->child1()).m_structure.isFinite()) {
2842 JSGlobalObject* globalObject = nullptr;
2843 bool ok = true;
2844 forNode(node->child1()).m_structure.forEach(
2845 [&] (RegisteredStructure structure) {
2846 if (!globalObject)
2847 globalObject = structure->globalObject();
2848 else if (globalObject != structure->globalObject())
2849 ok = false;
2850 });
2851 if (globalObject && ok) {
2852 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2853 break;
2854 }
2855 }
2856
2857 setTypeForNode(node, SpecObjectOther);
2858 break;
2859 }
2860
2861 case GetGlobalThis: {
2862 setTypeForNode(node, SpecObject);
2863 break;
2864 }
2865
2866 case GetClosureVar:
2867 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
2868 setConstant(node, *m_graph.freeze(value));
2869 break;
2870 }
2871 makeBytecodeTopForNode(node);
2872 break;
2873
2874 case PutClosureVar:
2875 break;
2876
2877 case GetRegExpObjectLastIndex:
2878 makeHeapTopForNode(node);
2879 break;
2880
2881 case SetRegExpObjectLastIndex:
2882 case RecordRegExpCachedResult:
2883 break;
2884
2885 case GetFromArguments:
2886 makeHeapTopForNode(node);
2887 break;
2888
2889 case PutToArguments:
2890 break;
2891
2892 case GetArgument:
2893 makeHeapTopForNode(node);
2894 break;
2895
2896 case TryGetById:
2897 // FIXME: This should constant fold at least as well as the normal GetById case.
2898 // https://bugs.webkit.org/show_bug.cgi?id=156422
2899 makeHeapTopForNode(node);
2900 break;
2901
2902 case GetByIdDirect:
2903 case GetByIdDirectFlush:
2904 case GetById:
2905 case GetByIdFlush: {
2906 AbstractValue& value = forNode(node->child1());
2907 if (value.m_structure.isFinite()
2908 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
2909 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2910 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.toStructureSet(), uid);
2911 if (status.isSimple()) {
2912 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2913 // something more subtle?
2914 AbstractValue result;
2915 for (unsigned i = status.numVariants(); i--;) {
2916 // This thing won't give us a variant that involves prototypes. If it did, we'd
2917 // have more work to do here.
2918 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
2919
2920 result.merge(
2921 m_graph.inferredValueForProperty(
2922 value, status[i].offset(), m_state.structureClobberState()));
2923 }
2924
2925 m_state.setFoundConstants(true);
2926 didFoldClobberWorld();
2927 forNode(node) = result;
2928 break;
2929 }
2930 }
2931
2932 clobberWorld();
2933 makeHeapTopForNode(node);
2934 break;
2935 }
2936
2937 case GetByValWithThis:
2938 case GetByIdWithThis:
2939 clobberWorld();
2940 makeHeapTopForNode(node);
2941 break;
2942
2943 case GetArrayLength: {
2944 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2945 forNode(node->child1()).m_value, node->arrayMode());
2946 if (view) {
2947 setConstant(node, jsNumber(view->length()));
2948 break;
2949 }
2950 setNonCellTypeForNode(node, SpecInt32Only);
2951 break;
2952 }
2953
2954 case GetVectorLength: {
2955 setNonCellTypeForNode(node, SpecInt32Only);
2956 break;
2957 }
2958
2959 case DeleteById:
2960 case DeleteByVal: {
2961 // FIXME: This could decide if the delete will be successful based on the set of structures that
2962 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2963 clobberWorld();
2964 setNonCellTypeForNode(node, SpecBoolean);
2965 break;
2966 }
2967
2968 case CheckStructure: {
2969 AbstractValue& value = forNode(node->child1());
2970
2971 const RegisteredStructureSet& set = node->structureSet();
2972
2973 // It's interesting that we could have proven that the object has a larger structure set
2974 // that includes the set we're testing. In that case we could make the structure check
2975 // more efficient. We currently don't.
2976
2977 if (value.m_structure.isSubsetOf(set))
2978 m_state.setFoundConstants(true);
2979
2980 SpeculatedType admittedTypes = SpecNone;
2981 switch (node->child1().useKind()) {
2982 case CellUse:
2983 case KnownCellUse:
2984 admittedTypes = SpecNone;
2985 break;
2986 case CellOrOtherUse:
2987 admittedTypes = SpecOther;
2988 break;
2989 default:
2990 DFG_CRASH(m_graph, node, "Bad use kind");
2991 break;
2992 }
2993
2994 filter(value, set, admittedTypes);
2995 break;
2996 }
2997
2998 case CheckStructureOrEmpty: {
2999 AbstractValue& value = forNode(node->child1());
3000
3001 bool mayBeEmpty = value.m_type & SpecEmpty;
3002 if (!mayBeEmpty)
3003 m_state.setFoundConstants(true);
3004
3005 SpeculatedType admittedTypes = mayBeEmpty ? SpecEmpty : SpecNone;
3006 filter(value, node->structureSet(), admittedTypes);
3007 break;
3008 }
3009
3010 case CheckStructureImmediate: {
3011 // FIXME: This currently can only reason about one structure at a time.
3012 // https://bugs.webkit.org/show_bug.cgi?id=136988
3013
3014 AbstractValue& value = forNode(node->child1());
3015 const RegisteredStructureSet& set = node->structureSet();
3016
3017 if (value.value()) {
3018 if (Structure* structure = jsDynamicCast<Structure*>(m_vm, value.value())) {
3019 if (set.contains(m_graph.registerStructure(structure))) {
3020 m_state.setFoundConstants(true);
3021 break;
3022 }
3023 }
3024 m_state.setIsValid(false);
3025 break;
3026 }
3027
3028 if (m_phiChildren) {
3029 bool allGood = true;
3030 m_phiChildren->forAllTransitiveIncomingValues(
3031 node,
3032 [&] (Node* incoming) {
3033 if (Structure* structure = incoming->dynamicCastConstant<Structure*>(m_vm)) {
3034 if (set.contains(m_graph.registerStructure(structure)))
3035 return;
3036 }
3037 allGood = false;
3038 });
3039 if (allGood) {
3040 m_state.setFoundConstants(true);
3041 break;
3042 }
3043 }
3044
3045 if (RegisteredStructure structure = set.onlyStructure()) {
3046 filterByValue(node->child1(), *m_graph.freeze(structure.get()));
3047 break;
3048 }
3049
3050 // Aw shucks, we can't do anything!
3051 break;
3052 }
3053
3054 case PutStructure:
3055 if (!forNode(node->child1()).m_structure.isClear()) {
3056 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) {
3057 didFoldClobberStructures();
3058 m_state.setFoundConstants(true);
3059 } else {
3060 observeTransition(
3061 clobberLimit, node->transition()->previous, node->transition()->next);
3062 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
3063 }
3064 } else {
3065 // We're going to exit before we get here, but for the sake of validation, we've folded our write to StructureID.
3066 didFoldClobberStructures();
3067 }
3068 break;
3069 case GetButterfly:
3070 case AllocatePropertyStorage:
3071 case ReallocatePropertyStorage:
3072 case NukeStructureAndSetButterfly:
3073 // FIXME: We don't model the fact that the structureID is nuked, simply because currently
3074 // nobody would currently benefit from having that information. But it's a bug nonetheless.
3075 if (node->op() == NukeStructureAndSetButterfly)
3076 didFoldClobberStructures();
3077 clearForNode(node); // The result is not a JS value.
3078 break;
3079 case CheckSubClass: {
3080 JSValue constant = forNode(node->child1()).value();
3081 if (constant) {
3082 if (constant.isCell() && constant.asCell()->inherits(m_vm, node->classInfo())) {
3083 m_state.setFoundConstants(true);
3084 ASSERT(constant);
3085 break;
3086 }
3087 }
3088
3089 AbstractValue& value = forNode(node->child1());
3090
3091 if (value.m_structure.isSubClassOf(node->classInfo()))
3092 m_state.setFoundConstants(true);
3093
3094 filterClassInfo(value, node->classInfo());
3095 break;
3096 }
3097 case CallDOMGetter: {
3098 CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
3099 DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet;
3100 if (!snippet || snippet->effect.writes)
3101 clobberWorld();
3102 if (callDOMGetterData->domJIT)
3103 setTypeForNode(node, callDOMGetterData->domJIT->resultType());
3104 else
3105 makeBytecodeTopForNode(node);
3106 break;
3107 }
3108 case CallDOM: {
3109 const DOMJIT::Signature* signature = node->signature();
3110 if (signature->effect.writes)
3111 clobberWorld();
3112 setTypeForNode(node, signature->result);
3113 break;
3114 }
3115 case CheckArray: {
3116 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
3117 m_state.setFoundConstants(true);
3118 break;
3119 }
3120 switch (node->arrayMode().type()) {
3121 case Array::String:
3122 filter(node->child1(), SpecString);
3123 break;
3124 case Array::Int32:
3125 case Array::Double:
3126 case Array::Contiguous:
3127 case Array::Undecided:
3128 case Array::ArrayStorage:
3129 case Array::SlowPutArrayStorage:
3130 break;
3131 case Array::DirectArguments:
3132 filter(node->child1(), SpecDirectArguments);
3133 break;
3134 case Array::ScopedArguments:
3135 filter(node->child1(), SpecScopedArguments);
3136 break;
3137 case Array::Int8Array:
3138 filter(node->child1(), SpecInt8Array);
3139 break;
3140 case Array::Int16Array:
3141 filter(node->child1(), SpecInt16Array);
3142 break;
3143 case Array::Int32Array:
3144 filter(node->child1(), SpecInt32Array);
3145 break;
3146 case Array::Uint8Array:
3147 filter(node->child1(), SpecUint8Array);
3148 break;
3149 case Array::Uint8ClampedArray:
3150 filter(node->child1(), SpecUint8ClampedArray);
3151 break;
3152 case Array::Uint16Array:
3153 filter(node->child1(), SpecUint16Array);
3154 break;
3155 case Array::Uint32Array:
3156 filter(node->child1(), SpecUint32Array);
3157 break;
3158 case Array::Float32Array:
3159 filter(node->child1(), SpecFloat32Array);
3160 break;
3161 case Array::Float64Array:
3162 filter(node->child1(), SpecFloat64Array);
3163 break;
3164 case Array::AnyTypedArray:
3165 filter(node->child1(), SpecTypedArrayView);
3166 break;
3167 default:
3168 RELEASE_ASSERT_NOT_REACHED();
3169 break;
3170 }
3171 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
3172 break;
3173 }
3174 case Arrayify: {
3175 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
3176 didFoldClobberStructures();
3177 m_state.setFoundConstants(true);
3178 break;
3179 }
3180 ASSERT(node->arrayMode().conversion() == Array::Convert);
3181 clobberStructures();
3182 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
3183 break;
3184 }
3185 case ArrayifyToStructure: {
3186 AbstractValue& value = forNode(node->child1());
3187 if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
3188 m_state.setFoundConstants(true);
3189 clobberStructures();
3190
3191 // We have a bunch of options of how to express the abstract set at this point. Let set S
3192 // be the set of structures that the value had before clobbering and assume that all of
3193 // them are watchable. The new value should be the least expressible upper bound of the
3194 // intersection of "values that currently have structure = node->structure()" and "values
3195 // that have structure in S plus any structure transition-reachable from S". Assume that
3196 // node->structure() is not in S but it is transition-reachable from S. Then we would
3197 // like to say that the result is "values that have structure = node->structure() until
3198 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
3199 // we must choose between:
3200 //
3201 // 1) "values that currently have structure = node->structure()". This is a valid
3202 // superset of the value that we really want, and it's specific enough to satisfy the
3203 // preconditions of the array access that this is guarding. It's also specific enough
3204 // to allow relevant optimizations in the case that we didn't have a contradiction
3205 // like in this example. Notice that in the abscence of any contradiction, this result
3206 // is precise rather than being a conservative LUB.
3207 //
3208 // 2) "values that currently hava structure in S plus any structure transition-reachable
3209 // from S". This is also a valid superset of the value that we really want, but it's
3210 // not specific enough to satisfy the preconditions of the array access that this is
3211 // guarding - so playing such shenanigans would preclude us from having assertions on
3212 // the typing preconditions of any array accesses. This would also not be a desirable
3213 // answer in the absence of a contradiction.
3214 //
3215 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
3216 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
3217 // yet.
3218 forNode(node->child1()).set(m_graph, node->structure());
3219 break;
3220 }
3221 case GetIndexedPropertyStorage: {
3222 JSArrayBufferView* view = m_graph.tryGetFoldableView(
3223 forNode(node->child1()).m_value, node->arrayMode());
3224 if (view)
3225 m_state.setFoundConstants(true);
3226 clearForNode(node);
3227 break;
3228 }
3229 case ConstantStoragePointer: {
3230 clearForNode(node);
3231 break;
3232 }
3233
3234 case GetTypedArrayByteOffset: {
3235 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
3236 if (view) {
3237 setConstant(node, jsNumber(view->byteOffset()));
3238 break;
3239 }
3240 setNonCellTypeForNode(node, SpecInt32Only);
3241 break;
3242 }
3243
3244 case GetPrototypeOf: {
3245 AbstractValue& value = forNode(node->child1());
3246 if ((value.m_type && !(value.m_type & ~SpecObject)) && value.m_structure.isFinite()) {
3247 bool canFold = !value.m_structure.isClear();
3248 JSValue prototype;
3249 value.m_structure.forEach([&] (RegisteredStructure structure) {
3250 auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3251 MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3252 if (getPrototypeMethod != defaultGetPrototype) {
3253 canFold = false;
3254 return;
3255 }
3256
3257 if (structure->hasPolyProto()) {
3258 canFold = false;
3259 return;
3260 }
3261 if (!prototype)
3262 prototype = structure->storedPrototype();
3263 else if (prototype != structure->storedPrototype())
3264 canFold = false;
3265 });
3266
3267 if (prototype && canFold) {
3268 switch (node->child1().useKind()) {
3269 case ArrayUse:
3270 case FunctionUse:
3271 case FinalObjectUse:
3272 break;
3273 default:
3274 didFoldClobberWorld();
3275 break;
3276 }
3277 setConstant(node, *m_graph.freeze(prototype));
3278 break;
3279 }
3280 }
3281
3282 switch (node->child1().useKind()) {
3283 case ArrayUse:
3284 case FunctionUse:
3285 case FinalObjectUse:
3286 break;
3287 default:
3288 clobberWorld();
3289 break;
3290 }
3291 setTypeForNode(node, SpecObject | SpecOther);
3292 break;
3293 }
3294
3295 case GetByOffset: {
3296 StorageAccessData& data = node->storageAccessData();
3297
3298 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
3299 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
3300 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
3301 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
3302 // on the type that ByteCodeParser was able to prove.
3303 AbstractValue value = m_graph.inferredValueForProperty(
3304 forNode(node->child2()), data.offset, m_state.structureClobberState());
3305
3306 // If we decide that there does not exist any value that this can return, then it's probably
3307 // because the compilation was already invalidated.
3308 if (value.isClear())
3309 m_state.setIsValid(false);
3310
3311 setForNode(node, value);
3312 if (value.m_value)
3313 m_state.setFoundConstants(true);
3314 break;
3315 }
3316
3317 case GetGetterSetterByOffset: {
3318 StorageAccessData& data = node->storageAccessData();
3319 AbstractValue base = forNode(node->child2());
3320 JSValue result = m_graph.tryGetConstantProperty(base, data.offset);
3321 if (result && jsDynamicCast<GetterSetter*>(m_vm, result)) {
3322 setConstant(node, *m_graph.freeze(result));
3323 break;
3324 }
3325
3326 if (base.value() && base.value().isObject()) {
3327 setForNode(node, asObject(base.value())->globalObject()->getterSetterStructure());
3328 break;
3329 }
3330
3331 setTypeForNode(node, SpecObjectOther);
3332 break;
3333 }
3334
3335 case MultiGetByOffset: {
3336 // This code will filter the base value in a manner that is possibly different (either more
3337 // or less precise) than the way it would be filtered if this was strength-reduced to a
3338 // CheckStructure. This is fine. It's legal for different passes over the code to prove
3339 // different things about the code, so long as all of them are sound. That even includes
3340 // one guy proving that code should never execute (due to a contradiction) and another guy
3341 // not finding that contradiction. If someone ever proved that there would be a
3342 // contradiction then there must always be a contradiction even if subsequent passes don't
3343 // realize it. This is the case here.
3344
3345 // Ordinarily you have to be careful with calling setFoundConstants()
3346 // because of the effect on compile times, but this node is FTL-only.
3347 m_state.setFoundConstants(true);
3348
3349 AbstractValue base = forNode(node->child1());
3350 RegisteredStructureSet baseSet;
3351 AbstractValue result;
3352 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
3353 RegisteredStructureSet set = getCase.set();
3354 set.filter(base);
3355 if (set.isEmpty())
3356 continue;
3357 baseSet.merge(set);
3358
3359 switch (getCase.method().kind()) {
3360 case GetByOffsetMethod::Constant: {
3361 AbstractValue thisResult;
3362 thisResult.set(
3363 m_graph,
3364 *getCase.method().constant(),
3365 m_state.structureClobberState());
3366 result.merge(thisResult);
3367 break;
3368 }
3369
3370 default: {
3371 result.makeHeapTop();
3372 break;
3373 } }
3374 }
3375
3376 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
3377 m_state.setIsValid(false);
3378
3379 setForNode(node, result);
3380 break;
3381 }
3382
3383 case PutByOffset: {
3384 break;
3385 }
3386
3387 case MultiPutByOffset: {
3388 RegisteredStructureSet newSet;
3389 TransitionVector transitions;
3390
3391 // Ordinarily you have to be careful with calling setFoundConstants()
3392 // because of the effect on compile times, but this node is FTL-only.
3393 m_state.setFoundConstants(true);
3394
3395 AbstractValue base = forNode(node->child1());
3396 AbstractValue originalValue = forNode(node->child2());
3397 AbstractValue resultingValue;
3398
3399 if (node->multiPutByOffsetData().writesStructures())
3400 didFoldClobberStructures();
3401
3402 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
3403 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
3404 RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
3405 thisSet.filter(base);
3406 if (thisSet.isEmpty())
3407 continue;
3408
3409 AbstractValue thisValue = originalValue;
3410 resultingValue.merge(thisValue);
3411
3412 if (variant.kind() == PutByIdVariant::Transition) {
3413 RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
3414 if (thisSet.onlyStructure() != newStructure) {
3415 transitions.append(
3416 Transition(m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
3417 } // else this is really a replace.
3418 newSet.add(newStructure);
3419 } else {
3420 ASSERT(variant.kind() == PutByIdVariant::Replace);
3421 newSet.merge(thisSet);
3422 }
3423 }
3424
3425 // We need to order AI executing these effects in the same order as they're executed
3426 // at runtime. This is critical when you have JS code like `o.f = o;`. We first
3427 // filter types on o, then transition o. Not the other way around. If we got
3428 // this ordering wrong, we could end up with the wrong type representing o.
3429 setForNode(node->child2(), resultingValue);
3430 if (!!originalValue && !resultingValue)
3431 m_state.setIsValid(false);
3432
3433 observeTransitions(clobberLimit, transitions);
3434 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
3435 m_state.setIsValid(false);
3436 break;
3437 }
3438
3439 case GetExecutable: {
3440 JSValue value = forNode(node->child1()).value();
3441 if (value) {
3442 JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, value);
3443 if (function) {
3444 setConstant(node, *m_graph.freeze(function->executable()));
3445 break;
3446 }
3447 }
3448 setTypeForNode(node, SpecCellOther);
3449 break;
3450 }
3451
3452 case CheckCell: {
3453 JSValue value = forNode(node->child1()).value();
3454 if (value == node->cellOperand()->value()) {
3455 m_state.setFoundConstants(true);
3456 ASSERT(value);
3457 break;
3458 }
3459 filterByValue(node->child1(), *node->cellOperand());
3460 break;
3461 }
3462
3463 case AssertNotEmpty:
3464 case CheckNotEmpty: {
3465 AbstractValue& value = forNode(node->child1());
3466 if (!(value.m_type & SpecEmpty)) {
3467 m_state.setFoundConstants(true);
3468 break;
3469 }
3470
3471 filter(value, ~SpecEmpty);
3472 break;
3473 }
3474
3475 case CheckStringIdent: {
3476 AbstractValue& value = forNode(node->child1());
3477 UniquedStringImpl* uid = node->uidOperand();
3478 ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
3479
3480 JSValue childConstant = value.value();
3481 if (childConstant) {
3482 ASSERT(childConstant.isString());
3483 if (asString(childConstant)->tryGetValueImpl() == uid) {
3484 m_state.setFoundConstants(true);
3485 break;
3486 }
3487 }
3488
3489 filter(value, SpecStringIdent);
3490 break;
3491 }
3492
3493 case CheckInBounds: {
3494 JSValue left = forNode(node->child1()).value();
3495 JSValue right = forNode(node->child2()).value();
3496 if (left && right && left.isInt32() && right.isInt32() && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32()))
3497 m_state.setFoundConstants(true);
3498
3499 // We claim we result in Int32. It's not really important what our result is (though we
3500 // don't want to claim we may result in the empty value), other nodes with data flow edges
3501 // to us just do that to maintain the invariant that they can't be hoisted higher than us.
3502 // So we just arbitrarily pick Int32. In some ways, StorageResult may be the more correct
3503 // thing to do here. We pick NodeResultJS because it makes converting this to an identity
3504 // easier.
3505 setNonCellTypeForNode(node, SpecInt32Only);
3506 break;
3507 }
3508
3509 case PutById:
3510 case PutByIdFlush:
3511 case PutByIdDirect: {
3512 AbstractValue& value = forNode(node->child1());
3513 if (value.m_structure.isFinite()) {
3514 PutByIdStatus status = PutByIdStatus::computeFor(
3515 m_graph.globalObjectFor(node->origin.semantic),
3516 value.m_structure.toStructureSet(),
3517 m_graph.identifiers()[node->identifierNumber()],
3518 node->op() == PutByIdDirect);
3519
3520 if (status.isSimple()) {
3521 RegisteredStructureSet newSet;
3522 TransitionVector transitions;
3523
3524 for (unsigned i = status.numVariants(); i--;) {
3525 const PutByIdVariant& variant = status[i];
3526 if (variant.kind() == PutByIdVariant::Transition) {
3527 RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
3528 transitions.append(
3529 Transition(
3530 m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
3531 newSet.add(newStructure);
3532 } else {
3533 ASSERT(variant.kind() == PutByIdVariant::Replace);
3534 newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
3535 }
3536 }
3537
3538 if (status.numVariants() == 1 || m_graph.m_plan.isFTL())
3539 m_state.setFoundConstants(true);
3540
3541 didFoldClobberWorld();
3542 observeTransitions(clobberLimit, transitions);
3543 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
3544 m_state.setIsValid(false);
3545 break;
3546 }
3547 }
3548
3549 clobberWorld();
3550 break;
3551 }
3552
3553 case PutByValWithThis:
3554 case PutByIdWithThis:
3555 clobberWorld();
3556 break;
3557
3558 case PutGetterById:
3559 case PutSetterById:
3560 case PutGetterSetterById:
3561 case PutGetterByVal:
3562 case PutSetterByVal: {
3563 clobberWorld();
3564 break;
3565 }
3566
3567 case DefineDataProperty:
3568 case DefineAccessorProperty:
3569 clobberWorld();
3570 break;
3571
3572 case InById: {
3573 // FIXME: We can determine when the property definitely exists based on abstract
3574 // value information.
3575 clobberWorld();
3576 filter(node->child1(), SpecObject);
3577 setNonCellTypeForNode(node, SpecBoolean);
3578 break;
3579 }
3580
3581 case InByVal: {
3582 AbstractValue& property = forNode(node->child2());
3583 if (JSValue constant = property.value()) {
3584 if (constant.isString()) {
3585 JSString* string = asString(constant);
3586 const StringImpl* impl = string->tryGetValueImpl();
3587 if (impl && impl->isAtom())
3588 m_state.setFoundConstants(true);
3589 }
3590 }
3591
3592 // FIXME: We can determine when the property definitely exists based on abstract
3593 // value information.
3594 clobberWorld();
3595 filter(node->child1(), SpecObject);
3596 setNonCellTypeForNode(node, SpecBoolean);
3597 break;
3598 }
3599
3600 case HasOwnProperty: {
3601 clobberWorld();
3602 setNonCellTypeForNode(node, SpecBoolean);
3603 break;
3604 }
3605
3606 case GetEnumerableLength: {
3607 setNonCellTypeForNode(node, SpecInt32Only);
3608 break;
3609 }
3610 case HasGenericProperty: {
3611 setNonCellTypeForNode(node, SpecBoolean);
3612 clobberWorld();
3613 break;
3614 }
3615 case HasStructureProperty: {
3616 setNonCellTypeForNode(node, SpecBoolean);
3617 clobberWorld();
3618 break;
3619 }
3620 case HasIndexedProperty: {
3621 ArrayMode mode = node->arrayMode();
3622 switch (mode.type()) {
3623 case Array::Int32:
3624 case Array::Double:
3625 case Array::Contiguous:
3626 case Array::ArrayStorage: {
3627 break;
3628 }
3629 default: {
3630 clobberWorld();
3631 break;
3632 }
3633 }
3634 setNonCellTypeForNode(node, SpecBoolean);
3635 break;
3636 }
3637 case GetDirectPname: {
3638 clobberWorld();
3639 makeHeapTopForNode(node);
3640 break;
3641 }
3642 case GetPropertyEnumerator: {
3643 setTypeForNode(node, SpecCell);
3644 clobberWorld();
3645 break;
3646 }
3647 case GetEnumeratorStructurePname: {
3648 setTypeForNode(node, SpecString | SpecOther);
3649 break;
3650 }
3651 case GetEnumeratorGenericPname: {
3652 setTypeForNode(node, SpecString | SpecOther);
3653 break;
3654 }
3655 case ToIndexString: {
3656 setTypeForNode(node, SpecString);
3657 break;
3658 }
3659
3660 case GetGlobalVar:
3661 makeHeapTopForNode(node);
3662 break;
3663
3664 case GetGlobalLexicalVariable:
3665 makeBytecodeTopForNode(node);
3666 break;
3667
3668 case GetDynamicVar:
3669 clobberWorld();
3670 makeBytecodeTopForNode(node);
3671 break;
3672
3673 case PutDynamicVar:
3674 clobberWorld();
3675 break;
3676
3677 case ResolveScope:
3678 clobberWorld();
3679 setTypeForNode(node, SpecObject);
3680 break;
3681
3682 case ResolveScopeForHoistingFuncDeclInEval:
3683 clobberWorld();
3684 makeBytecodeTopForNode(node);
3685 break;
3686
3687 case PutGlobalVariable:
3688 case NotifyWrite:
3689 break;
3690
3691 case OverridesHasInstance:
3692 setNonCellTypeForNode(node, SpecBoolean);
3693 break;
3694
3695 case InstanceOf:
3696 clobberWorld();
3697 setNonCellTypeForNode(node, SpecBoolean);
3698 break;
3699
3700 case InstanceOfCustom:
3701 clobberWorld();
3702 setNonCellTypeForNode(node, SpecBoolean);
3703 break;
3704
3705 case MatchStructure: {
3706 AbstractValue base = forNode(node->child1());
3707 RegisteredStructureSet baseSet;
3708
3709 BooleanLattice result = BooleanLattice::Bottom;
3710 for (MatchStructureVariant& variant : node->matchStructureData().variants) {
3711 RegisteredStructure structure = variant.structure;
3712 if (!base.contains(structure)) {
3713 m_state.setFoundConstants(true);
3714 continue;
3715 }
3716
3717 baseSet.add(structure);
3718 result = leastUpperBoundOfBooleanLattices(
3719 result, variant.result ? BooleanLattice::True : BooleanLattice::False);
3720 }
3721
3722 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
3723 m_state.setIsValid(false);
3724
3725 switch (result) {
3726 case BooleanLattice::False:
3727 setConstant(node, jsBoolean(false));
3728 break;
3729 case BooleanLattice::True:
3730 setConstant(node, jsBoolean(true));
3731 break;
3732 default:
3733 setNonCellTypeForNode(node, SpecBoolean);
3734 break;
3735 }
3736 break;
3737 }
3738
3739 case Phi:
3740 RELEASE_ASSERT(m_graph.m_form == SSA);
3741 setForNode(node, forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow)));
3742 // The state of this node would have already been decided, but it may have become a
3743 // constant, in which case we'd like to know.
3744 if (forNode(node).m_value)
3745 m_state.setFoundConstants(true);
3746 break;
3747
3748 case Upsilon: {
3749 NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
3750 if (shadow.isStillValid()) {
3751 m_state.createValueForNode(shadow);
3752 setForNode(shadow, forNode(node->child1()));
3753 }
3754 break;
3755 }
3756
3757 case Flush:
3758 case PhantomLocal:
3759 break;
3760
3761 case Call:
3762 case TailCallInlinedCaller:
3763 case Construct:
3764 case CallVarargs:
3765 case CallForwardVarargs:
3766 case TailCallVarargsInlinedCaller:
3767 case ConstructVarargs:
3768 case ConstructForwardVarargs:
3769 case TailCallForwardVarargsInlinedCaller:
3770 case CallEval:
3771 case DirectCall:
3772 case DirectConstruct:
3773 case DirectTailCallInlinedCaller:
3774 clobberWorld();
3775 makeHeapTopForNode(node);
3776 break;
3777
3778 case ForceOSRExit:
3779 case CheckBadCell:
3780 m_state.setIsValid(false);
3781 break;
3782
3783 case InvalidationPoint:
3784 m_state.setStructureClobberState(StructuresAreWatched);
3785 m_state.observeInvalidationPoint();
3786 break;
3787
3788 case CPUIntrinsic:
3789 if (node->intrinsic() == CPURdtscIntrinsic)
3790 setNonCellTypeForNode(node, SpecInt32Only);
3791 else
3792 setNonCellTypeForNode(node, SpecOther);
3793 break;
3794
3795 case CheckTraps:
3796 case LogShadowChickenPrologue:
3797 case LogShadowChickenTail:
3798 case ProfileType:
3799 case ProfileControlFlow:
3800 case Phantom:
3801 case CountExecution:
3802 case CheckTierUpInLoop:
3803 case CheckTierUpAtReturn:
3804 case SuperSamplerBegin:
3805 case SuperSamplerEnd:
3806 case CheckTierUpAndOSREnter:
3807 case LoopHint:
3808 case ZombieHint:
3809 case ExitOK:
3810 case FilterCallLinkStatus:
3811 case FilterGetByIdStatus:
3812 case FilterPutByIdStatus:
3813 case FilterInByIdStatus:
3814 case ClearCatchLocals:
3815 break;
3816
3817 case CheckTypeInfoFlags: {
3818 const AbstractValue& abstractValue = forNode(node->child1());
3819 unsigned bits = node->typeInfoOperand();
3820 ASSERT(bits);
3821 if (bits == ImplementsDefaultHasInstance) {
3822 if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
3823 m_state.setFoundConstants(true);
3824 break;
3825 }
3826 }
3827
3828 if (JSValue value = abstractValue.value()) {
3829 if (value.isCell()) {
3830 // This works because if we see a cell here, we know it's fully constructed
3831 // and we can read its inline type info flags. These flags don't change over the
3832 // object's lifetime.
3833 if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
3834 m_state.setFoundConstants(true);
3835 break;
3836 }
3837 }
3838 }
3839
3840 if (abstractValue.m_structure.isFinite()) {
3841 bool ok = true;
3842 abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
3843 ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
3844 });
3845 if (ok) {
3846 m_state.setFoundConstants(true);
3847 break;
3848 }
3849 }
3850
3851 break;
3852 }
3853
3854 case ParseInt: {
3855 AbstractValue value = forNode(node->child1());
3856 if (value.m_type && !(value.m_type & ~SpecInt32Only)) {
3857 JSValue radix;
3858 if (!node->child2())
3859 radix = jsNumber(0);
3860 else
3861 radix = forNode(node->child2()).m_value;
3862
3863 if (radix.isNumber()
3864 && (radix.asNumber() == 0 || radix.asNumber() == 10)) {
3865 m_state.setFoundConstants(true);
3866 if (node->child1().useKind() == UntypedUse)
3867 didFoldClobberWorld();
3868 setNonCellTypeForNode(node, SpecInt32Only);
3869 break;
3870 }
3871 }
3872
3873 if (node->child1().useKind() == UntypedUse)
3874 clobberWorld();
3875 setNonCellTypeForNode(node, SpecBytecodeNumber);
3876 break;
3877 }
3878
3879 case CreateRest:
3880 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
3881 // This means we're already having a bad time.
3882 clobberWorld();
3883 setTypeForNode(node, SpecArray);
3884 break;
3885 }
3886 setForNode(node,
3887 m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
3888 break;
3889
3890 case CheckVarargs:
3891 case Check: {
3892 // Simplify out checks that don't actually do checking.
3893 m_graph.doToChildren(node, [&] (Edge edge) {
3894 if (!edge)
3895 return;
3896 if (edge.isProved() || edge.willNotHaveCheck())
3897 m_state.setFoundConstants(true);
3898 });
3899 break;
3900 }
3901
3902 case SetFunctionName: {
3903 clobberWorld();
3904 break;
3905 }
3906
3907 case StoreBarrier:
3908 case FencedStoreBarrier: {
3909 filter(node->child1(), SpecCell);
3910 break;
3911 }
3912
3913 case DataViewGetInt: {
3914 DataViewData data = node->dataViewData();
3915 if (data.byteSize < 4)
3916 setNonCellTypeForNode(node, SpecInt32Only);
3917 else {
3918 ASSERT(data.byteSize == 4);
3919 if (data.isSigned)
3920 setNonCellTypeForNode(node, SpecInt32Only);
3921 else
3922 setNonCellTypeForNode(node, SpecInt52Any);
3923 }
3924 break;
3925 }
3926
3927 case DataViewGetFloat: {
3928 setNonCellTypeForNode(node, SpecFullDouble);
3929 break;
3930 }
3931
3932 case DataViewSet: {
3933 break;
3934 }
3935
3936 case Unreachable:
3937 // It may be that during a previous run of AI we proved that something was unreachable, but
3938 // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
3939 // monotonically stronger over time. So, we don't assert that AI doesn't reach the
3940 // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
3941 // crash whenever AI fails to be as powerful on run K as it was on run K-1.
3942 m_state.setIsValid(false);
3943 break;
3944
3945 case LastNodeType:
3946 case ArithIMul:
3947 case FiatInt52:
3948 DFG_CRASH(m_graph, node, "Unexpected node type");
3949 break;
3950 }
3951
3952 return m_state.isValid();
3953}
3954
3955template<typename AbstractStateType>
3956void AbstractInterpreter<AbstractStateType>::filterICStatus(Node* node)
3957{
3958 switch (node->op()) {
3959 case FilterCallLinkStatus:
3960 if (JSValue value = forNode(node->child1()).m_value)
3961 node->callLinkStatus()->filter(m_vm, value);
3962 break;
3963
3964 case FilterGetByIdStatus: {
3965 AbstractValue& value = forNode(node->child1());
3966 if (value.m_structure.isFinite())
3967 node->getByIdStatus()->filter(value.m_structure.toStructureSet());
3968 break;
3969 }
3970
3971 case FilterInByIdStatus: {
3972 AbstractValue& value = forNode(node->child1());
3973 if (value.m_structure.isFinite())
3974 node->inByIdStatus()->filter(value.m_structure.toStructureSet());
3975 break;
3976 }
3977
3978 case FilterPutByIdStatus: {
3979 AbstractValue& value = forNode(node->child1());
3980 if (value.m_structure.isFinite())
3981 node->putByIdStatus()->filter(value.m_structure.toStructureSet());
3982 break;
3983 }
3984
3985 default:
3986 RELEASE_ASSERT_NOT_REACHED();
3987 break;
3988 }
3989}
3990
3991template<typename AbstractStateType>
3992bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
3993{
3994 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
3995}
3996
3997template<typename AbstractStateType>
3998bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
3999{
4000 Node* node = m_state.block()->at(indexInBlock);
4001
4002 startExecuting();
4003 executeEdges(node);
4004 return executeEffects(indexInBlock, node);
4005}
4006
4007template<typename AbstractStateType>
4008bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
4009{
4010 startExecuting();
4011 executeEdges(node);
4012 return executeEffects(UINT_MAX, node);
4013}
4014
4015template<typename AbstractStateType>
4016void AbstractInterpreter<AbstractStateType>::clobberWorld()
4017{
4018 clobberStructures();
4019}
4020
4021template<typename AbstractStateType>
4022void AbstractInterpreter<AbstractStateType>::didFoldClobberWorld()
4023{
4024 didFoldClobberStructures();
4025}
4026
4027template<typename AbstractStateType>
4028template<typename Functor>
4029void AbstractInterpreter<AbstractStateType>::forAllValues(
4030 unsigned clobberLimit, Functor& functor)
4031{
4032 if (clobberLimit >= m_state.block()->size())
4033 clobberLimit = m_state.block()->size();
4034 else
4035 clobberLimit++;
4036 ASSERT(clobberLimit <= m_state.block()->size());
4037 for (size_t i = clobberLimit; i--;) {
4038 NodeFlowProjection::forEach(
4039 m_state.block()->at(i),
4040 [&] (NodeFlowProjection nodeProjection) {
4041 functor(forNode(nodeProjection));
4042 });
4043 }
4044 if (m_graph.m_form == SSA) {
4045 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
4046 if (node.isStillValid())
4047 functor(forNode(node));
4048 }
4049 }
4050 for (size_t i = m_state.numberOfArguments(); i--;)
4051 functor(m_state.argument(i));
4052 for (size_t i = m_state.numberOfLocals(); i--;)
4053 functor(m_state.local(i));
4054}
4055
4056template<typename AbstractStateType>
4057void AbstractInterpreter<AbstractStateType>::clobberStructures()
4058{
4059 m_state.clobberStructures();
4060 m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures);
4061 m_state.setStructureClobberState(StructuresAreClobbered);
4062}
4063
4064template<typename AbstractStateType>
4065void AbstractInterpreter<AbstractStateType>::didFoldClobberStructures()
4066{
4067 m_state.mergeClobberState(AbstractInterpreterClobberState::FoldedClobber);
4068}
4069
4070template<typename AbstractStateType>
4071void AbstractInterpreter<AbstractStateType>::observeTransition(
4072 unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
4073{
4074 AbstractValue::TransitionObserver transitionObserver(from, to);
4075 forAllValues(clobberLimit, transitionObserver);
4076
4077 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.
4078
4079 m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
4080}
4081
4082template<typename AbstractStateType>
4083void AbstractInterpreter<AbstractStateType>::observeTransitions(
4084 unsigned clobberLimit, const TransitionVector& vector)
4085{
4086 if (vector.isEmpty())
4087 return;
4088
4089 AbstractValue::TransitionsObserver transitionsObserver(vector);
4090 forAllValues(clobberLimit, transitionsObserver);
4091
4092 if (!ASSERT_DISABLED) {
4093 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
4094 for (unsigned i = vector.size(); i--;)
4095 ASSERT(!vector[i].previous->dfgShouldWatch());
4096 }
4097
4098 m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
4099}
4100
4101template<typename AbstractStateType>
4102void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
4103{
4104 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
4105}
4106
4107template<typename AbstractStateType>
4108void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
4109{
4110 CommaPrinter comma(" ");
4111 HashSet<NodeFlowProjection> seen;
4112 if (m_graph.m_form == SSA) {
4113 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
4114 seen.add(node);
4115 AbstractValue& value = forNode(node);
4116 if (value.isClear())
4117 continue;
4118 out.print(comma, node, ":", value);
4119 }
4120 }
4121 for (size_t i = 0; i < m_state.block()->size(); ++i) {
4122 NodeFlowProjection::forEach(
4123 m_state.block()->at(i), [&] (NodeFlowProjection nodeProjection) {
4124 seen.add(nodeProjection);
4125 AbstractValue& value = forNode(nodeProjection);
4126 if (value.isClear())
4127 return;
4128 out.print(comma, nodeProjection, ":", value);
4129 });
4130 }
4131 if (m_graph.m_form == SSA) {
4132 for (NodeFlowProjection node : m_state.block()->ssa->liveAtTail) {
4133 if (seen.contains(node))
4134 continue;
4135 AbstractValue& value = forNode(node);
4136 if (value.isClear())
4137 continue;
4138 out.print(comma, node, ":", value);
4139 }
4140 }
4141}
4142
4143template<typename AbstractStateType>
4144FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
4145 AbstractValue& value, const RegisteredStructureSet& set, SpeculatedType admittedTypes)
4146{
4147 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
4148 return FiltrationOK;
4149 m_state.setIsValid(false);
4150 return Contradiction;
4151}
4152
4153template<typename AbstractStateType>
4154FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
4155 AbstractValue& value, ArrayModes arrayModes)
4156{
4157 if (value.filterArrayModes(arrayModes) == FiltrationOK)
4158 return FiltrationOK;
4159 m_state.setIsValid(false);
4160 return Contradiction;
4161}
4162
4163template<typename AbstractStateType>
4164FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
4165 AbstractValue& value, SpeculatedType type)
4166{
4167 if (value.filter(type) == FiltrationOK)
4168 return FiltrationOK;
4169 m_state.setIsValid(false);
4170 return Contradiction;
4171}
4172
4173template<typename AbstractStateType>
4174FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
4175 AbstractValue& abstractValue, FrozenValue concreteValue)
4176{
4177 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
4178 return FiltrationOK;
4179 m_state.setIsValid(false);
4180 return Contradiction;
4181}
4182
4183template<typename AbstractStateType>
4184FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo(
4185 AbstractValue& value, const ClassInfo* classInfo)
4186{
4187 if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK)
4188 return FiltrationOK;
4189 m_state.setIsValid(false);
4190 return Contradiction;
4191}
4192
4193template<typename AbstractStateType>
4194void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
4195{
4196 JSValue child = forNode(node->child1()).value();
4197 if (Optional<double> number = child.toNumberFromPrimitive()) {
4198 if (node->child1().useKind() != DoubleRepUse)
4199 didFoldClobberWorld();
4200 setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
4201 return;
4202 }
4203 SpeculatedType type;
4204 if (node->child1().useKind() == DoubleRepUse)
4205 type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
4206 else {
4207 clobberWorld();
4208 type = SpecBytecodeNumber;
4209 }
4210 setNonCellTypeForNode(node, type);
4211}
4212
4213} } // namespace JSC::DFG
4214
4215#endif // ENABLE(DFG_JIT)
4216