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)));
503 break;
504 case BitLShift:
505 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
506 break;
507 case BitURShift:
508 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
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 ValueMul: {
906 if (node->binaryUseKind() == BigIntUse)
907 setTypeForNode(node, SpecBigInt);
908 else {
909 clobberWorld();
910 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
911 }
912 break;
913 }
914
915 case ArithMul: {
916 JSValue left = forNode(node->child1()).value();
917 JSValue right = forNode(node->child2()).value();
918 switch (node->binaryUseKind()) {
919 case Int32Use:
920 if (left && right && left.isInt32() && right.isInt32()) {
921 if (!shouldCheckOverflow(node->arithMode())) {
922 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
923 break;
924 }
925 double doubleResult = left.asNumber() * right.asNumber();
926 if (!shouldCheckNegativeZero(node->arithMode()))
927 doubleResult += 0; // Sanitizes zero.
928 JSValue valueResult = jsNumber(doubleResult);
929 if (valueResult.isInt32()) {
930 setConstant(node, valueResult);
931 break;
932 }
933 }
934 setNonCellTypeForNode(node, SpecInt32Only);
935 break;
936 case Int52RepUse:
937 if (left && right && left.isAnyInt() && right.isAnyInt()) {
938 double doubleResult = left.asNumber() * right.asNumber();
939 if (!shouldCheckNegativeZero(node->arithMode()))
940 doubleResult += 0;
941 JSValue valueResult = jsNumber(doubleResult);
942 if (valueResult.isAnyInt()) {
943 setConstant(node, valueResult);
944 break;
945 }
946 }
947 setNonCellTypeForNode(node, SpecInt52Any);
948 break;
949 case DoubleRepUse:
950 if (left && right && left.isNumber() && right.isNumber()) {
951 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
952 break;
953 }
954 setNonCellTypeForNode(node,
955 typeOfDoubleProduct(
956 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
957 break;
958 default:
959 RELEASE_ASSERT_NOT_REACHED();
960 break;
961 }
962 break;
963 }
964
965 case ValueMod:
966 case ValueDiv: {
967 if (handleConstantDivOp(node))
968 break;
969
970 if (node->binaryUseKind() == BigIntUse)
971 setTypeForNode(node, SpecBigInt);
972 else {
973 clobberWorld();
974 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
975 }
976 break;
977 }
978
979 case ArithMod:
980 case ArithDiv: {
981 if (handleConstantDivOp(node))
982 break;
983
984 switch (node->binaryUseKind()) {
985 case Int32Use:
986 setNonCellTypeForNode(node, SpecInt32Only);
987 break;
988 case DoubleRepUse:
989 if (node->op() == ArithDiv) {
990 setNonCellTypeForNode(node,
991 typeOfDoubleQuotient(
992 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
993 } else {
994 setNonCellTypeForNode(node,
995 typeOfDoubleBinaryOp(
996 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
997 }
998
999 break;
1000 default:
1001 RELEASE_ASSERT_NOT_REACHED();
1002 break;
1003 }
1004 break;
1005 }
1006
1007 case ArithMin: {
1008 JSValue left = forNode(node->child1()).value();
1009 JSValue right = forNode(node->child2()).value();
1010 switch (node->binaryUseKind()) {
1011 case Int32Use:
1012 if (left && right && left.isInt32() && right.isInt32()) {
1013 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
1014 break;
1015 }
1016 setNonCellTypeForNode(node, SpecInt32Only);
1017 break;
1018 case DoubleRepUse:
1019 if (left && right && left.isNumber() && right.isNumber()) {
1020 double a = left.asNumber();
1021 double b = right.asNumber();
1022 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
1023 break;
1024 }
1025 setNonCellTypeForNode(node,
1026 typeOfDoubleMinMax(
1027 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1028 break;
1029 default:
1030 RELEASE_ASSERT_NOT_REACHED();
1031 break;
1032 }
1033 break;
1034 }
1035
1036 case ArithMax: {
1037 JSValue left = forNode(node->child1()).value();
1038 JSValue right = forNode(node->child2()).value();
1039 switch (node->binaryUseKind()) {
1040 case Int32Use:
1041 if (left && right && left.isInt32() && right.isInt32()) {
1042 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
1043 break;
1044 }
1045 setNonCellTypeForNode(node, SpecInt32Only);
1046 break;
1047 case DoubleRepUse:
1048 if (left && right && left.isNumber() && right.isNumber()) {
1049 double a = left.asNumber();
1050 double b = right.asNumber();
1051 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
1052 break;
1053 }
1054 setNonCellTypeForNode(node,
1055 typeOfDoubleMinMax(
1056 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1057 break;
1058 default:
1059 RELEASE_ASSERT_NOT_REACHED();
1060 break;
1061 }
1062 break;
1063 }
1064
1065 case ArithAbs: {
1066 JSValue child = forNode(node->child1()).value();
1067 switch (node->child1().useKind()) {
1068 case Int32Use:
1069 if (Optional<double> number = child.toNumberFromPrimitive()) {
1070 JSValue result = jsNumber(fabs(*number));
1071 if (result.isInt32()) {
1072 setConstant(node, result);
1073 break;
1074 }
1075 }
1076 setNonCellTypeForNode(node, SpecInt32Only);
1077 break;
1078 case DoubleRepUse:
1079 if (Optional<double> number = child.toNumberFromPrimitive()) {
1080 setConstant(node, jsDoubleNumber(fabs(*number)));
1081 break;
1082 }
1083 setNonCellTypeForNode(node, typeOfDoubleAbs(forNode(node->child1()).m_type));
1084 break;
1085 default:
1086 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
1087 clobberWorld();
1088 setNonCellTypeForNode(node, SpecBytecodeNumber);
1089 break;
1090 }
1091 break;
1092 }
1093
1094 case ArithPow: {
1095 JSValue childY = forNode(node->child2()).value();
1096 if (childY && childY.isNumber()) {
1097 if (!childY.asNumber()) {
1098 setConstant(node, jsDoubleNumber(1));
1099 break;
1100 }
1101
1102 JSValue childX = forNode(node->child1()).value();
1103 if (childX && childX.isNumber()) {
1104 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
1105 break;
1106 }
1107 }
1108 setNonCellTypeForNode(node, typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
1109 break;
1110 }
1111
1112 case ArithRandom: {
1113 setNonCellTypeForNode(node, SpecDoubleReal);
1114 break;
1115 }
1116
1117 case ArithRound:
1118 case ArithFloor:
1119 case ArithCeil:
1120 case ArithTrunc: {
1121 JSValue operand = forNode(node->child1()).value();
1122 if (Optional<double> number = operand.toNumberFromPrimitive()) {
1123 if (node->child1().useKind() != DoubleRepUse)
1124 didFoldClobberWorld();
1125
1126 double roundedValue = 0;
1127 if (node->op() == ArithRound)
1128 roundedValue = jsRound(*number);
1129 else if (node->op() == ArithFloor)
1130 roundedValue = floor(*number);
1131 else if (node->op() == ArithCeil)
1132 roundedValue = ceil(*number);
1133 else {
1134 ASSERT(node->op() == ArithTrunc);
1135 roundedValue = trunc(*number);
1136 }
1137
1138 if (node->child1().useKind() == UntypedUse) {
1139 setConstant(node, jsNumber(roundedValue));
1140 break;
1141 }
1142 if (producesInteger(node->arithRoundingMode())) {
1143 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
1144 if (roundedValueAsInt32 == roundedValue) {
1145 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
1146 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
1147 setConstant(node, jsNumber(roundedValueAsInt32));
1148 break;
1149 }
1150 } else {
1151 setConstant(node, jsNumber(roundedValueAsInt32));
1152 break;
1153 }
1154 }
1155 } else {
1156 setConstant(node, jsDoubleNumber(roundedValue));
1157 break;
1158 }
1159 }
1160 if (node->child1().useKind() == DoubleRepUse) {
1161 if (producesInteger(node->arithRoundingMode()))
1162 setNonCellTypeForNode(node, SpecInt32Only);
1163 else if (node->child1().useKind() == DoubleRepUse)
1164 setNonCellTypeForNode(node, typeOfDoubleRounding(forNode(node->child1()).m_type));
1165 } else {
1166 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
1167 clobberWorld();
1168 setNonCellTypeForNode(node, SpecBytecodeNumber);
1169 }
1170 break;
1171 }
1172
1173 case ArithSqrt:
1174 executeDoubleUnaryOpEffects(node, sqrt);
1175 break;
1176
1177 case ArithFRound:
1178 executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
1179 break;
1180
1181 case ArithUnary:
1182 executeDoubleUnaryOpEffects(node, arithUnaryFunction(node->arithUnaryType()));
1183 break;
1184
1185 case LogicalNot: {
1186 switch (booleanResult(node, forNode(node->child1()))) {
1187 case DefinitelyTrue:
1188 setConstant(node, jsBoolean(false));
1189 break;
1190 case DefinitelyFalse:
1191 setConstant(node, jsBoolean(true));
1192 break;
1193 default:
1194 setNonCellTypeForNode(node, SpecBoolean);
1195 break;
1196 }
1197 break;
1198 }
1199
1200 case MapHash: {
1201 if (JSValue key = forNode(node->child1()).value()) {
1202 if (Optional<uint32_t> hash = concurrentJSMapHash(key)) {
1203 // Although C++ code uses uint32_t for the hash, the closest type in DFG IR is Int32
1204 // and that's what MapHash returns. So, we have to cast to int32_t to avoid large
1205 // unsigned values becoming doubles. This casting between signed and unsigned
1206 // happens in the assembly code we emit when we don't constant fold this node.
1207 setConstant(node, jsNumber(static_cast<int32_t>(*hash)));
1208 break;
1209 }
1210 }
1211 setNonCellTypeForNode(node, SpecInt32Only);
1212 break;
1213 }
1214
1215 case NormalizeMapKey: {
1216 if (JSValue key = forNode(node->child1()).value()) {
1217 setConstant(node, *m_graph.freeze(normalizeMapKey(key)));
1218 break;
1219 }
1220
1221 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only);
1222 if (!(forNode(node->child1()).m_type & typeMaybeNormalized)) {
1223 m_state.setFoundConstants(true);
1224 forNode(node) = forNode(node->child1());
1225 break;
1226 }
1227
1228 makeHeapTopForNode(node);
1229 break;
1230 }
1231
1232 case StringValueOf: {
1233 clobberWorld();
1234 setTypeForNode(node, SpecString);
1235 break;
1236 }
1237
1238 case StringSlice: {
1239 setTypeForNode(node, SpecString);
1240 break;
1241 }
1242
1243 case ToLowerCase: {
1244 setTypeForNode(node, SpecString);
1245 break;
1246 }
1247
1248 case LoadKeyFromMapBucket:
1249 case LoadValueFromMapBucket:
1250 case ExtractValueFromWeakMapGet:
1251 makeHeapTopForNode(node);
1252 break;
1253
1254 case GetMapBucket:
1255 case GetMapBucketHead:
1256 if (node->child1().useKind() == MapObjectUse)
1257 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1258 else {
1259 ASSERT(node->child1().useKind() == SetObjectUse);
1260 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1261 }
1262 break;
1263
1264 case GetMapBucketNext:
1265 if (node->bucketOwnerType() == BucketOwnerType::Map)
1266 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1267 else {
1268 ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
1269 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1270 }
1271 break;
1272
1273 case SetAdd:
1274 setForNode(node, m_vm.hashMapBucketSetStructure.get());
1275 break;
1276
1277 case MapSet:
1278 setForNode(node, m_vm.hashMapBucketMapStructure.get());
1279 break;
1280
1281 case WeakSetAdd:
1282 case WeakMapSet:
1283 break;
1284
1285 case WeakMapGet:
1286 makeBytecodeTopForNode(node);
1287 break;
1288
1289 case IsEmpty:
1290 case IsUndefined:
1291 case IsUndefinedOrNull:
1292 case IsBoolean:
1293 case IsNumber:
1294 case NumberIsInteger:
1295 case IsObject:
1296 case IsObjectOrNull:
1297 case IsFunction:
1298 case IsCellWithType:
1299 case IsTypedArrayView: {
1300 AbstractValue child = forNode(node->child1());
1301 if (child.value()) {
1302 bool constantWasSet = true;
1303 switch (node->op()) {
1304 case IsCellWithType:
1305 setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
1306 break;
1307 case IsUndefined:
1308 setConstant(node, jsBoolean(
1309 child.value().isCell()
1310 ? child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
1311 : child.value().isUndefined()));
1312 break;
1313 case IsUndefinedOrNull:
1314 setConstant(node, jsBoolean(child.value().isUndefinedOrNull()));
1315 break;
1316 case IsBoolean:
1317 setConstant(node, jsBoolean(child.value().isBoolean()));
1318 break;
1319 case IsNumber:
1320 setConstant(node, jsBoolean(child.value().isNumber()));
1321 break;
1322 case NumberIsInteger:
1323 setConstant(node, jsBoolean(NumberConstructor::isIntegerImpl(child.value())));
1324 break;
1325 case IsObject:
1326 setConstant(node, jsBoolean(child.value().isObject()));
1327 break;
1328 case IsObjectOrNull:
1329 if (child.value().isObject()) {
1330 JSObject* object = asObject(child.value());
1331 if (object->type() == JSFunctionType)
1332 setConstant(node, jsBoolean(false));
1333 else if (!(object->inlineTypeFlags() & OverridesGetCallData))
1334 setConstant(node, jsBoolean(!child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
1335 else {
1336 // FIXME: This could just call getCallData.
1337 // https://bugs.webkit.org/show_bug.cgi?id=144457
1338 constantWasSet = false;
1339 }
1340 } else
1341 setConstant(node, jsBoolean(child.value().isNull()));
1342 break;
1343 case IsFunction:
1344 if (child.value().isObject()) {
1345 JSObject* object = asObject(child.value());
1346 if (object->type() == JSFunctionType)
1347 setConstant(node, jsBoolean(true));
1348 else if (!(object->inlineTypeFlags() & OverridesGetCallData))
1349 setConstant(node, jsBoolean(false));
1350 else {
1351 // FIXME: This could just call getCallData.
1352 // https://bugs.webkit.org/show_bug.cgi?id=144457
1353 constantWasSet = false;
1354 }
1355 } else
1356 setConstant(node, jsBoolean(false));
1357 break;
1358 case IsEmpty:
1359 setConstant(node, jsBoolean(child.value().isEmpty()));
1360 break;
1361 case IsTypedArrayView:
1362 setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo(m_vm)->typedArrayStorageType)));
1363 break;
1364 default:
1365 constantWasSet = false;
1366 break;
1367 }
1368 if (constantWasSet)
1369 break;
1370 }
1371
1372 // FIXME: This code should really use AbstractValue::isType() and
1373 // AbstractValue::couldBeType().
1374 // https://bugs.webkit.org/show_bug.cgi?id=146870
1375
1376 bool constantWasSet = false;
1377 switch (node->op()) {
1378 case IsEmpty: {
1379 if (child.m_type && !(child.m_type & SpecEmpty)) {
1380 setConstant(node, jsBoolean(false));
1381 constantWasSet = true;
1382 break;
1383 }
1384
1385 if (child.m_type && !(child.m_type & ~SpecEmpty)) {
1386 setConstant(node, jsBoolean(true));
1387 constantWasSet = true;
1388 break;
1389 }
1390
1391 break;
1392 }
1393 case IsUndefined:
1394 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1395 // https://bugs.webkit.org/show_bug.cgi?id=144456
1396
1397 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
1398 setConstant(node, jsBoolean(false));
1399 constantWasSet = true;
1400 break;
1401 }
1402
1403 break;
1404 case IsUndefinedOrNull:
1405 if (!(child.m_type & ~SpecOther)) {
1406 setConstant(node, jsBoolean(true));
1407 constantWasSet = true;
1408 break;
1409 }
1410
1411 if (!(child.m_type & SpecOther)) {
1412 setConstant(node, jsBoolean(false));
1413 constantWasSet = true;
1414 break;
1415 }
1416 break;
1417 case IsBoolean:
1418 if (!(child.m_type & ~SpecBoolean)) {
1419 setConstant(node, jsBoolean(true));
1420 constantWasSet = true;
1421 break;
1422 }
1423
1424 if (!(child.m_type & SpecBoolean)) {
1425 setConstant(node, jsBoolean(false));
1426 constantWasSet = true;
1427 break;
1428 }
1429
1430 break;
1431 case IsNumber:
1432 if (!(child.m_type & ~SpecFullNumber)) {
1433 setConstant(node, jsBoolean(true));
1434 constantWasSet = true;
1435 break;
1436 }
1437
1438 if (!(child.m_type & SpecFullNumber)) {
1439 setConstant(node, jsBoolean(false));
1440 constantWasSet = true;
1441 break;
1442 }
1443
1444 break;
1445
1446 case NumberIsInteger:
1447 if (!(child.m_type & ~SpecInt32Only)) {
1448 setConstant(node, jsBoolean(true));
1449 constantWasSet = true;
1450 break;
1451 }
1452
1453 if (!(child.m_type & SpecFullNumber)) {
1454 setConstant(node, jsBoolean(false));
1455 constantWasSet = true;
1456 break;
1457 }
1458
1459 break;
1460
1461 case IsObject:
1462 if (!(child.m_type & ~SpecObject)) {
1463 setConstant(node, jsBoolean(true));
1464 constantWasSet = true;
1465 break;
1466 }
1467
1468 if (!(child.m_type & SpecObject)) {
1469 setConstant(node, jsBoolean(false));
1470 constantWasSet = true;
1471 break;
1472 }
1473
1474 break;
1475 case IsObjectOrNull:
1476 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1477 // https://bugs.webkit.org/show_bug.cgi?id=144456
1478
1479 // These expressions are complicated to parse. A helpful way to parse this is that
1480 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1481 // disjoint set from S". Things like "T - S" means that, provided that S is a
1482 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1483 // mean the "union of T and S".
1484
1485 // Is the child's type an object that isn't an other-object (i.e. object that could
1486 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1487 // this to true.
1488 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1489 setConstant(node, jsBoolean(true));
1490 constantWasSet = true;
1491 break;
1492 }
1493
1494 // Is the child's type definitely not either of: an object that isn't a function,
1495 // or either undefined or null? Then: we should fold this to false. This means
1496 // for example that if it's any non-function object, including those that have
1497 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1498 // if it's undefined-or-null, since the type bits don't distinguish between
1499 // undefined (which should fold to false) and null (which should fold to true).
1500 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1501 setConstant(node, jsBoolean(false));
1502 constantWasSet = true;
1503 break;
1504 }
1505
1506 break;
1507 case IsFunction:
1508 if (!(child.m_type & ~SpecFunction)) {
1509 setConstant(node, jsBoolean(true));
1510 constantWasSet = true;
1511 break;
1512 }
1513
1514 if (!(child.m_type & (SpecFunction | SpecObjectOther | SpecProxyObject))) {
1515 setConstant(node, jsBoolean(false));
1516 constantWasSet = true;
1517 break;
1518 }
1519 break;
1520
1521 case IsCellWithType:
1522 if (!(child.m_type & ~node->speculatedTypeForQuery())) {
1523 setConstant(node, jsBoolean(true));
1524 constantWasSet = true;
1525 break;
1526 }
1527 if (!(child.m_type & node->speculatedTypeForQuery())) {
1528 setConstant(node, jsBoolean(false));
1529 constantWasSet = true;
1530 break;
1531 }
1532 break;
1533
1534 case IsTypedArrayView:
1535 if (!(child.m_type & ~SpecTypedArrayView)) {
1536 setConstant(node, jsBoolean(true));
1537 constantWasSet = true;
1538 break;
1539 }
1540 if (!(child.m_type & SpecTypedArrayView)) {
1541 setConstant(node, jsBoolean(false));
1542 constantWasSet = true;
1543 break;
1544 }
1545 break;
1546
1547 default:
1548 break;
1549 }
1550 if (constantWasSet)
1551 break;
1552
1553 setNonCellTypeForNode(node, SpecBoolean);
1554 break;
1555 }
1556
1557 case TypeOf: {
1558 JSValue child = forNode(node->child1()).value();
1559 AbstractValue& abstractChild = forNode(node->child1());
1560 if (child) {
1561 JSValue typeString = jsTypeStringForValue(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
1562 setConstant(node, *m_graph.freeze(typeString));
1563 break;
1564 }
1565
1566 if (isFullNumberSpeculation(abstractChild.m_type)) {
1567 setConstant(node, *m_graph.freeze(m_vm.smallStrings.numberString()));
1568 break;
1569 }
1570
1571 if (isStringSpeculation(abstractChild.m_type)) {
1572 setConstant(node, *m_graph.freeze(m_vm.smallStrings.stringString()));
1573 break;
1574 }
1575
1576 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1577 // https://bugs.webkit.org/show_bug.cgi?id=144456
1578 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1579 setConstant(node, *m_graph.freeze(m_vm.smallStrings.objectString()));
1580 break;
1581 }
1582
1583 if (isFunctionSpeculation(abstractChild.m_type)) {
1584 setConstant(node, *m_graph.freeze(m_vm.smallStrings.functionString()));
1585 break;
1586 }
1587
1588 if (isBooleanSpeculation(abstractChild.m_type)) {
1589 setConstant(node, *m_graph.freeze(m_vm.smallStrings.booleanString()));
1590 break;
1591 }
1592
1593 if (isSymbolSpeculation(abstractChild.m_type)) {
1594 setConstant(node, *m_graph.freeze(m_vm.smallStrings.symbolString()));
1595 break;
1596 }
1597
1598 if (isBigIntSpeculation(abstractChild.m_type)) {
1599 setConstant(node, *m_graph.freeze(m_vm.smallStrings.bigintString()));
1600 break;
1601 }
1602
1603 setTypeForNode(node, SpecStringIdent);
1604 break;
1605 }
1606
1607 case CompareBelow:
1608 case CompareBelowEq: {
1609 JSValue leftConst = forNode(node->child1()).value();
1610 JSValue rightConst = forNode(node->child2()).value();
1611 if (leftConst && rightConst) {
1612 if (leftConst.isInt32() && rightConst.isInt32()) {
1613 uint32_t a = static_cast<uint32_t>(leftConst.asInt32());
1614 uint32_t b = static_cast<uint32_t>(rightConst.asInt32());
1615 switch (node->op()) {
1616 case CompareBelow:
1617 setConstant(node, jsBoolean(a < b));
1618 break;
1619 case CompareBelowEq:
1620 setConstant(node, jsBoolean(a <= b));
1621 break;
1622 default:
1623 RELEASE_ASSERT_NOT_REACHED();
1624 break;
1625 }
1626 break;
1627 }
1628 }
1629
1630 if (node->child1() == node->child2()) {
1631 switch (node->op()) {
1632 case CompareBelow:
1633 setConstant(node, jsBoolean(false));
1634 break;
1635 case CompareBelowEq:
1636 setConstant(node, jsBoolean(true));
1637 break;
1638 default:
1639 DFG_CRASH(m_graph, node, "Unexpected node type");
1640 break;
1641 }
1642 break;
1643 }
1644 setNonCellTypeForNode(node, SpecBoolean);
1645 break;
1646 }
1647
1648 case CompareLess:
1649 case CompareLessEq:
1650 case CompareGreater:
1651 case CompareGreaterEq:
1652 case CompareEq: {
1653 bool isClobbering = node->isBinaryUseKind(UntypedUse);
1654
1655 if (isClobbering)
1656 didFoldClobberWorld();
1657
1658 JSValue leftConst = forNode(node->child1()).value();
1659 JSValue rightConst = forNode(node->child2()).value();
1660 if (leftConst && rightConst) {
1661 if (leftConst.isNumber() && rightConst.isNumber()) {
1662 double a = leftConst.asNumber();
1663 double b = rightConst.asNumber();
1664 switch (node->op()) {
1665 case CompareLess:
1666 setConstant(node, jsBoolean(a < b));
1667 break;
1668 case CompareLessEq:
1669 setConstant(node, jsBoolean(a <= b));
1670 break;
1671 case CompareGreater:
1672 setConstant(node, jsBoolean(a > b));
1673 break;
1674 case CompareGreaterEq:
1675 setConstant(node, jsBoolean(a >= b));
1676 break;
1677 case CompareEq:
1678 setConstant(node, jsBoolean(a == b));
1679 break;
1680 default:
1681 RELEASE_ASSERT_NOT_REACHED();
1682 break;
1683 }
1684 break;
1685 }
1686
1687 if (leftConst.isString() && rightConst.isString()) {
1688 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1689 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1690 if (a && b) {
1691 bool result;
1692 if (node->op() == CompareEq)
1693 result = WTF::equal(a, b);
1694 else if (node->op() == CompareLess)
1695 result = codePointCompare(a, b) < 0;
1696 else if (node->op() == CompareLessEq)
1697 result = codePointCompare(a, b) <= 0;
1698 else if (node->op() == CompareGreater)
1699 result = codePointCompare(a, b) > 0;
1700 else if (node->op() == CompareGreaterEq)
1701 result = codePointCompare(a, b) >= 0;
1702 else
1703 RELEASE_ASSERT_NOT_REACHED();
1704 setConstant(node, jsBoolean(result));
1705 break;
1706 }
1707 }
1708
1709 if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
1710 setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
1711 break;
1712 }
1713 }
1714
1715 if (node->op() == CompareEq) {
1716 SpeculatedType leftType = forNode(node->child1()).m_type;
1717 SpeculatedType rightType = forNode(node->child2()).m_type;
1718 if (!valuesCouldBeEqual(leftType, rightType)) {
1719 setConstant(node, jsBoolean(false));
1720 break;
1721 }
1722
1723 if (leftType == SpecOther)
1724 std::swap(leftType, rightType);
1725 if (rightType == SpecOther) {
1726 // Undefined and Null are always equal when compared to eachother.
1727 if (!(leftType & ~SpecOther)) {
1728 setConstant(node, jsBoolean(true));
1729 break;
1730 }
1731
1732 // Any other type compared to Null or Undefined is always false
1733 // as long as the MasqueradesAsUndefined watchpoint is valid.
1734 //
1735 // MasqueradesAsUndefined only matters for SpecObjectOther, other
1736 // cases are always "false".
1737 if (!(leftType & (SpecObjectOther | SpecOther))) {
1738 setConstant(node, jsBoolean(false));
1739 break;
1740 }
1741
1742 if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
1743 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1744 m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
1745 setConstant(node, jsBoolean(false));
1746 break;
1747 }
1748 }
1749 }
1750
1751 if (node->child1() == node->child2()) {
1752 if (node->isBinaryUseKind(Int32Use) ||
1753 node->isBinaryUseKind(Int52RepUse) ||
1754 node->isBinaryUseKind(StringUse) ||
1755 node->isBinaryUseKind(BooleanUse) ||
1756 node->isBinaryUseKind(SymbolUse) ||
1757 node->isBinaryUseKind(StringIdentUse) ||
1758 node->isBinaryUseKind(ObjectUse) ||
1759 node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
1760 node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
1761 switch (node->op()) {
1762 case CompareLess:
1763 case CompareGreater:
1764 setConstant(node, jsBoolean(false));
1765 break;
1766 case CompareLessEq:
1767 case CompareGreaterEq:
1768 case CompareEq:
1769 setConstant(node, jsBoolean(true));
1770 break;
1771 default:
1772 DFG_CRASH(m_graph, node, "Unexpected node type");
1773 break;
1774 }
1775 break;
1776 }
1777 }
1778
1779 if (isClobbering)
1780 clobberWorld();
1781 setNonCellTypeForNode(node, SpecBoolean);
1782 break;
1783 }
1784
1785 case CompareStrictEq:
1786 case SameValue: {
1787 Node* leftNode = node->child1().node();
1788 Node* rightNode = node->child2().node();
1789 JSValue left = forNode(leftNode).value();
1790 JSValue right = forNode(rightNode).value();
1791 if (left && right) {
1792 if (left.isString() && right.isString()) {
1793 // We need this case because JSValue::strictEqual is otherwise too racy for
1794 // string comparisons.
1795 const StringImpl* a = asString(left)->tryGetValueImpl();
1796 const StringImpl* b = asString(right)->tryGetValueImpl();
1797 if (a && b) {
1798 setConstant(node, jsBoolean(WTF::equal(a, b)));
1799 break;
1800 }
1801 } else {
1802 if (node->op() == CompareStrictEq)
1803 setConstant(node, jsBoolean(JSValue::strictEqual(nullptr, left, right)));
1804 else
1805 setConstant(node, jsBoolean(sameValue(nullptr, left, right)));
1806 break;
1807 }
1808 }
1809
1810 if (node->isBinaryUseKind(UntypedUse)) {
1811 // FIXME: Revisit this condition when introducing BigInt to JSC.
1812 auto isNonStringCellConstant = [] (JSValue value) {
1813 return value && value.isCell() && !value.isString();
1814 };
1815
1816 if (isNonStringCellConstant(left) || isNonStringCellConstant(right)) {
1817 m_state.setFoundConstants(true);
1818 setNonCellTypeForNode(node, SpecBoolean);
1819 break;
1820 }
1821 }
1822
1823 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1824 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1825 if (!(leftLUB & rightLUB)) {
1826 setConstant(node, jsBoolean(false));
1827 break;
1828 }
1829
1830 if (node->child1() == node->child2()) {
1831 if (node->isBinaryUseKind(BooleanUse) ||
1832 node->isBinaryUseKind(Int32Use) ||
1833 node->isBinaryUseKind(Int52RepUse) ||
1834 node->isBinaryUseKind(StringUse) ||
1835 node->isBinaryUseKind(StringIdentUse) ||
1836 node->isBinaryUseKind(SymbolUse) ||
1837 node->isBinaryUseKind(ObjectUse) ||
1838 node->isBinaryUseKind(MiscUse, UntypedUse) ||
1839 node->isBinaryUseKind(UntypedUse, MiscUse) ||
1840 node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1841 node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1842 node->isBinaryUseKind(StringUse, UntypedUse) ||
1843 node->isBinaryUseKind(UntypedUse, StringUse)) {
1844 setConstant(node, jsBoolean(true));
1845 break;
1846 }
1847 }
1848
1849 setNonCellTypeForNode(node, SpecBoolean);
1850 break;
1851 }
1852
1853 case CompareEqPtr: {
1854 Node* childNode = node->child1().node();
1855 JSValue childValue = forNode(childNode).value();
1856 if (childValue) {
1857 setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
1858 break;
1859 }
1860
1861 setNonCellTypeForNode(node, SpecBoolean);
1862 break;
1863 }
1864
1865 case StringCharCodeAt:
1866 setNonCellTypeForNode(node, SpecInt32Only);
1867 break;
1868
1869 case StringFromCharCode:
1870 switch (node->child1().useKind()) {
1871 case Int32Use:
1872 break;
1873 case UntypedUse:
1874 clobberWorld();
1875 break;
1876 default:
1877 DFG_CRASH(m_graph, node, "Bad use kind");
1878 break;
1879 }
1880 setTypeForNode(node, SpecString);
1881 break;
1882
1883 case StringCharAt:
1884 setForNode(node, m_vm.stringStructure.get());
1885 break;
1886
1887 case GetByVal:
1888 case AtomicsAdd:
1889 case AtomicsAnd:
1890 case AtomicsCompareExchange:
1891 case AtomicsExchange:
1892 case AtomicsLoad:
1893 case AtomicsOr:
1894 case AtomicsStore:
1895 case AtomicsSub:
1896 case AtomicsXor: {
1897 if (node->op() == GetByVal) {
1898 auto foldGetByValOnConstantProperty = [&] (Edge& arrayEdge, Edge& indexEdge) {
1899 // FIXME: We can expand this for non x86 environments.
1900 // https://bugs.webkit.org/show_bug.cgi?id=134641
1901 if (!isX86())
1902 return false;
1903
1904 AbstractValue& arrayValue = forNode(arrayEdge);
1905
1906 // Check the structure set is finite. This means that this constant's structure is watched and guaranteed the one of this set.
1907 // When the structure is changed, this code should be invalidated. This is important since the following code relies on the
1908 // constant object's is not changed.
1909 if (!arrayValue.m_structure.isFinite())
1910 return false;
1911
1912 JSValue arrayConstant = arrayValue.value();
1913 if (!arrayConstant)
1914 return false;
1915
1916 JSObject* array = jsDynamicCast<JSObject*>(m_vm, arrayConstant);
1917 if (!array)
1918 return false;
1919
1920 JSValue indexConstant = forNode(indexEdge).value();
1921 if (!indexConstant || !indexConstant.isInt32() || indexConstant.asInt32() < 0)
1922 return false;
1923 uint32_t index = indexConstant.asUInt32();
1924
1925 // Check that the early StructureID is not nuked, get the butterfly, and check the late StructureID again.
1926 // And we check the indexing mode of the structure. If the indexing mode is CoW, the butterfly is
1927 // definitely JSImmutableButterfly.
1928 StructureID structureIDEarly = array->structureID();
1929 if (isNuked(structureIDEarly))
1930 return false;
1931
1932 if (node->arrayMode().arrayClass() == Array::OriginalCopyOnWriteArray) {
1933
1934 WTF::loadLoadFence();
1935 Butterfly* butterfly = array->butterfly();
1936
1937 WTF::loadLoadFence();
1938 StructureID structureIDLate = array->structureID();
1939
1940 if (structureIDEarly != structureIDLate)
1941 return false;
1942
1943 Structure* structure = m_vm.getStructure(structureIDLate);
1944 switch (node->arrayMode().type()) {
1945 case Array::Int32:
1946 case Array::Contiguous:
1947 case Array::Double:
1948 if (structure->indexingMode() != (toIndexingShape(node->arrayMode().type()) | CopyOnWrite | IsArray))
1949 return false;
1950 break;
1951 default:
1952 return false;
1953 }
1954 ASSERT(isCopyOnWrite(structure->indexingMode()));
1955
1956 JSImmutableButterfly* immutableButterfly = JSImmutableButterfly::fromButterfly(butterfly);
1957 if (index < immutableButterfly->length()) {
1958 JSValue value = immutableButterfly->get(index);
1959 ASSERT(value);
1960 if (value.isCell())
1961 setConstant(node, *m_graph.freeze(value.asCell()));
1962 else
1963 setConstant(node, value);
1964 return true;
1965 }
1966
1967 if (node->arrayMode().isOutOfBounds()) {
1968 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
1969 Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(m_vm);
1970 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(m_vm);
1971 if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
1972 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
1973 && globalObject->arrayPrototypeChainIsSane()) {
1974 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
1975 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
1976 // Note that Array::Double and Array::Int32 return JSValue if array mode is OutOfBounds.
1977 setConstant(node, jsUndefined());
1978 return true;
1979 }
1980 }
1981 return false;
1982 }
1983
1984 if (node->arrayMode().type() == Array::ArrayStorage || node->arrayMode().type() == Array::SlowPutArrayStorage) {
1985 JSValue value;
1986 {
1987 // ArrayStorage's Butterfly can be half-broken state.
1988 auto locker = holdLock(array->cellLock());
1989
1990 WTF::loadLoadFence();
1991 Butterfly* butterfly = array->butterfly();
1992
1993 WTF::loadLoadFence();
1994 StructureID structureIDLate = array->structureID();
1995
1996 if (structureIDEarly != structureIDLate)
1997 return false;
1998
1999 Structure* structure = m_vm.getStructure(structureIDLate);
2000 if (!hasAnyArrayStorage(structure->indexingMode()))
2001 return false;
2002
2003 if (structure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
2004 return false;
2005
2006 ArrayStorage* storage = butterfly->arrayStorage();
2007 if (index >= storage->length())
2008 return false;
2009
2010 if (index < storage->vectorLength())
2011 return false;
2012
2013 SparseArrayValueMap* map = storage->m_sparseMap.get();
2014 if (!map)
2015 return false;
2016
2017 value = map->getConcurrently(index);
2018 }
2019 if (!value)
2020 return false;
2021
2022 if (value.isCell())
2023 setConstant(node, *m_graph.freeze(value.asCell()));
2024 else
2025 setConstant(node, value);
2026 return true;
2027 }
2028
2029 return false;
2030 };
2031
2032 bool didFold = false;
2033 switch (node->arrayMode().type()) {
2034 case Array::Generic:
2035 case Array::Int32:
2036 case Array::Double:
2037 case Array::Contiguous:
2038 case Array::ArrayStorage:
2039 case Array::SlowPutArrayStorage:
2040 if (foldGetByValOnConstantProperty(m_graph.child(node, 0), m_graph.child(node, 1))) {
2041 if (!node->arrayMode().isInBounds())
2042 didFoldClobberWorld();
2043 didFold = true;
2044 }
2045 break;
2046 default:
2047 break;
2048 }
2049
2050 if (didFold)
2051 break;
2052 }
2053
2054 if (node->op() != GetByVal) {
2055 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
2056 Edge storageEdge = m_graph.child(node, 2 + numExtraArgs);
2057 if (!storageEdge)
2058 clobberWorld();
2059 }
2060 switch (node->arrayMode().type()) {
2061 case Array::SelectUsingPredictions:
2062 case Array::Unprofiled:
2063 case Array::SelectUsingArguments:
2064 RELEASE_ASSERT_NOT_REACHED();
2065 break;
2066 case Array::ForceExit:
2067 m_state.setIsValid(false);
2068 break;
2069 case Array::Undecided: {
2070 JSValue index = forNode(m_graph.child(node, 1)).value();
2071 if (index && index.isInt32() && index.asInt32() >= 0) {
2072 setConstant(node, jsUndefined());
2073 break;
2074 }
2075 setNonCellTypeForNode(node, SpecOther);
2076 break;
2077 }
2078 case Array::Generic:
2079 clobberWorld();
2080 makeHeapTopForNode(node);
2081 break;
2082 case Array::String:
2083 if (node->arrayMode().isOutOfBounds()) {
2084 // If the watchpoint was still valid we could totally set this to be
2085 // SpecString | SpecOther. Except that we'd have to be careful. If we
2086 // tested the watchpoint state here then it could change by the time
2087 // we got to the backend. So to do this right, we'd have to get the
2088 // fixup phase to check the watchpoint state and then bake into the
2089 // GetByVal operation the fact that we're using a watchpoint, using
2090 // something like Array::SaneChain (except not quite, because that
2091 // implies an in-bounds access). None of this feels like it's worth it,
2092 // so we're going with TOP for now. The same thing applies to
2093 // clobbering the world.
2094 clobberWorld();
2095 makeHeapTopForNode(node);
2096 } else
2097 setForNode(node, m_vm.stringStructure.get());
2098 break;
2099 case Array::DirectArguments:
2100 case Array::ScopedArguments:
2101 if (node->arrayMode().isOutOfBounds())
2102 clobberWorld();
2103 makeHeapTopForNode(node);
2104 break;
2105 case Array::Int32:
2106 if (node->arrayMode().isOutOfBounds()) {
2107 clobberWorld();
2108 makeHeapTopForNode(node);
2109 } else
2110 setNonCellTypeForNode(node, SpecInt32Only);
2111 break;
2112 case Array::Double:
2113 if (node->arrayMode().isOutOfBounds()) {
2114 clobberWorld();
2115 makeHeapTopForNode(node);
2116 } else if (node->arrayMode().isSaneChain())
2117 setNonCellTypeForNode(node, SpecBytecodeDouble);
2118 else
2119 setNonCellTypeForNode(node, SpecDoubleReal);
2120 break;
2121 case Array::Contiguous:
2122 case Array::ArrayStorage:
2123 case Array::SlowPutArrayStorage:
2124 if (node->arrayMode().isOutOfBounds())
2125 clobberWorld();
2126 makeHeapTopForNode(node);
2127 break;
2128 case Array::Int8Array:
2129 setNonCellTypeForNode(node, SpecInt32Only);
2130 break;
2131 case Array::Int16Array:
2132 setNonCellTypeForNode(node, SpecInt32Only);
2133 break;
2134 case Array::Int32Array:
2135 setNonCellTypeForNode(node, SpecInt32Only);
2136 break;
2137 case Array::Uint8Array:
2138 setNonCellTypeForNode(node, SpecInt32Only);
2139 break;
2140 case Array::Uint8ClampedArray:
2141 setNonCellTypeForNode(node, SpecInt32Only);
2142 break;
2143 case Array::Uint16Array:
2144 setNonCellTypeForNode(node, SpecInt32Only);
2145 break;
2146 case Array::Uint32Array:
2147 if (node->shouldSpeculateInt32())
2148 setNonCellTypeForNode(node, SpecInt32Only);
2149 else if (node->shouldSpeculateInt52())
2150 setNonCellTypeForNode(node, SpecInt52Any);
2151 else
2152 setNonCellTypeForNode(node, SpecAnyIntAsDouble);
2153 break;
2154 case Array::Float32Array:
2155 setNonCellTypeForNode(node, SpecFullDouble);
2156 break;
2157 case Array::Float64Array:
2158 setNonCellTypeForNode(node, SpecFullDouble);
2159 break;
2160 default:
2161 RELEASE_ASSERT_NOT_REACHED();
2162 break;
2163 }
2164 break;
2165 }
2166
2167 case PutByValDirect:
2168 case PutByVal:
2169 case PutByValAlias: {
2170 switch (node->arrayMode().modeForPut().type()) {
2171 case Array::ForceExit:
2172 m_state.setIsValid(false);
2173 break;
2174 case Array::Generic:
2175 clobberWorld();
2176 break;
2177 case Array::Int32:
2178 if (node->arrayMode().isOutOfBounds())
2179 clobberWorld();
2180 break;
2181 case Array::Double:
2182 if (node->arrayMode().isOutOfBounds())
2183 clobberWorld();
2184 break;
2185 case Array::Contiguous:
2186 case Array::ArrayStorage:
2187 if (node->arrayMode().isOutOfBounds())
2188 clobberWorld();
2189 break;
2190 case Array::SlowPutArrayStorage:
2191 if (node->arrayMode().mayStoreToHole())
2192 clobberWorld();
2193 break;
2194 default:
2195 break;
2196 }
2197 break;
2198 }
2199
2200 case ArrayPush:
2201 clobberWorld();
2202 setNonCellTypeForNode(node, SpecBytecodeNumber);
2203 break;
2204
2205 case ArraySlice: {
2206 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2207
2208 // FIXME: We could do better here if we prove that the
2209 // incoming value has only a single structure.
2210 RegisteredStructureSet structureSet;
2211 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32)));
2212 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous)));
2213 structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble)));
2214
2215 setForNode(node, structureSet);
2216 break;
2217 }
2218
2219 case ArrayIndexOf: {
2220 setNonCellTypeForNode(node, SpecInt32Only);
2221 break;
2222 }
2223
2224 case ArrayPop:
2225 clobberWorld();
2226 makeHeapTopForNode(node);
2227 break;
2228
2229 case GetMyArgumentByVal:
2230 case GetMyArgumentByValOutOfBounds: {
2231 JSValue index = forNode(node->child2()).m_value;
2232 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame();
2233
2234 if (index && index.isUInt32()) {
2235 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
2236 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
2237 // paths as unreachable, or to return undefined. We could implement that eventually.
2238
2239 Checked<unsigned, RecordOverflow> argumentIndexChecked = index.asUInt32();
2240 argumentIndexChecked += node->numberOfArgumentsToSkip();
2241 unsigned argumentIndex;
2242 if (argumentIndexChecked.safeGet(argumentIndex) != CheckedState::DidOverflow) {
2243 if (inlineCallFrame) {
2244 if (argumentIndex < inlineCallFrame->argumentCountIncludingThis - 1) {
2245 setForNode(node, m_state.operand(
2246 virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset));
2247 m_state.setFoundConstants(true);
2248 break;
2249 }
2250 } else {
2251 if (argumentIndex < m_state.numberOfArguments() - 1) {
2252 setForNode(node, m_state.argument(argumentIndex + 1));
2253 m_state.setFoundConstants(true);
2254 break;
2255 }
2256 }
2257 }
2258 }
2259
2260 if (inlineCallFrame) {
2261 // We have a bound on the types even though it's random access. Take advantage of this.
2262
2263 AbstractValue result;
2264 for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->argumentCountIncludingThis; ++i) {
2265 result.merge(
2266 m_state.operand(
2267 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
2268 }
2269
2270 if (node->op() == GetMyArgumentByValOutOfBounds)
2271 result.merge(SpecOther);
2272
2273 if (result.value())
2274 m_state.setFoundConstants(true);
2275
2276 setForNode(node, result);
2277 break;
2278 }
2279
2280 makeHeapTopForNode(node);
2281 break;
2282 }
2283
2284 case RegExpExec:
2285 case RegExpExecNonGlobalOrSticky:
2286 if (node->op() == RegExpExec) {
2287 // Even if we've proven known input types as RegExpObject and String,
2288 // accessing lastIndex is effectful if it's a global regexp.
2289 clobberWorld();
2290 }
2291
2292 if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
2293 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(m_vm, globalObjectValue)) {
2294 if (!globalObject->isHavingABadTime()) {
2295 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2296 RegisteredStructureSet structureSet;
2297 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure()));
2298 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayWithGroupsStructure()));
2299 setForNode(node, structureSet);
2300 forNode(node).merge(SpecOther);
2301 break;
2302 }
2303 }
2304 }
2305 setTypeForNode(node, SpecOther | SpecArray);
2306 break;
2307
2308 case RegExpTest:
2309 // Even if we've proven known input types as RegExpObject and String,
2310 // accessing lastIndex is effectful if it's a global regexp.
2311 clobberWorld();
2312 setNonCellTypeForNode(node, SpecBoolean);
2313 break;
2314
2315 case RegExpMatchFast:
2316 ASSERT(node->child2().useKind() == RegExpObjectUse);
2317 ASSERT(node->child3().useKind() == StringUse || node->child3().useKind() == KnownStringUse);
2318 setTypeForNode(node, SpecOther | SpecArray);
2319 break;
2320
2321 case RegExpMatchFastGlobal:
2322 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == KnownStringUse);
2323 setTypeForNode(node, SpecOther | SpecArray);
2324 break;
2325
2326 case StringReplace:
2327 case StringReplaceRegExp:
2328 if (node->child1().useKind() == StringUse
2329 && node->child2().useKind() == RegExpObjectUse
2330 && node->child3().useKind() == StringUse) {
2331 // This doesn't clobber the world. It just reads and writes regexp state.
2332 } else
2333 clobberWorld();
2334 setForNode(node, m_vm.stringStructure.get());
2335 break;
2336
2337 case Jump:
2338 break;
2339
2340 case Branch: {
2341 Node* child = node->child1().node();
2342 BooleanResult result = booleanResult(node, forNode(child));
2343 if (result == DefinitelyTrue) {
2344 m_state.setBranchDirection(TakeTrue);
2345 break;
2346 }
2347 if (result == DefinitelyFalse) {
2348 m_state.setBranchDirection(TakeFalse);
2349 break;
2350 }
2351 // FIXME: The above handles the trivial cases of sparse conditional
2352 // constant propagation, but we can do better:
2353 // We can specialize the source variable's value on each direction of
2354 // the branch.
2355 m_state.setBranchDirection(TakeBoth);
2356 break;
2357 }
2358
2359 case Switch: {
2360 // Nothing to do for now.
2361 // FIXME: Do sparse conditional things.
2362 break;
2363 }
2364
2365 case EntrySwitch:
2366 break;
2367
2368 case Return:
2369 m_state.setIsValid(false);
2370 break;
2371
2372 case Throw:
2373 case ThrowStaticError:
2374 case TailCall:
2375 case DirectTailCall:
2376 case TailCallVarargs:
2377 case TailCallForwardVarargs:
2378 clobberWorld();
2379 m_state.setIsValid(false);
2380 break;
2381
2382 case ToPrimitive: {
2383 JSValue childConst = forNode(node->child1()).value();
2384 if (childConst && childConst.isNumber()) {
2385 didFoldClobberWorld();
2386 setConstant(node, childConst);
2387 break;
2388 }
2389
2390 ASSERT(node->child1().useKind() == UntypedUse);
2391
2392 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))) {
2393 m_state.setFoundConstants(true);
2394 didFoldClobberWorld();
2395 setForNode(node, forNode(node->child1()));
2396 break;
2397 }
2398
2399 clobberWorld();
2400
2401 setTypeForNode(node, SpecHeapTop & ~SpecObject);
2402 break;
2403 }
2404
2405 case ToNumber: {
2406 JSValue childConst = forNode(node->child1()).value();
2407 if (childConst && childConst.isNumber()) {
2408 didFoldClobberWorld();
2409 setConstant(node, childConst);
2410 break;
2411 }
2412
2413 ASSERT(node->child1().useKind() == UntypedUse);
2414
2415 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
2416 m_state.setFoundConstants(true);
2417 didFoldClobberWorld();
2418 setForNode(node, forNode(node->child1()));
2419 break;
2420 }
2421
2422 clobberWorld();
2423 setNonCellTypeForNode(node, SpecBytecodeNumber);
2424 break;
2425 }
2426
2427 case ToString:
2428 case CallStringConstructor: {
2429 switch (node->child1().useKind()) {
2430 case StringObjectUse:
2431 case StringOrStringObjectUse:
2432 case Int32Use:
2433 case Int52RepUse:
2434 case DoubleRepUse:
2435 case NotCellUse:
2436 break;
2437 case CellUse:
2438 case UntypedUse:
2439 clobberWorld();
2440 break;
2441 default:
2442 RELEASE_ASSERT_NOT_REACHED();
2443 break;
2444 }
2445 setForNode(node, m_vm.stringStructure.get());
2446 break;
2447 }
2448
2449 case NumberToStringWithRadix: {
2450 JSValue radixValue = forNode(node->child2()).m_value;
2451 if (radixValue && radixValue.isInt32()) {
2452 int32_t radix = radixValue.asInt32();
2453 if (2 <= radix && radix <= 36) {
2454 m_state.setFoundConstants(true);
2455 didFoldClobberWorld();
2456 setForNode(node, m_graph.m_vm.stringStructure.get());
2457 break;
2458 }
2459 }
2460 clobberWorld();
2461 setForNode(node, m_graph.m_vm.stringStructure.get());
2462 break;
2463 }
2464
2465 case NumberToStringWithValidRadixConstant: {
2466 setForNode(node, m_graph.m_vm.stringStructure.get());
2467 break;
2468 }
2469
2470 case NewStringObject: {
2471 ASSERT(node->structure()->classInfo() == StringObject::info());
2472 setForNode(node, node->structure());
2473 break;
2474 }
2475
2476 case NewSymbol: {
2477 setForNode(node, m_vm.symbolStructure.get());
2478 break;
2479 }
2480
2481 case NewArray:
2482 ASSERT(node->indexingMode() == node->indexingType()); // Copy on write arrays should only be created by NewArrayBuffer.
2483 setForNode(node,
2484 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
2485 break;
2486
2487 case NewArrayWithSpread:
2488 if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2489 // We've compiled assuming we're not having a bad time, so to be consistent
2490 // with StructureRegisterationPhase we must say we produce an original array
2491 // allocation structure.
2492 setForNode(node,
2493 m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
2494 } else {
2495 setForNode(node,
2496 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
2497 }
2498
2499 break;
2500
2501 case Spread:
2502 switch (node->child1()->op()) {
2503 case PhantomNewArrayBuffer:
2504 case PhantomCreateRest:
2505 break;
2506 default:
2507 if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
2508 clobberWorld();
2509 else
2510 didFoldClobberWorld();
2511 break;
2512 }
2513
2514 setForNode(node,
2515 m_vm.fixedArrayStructure.get());
2516 break;
2517
2518 case NewArrayBuffer:
2519 setForNode(node,
2520 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingMode()));
2521 break;
2522
2523 case NewArrayWithSize:
2524 setTypeForNode(node, SpecArray);
2525 break;
2526
2527 case NewTypedArray:
2528 switch (node->child1().useKind()) {
2529 case Int32Use:
2530 break;
2531 case UntypedUse:
2532 clobberWorld();
2533 break;
2534 default:
2535 RELEASE_ASSERT_NOT_REACHED();
2536 break;
2537 }
2538 setForNode(node,
2539 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
2540 node->typedArrayType()));
2541 break;
2542
2543 case NewRegexp:
2544 setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
2545 break;
2546
2547 case ToThis: {
2548 AbstractValue& source = forNode(node->child1());
2549 AbstractValue& destination = forNode(node);
2550 bool strictMode = m_graph.isStrictModeFor(node->origin.semantic);
2551
2552 ToThisResult result = isToThisAnIdentity(m_vm, strictMode, source);
2553 switch (result) {
2554 case ToThisResult::Identity:
2555 m_state.setFoundConstants(true);
2556 destination = source;
2557 break;
2558 case ToThisResult::Undefined:
2559 setConstant(node, jsUndefined());
2560 break;
2561 case ToThisResult::GlobalThis:
2562 m_state.setFoundConstants(true);
2563 destination.setType(m_graph, SpecObject);
2564 break;
2565 case ToThisResult::Dynamic:
2566 if (strictMode)
2567 destination.makeHeapTop();
2568 else {
2569 destination = source;
2570 destination.merge(SpecObject);
2571 }
2572 break;
2573 }
2574 break;
2575 }
2576
2577 case CreateThis: {
2578 if (JSValue base = forNode(node->child1()).m_value) {
2579 if (auto* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
2580 if (FunctionRareData* rareData = function->rareData()) {
2581 if (Structure* structure = rareData->objectAllocationStructure()) {
2582 m_graph.freeze(rareData);
2583 m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
2584 m_state.setFoundConstants(true);
2585 didFoldClobberWorld();
2586 setForNode(node, structure);
2587 break;
2588 }
2589 }
2590 }
2591 }
2592 clobberWorld();
2593 setTypeForNode(node, SpecFinalObject);
2594 break;
2595 }
2596
2597 case NewObject:
2598 ASSERT(!!node->structure().get());
2599 setForNode(node, node->structure());
2600 break;
2601
2602 case ObjectCreate: {
2603 if (JSValue base = forNode(node->child1()).m_value) {
2604 JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
2605 Structure* structure = nullptr;
2606 if (base.isNull())
2607 structure = globalObject->nullPrototypeObjectStructure();
2608 else if (base.isObject())
2609 structure = globalObject->vm().structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
2610
2611 if (structure) {
2612 m_state.setFoundConstants(true);
2613 if (node->child1().useKind() == UntypedUse)
2614 didFoldClobberWorld();
2615 setForNode(node, structure);
2616 break;
2617 }
2618 }
2619 if (node->child1().useKind() == UntypedUse)
2620 clobberWorld();
2621 setTypeForNode(node, SpecFinalObject);
2622 break;
2623 }
2624
2625 case ObjectKeys: {
2626 if (node->child1().useKind() == ObjectUse) {
2627 auto& structureSet = forNode(node->child1()).m_structure;
2628 if (structureSet.isFinite() && structureSet.size() == 1) {
2629 RegisteredStructure structure = structureSet.onlyStructure();
2630 if (auto* rareData = structure->rareDataConcurrently()) {
2631 if (!!rareData->cachedOwnKeysConcurrently()) {
2632 if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2633 m_state.setFoundConstants(true);
2634 didFoldClobberWorld();
2635 setTypeForNode(node, SpecArray);
2636 break;
2637 }
2638 }
2639 }
2640 }
2641 }
2642
2643 clobberWorld();
2644 setTypeForNode(node, SpecArray);
2645 break;
2646 }
2647
2648 case ToObject:
2649 case CallObjectConstructor: {
2650 AbstractValue& source = forNode(node->child1());
2651 AbstractValue& destination = forNode(node);
2652
2653 if (!(source.m_type & ~SpecObject)) {
2654 m_state.setFoundConstants(true);
2655 if (node->op() == ToObject)
2656 didFoldClobberWorld();
2657 destination = source;
2658 break;
2659 }
2660
2661 if (node->op() == ToObject)
2662 clobberWorld();
2663 setTypeForNode(node, SpecObject);
2664 break;
2665 }
2666
2667 case PhantomNewObject:
2668 case PhantomNewFunction:
2669 case PhantomNewGeneratorFunction:
2670 case PhantomNewAsyncGeneratorFunction:
2671 case PhantomNewAsyncFunction:
2672 case PhantomCreateActivation:
2673 case PhantomDirectArguments:
2674 case PhantomClonedArguments:
2675 case PhantomCreateRest:
2676 case PhantomSpread:
2677 case PhantomNewArrayWithSpread:
2678 case PhantomNewArrayBuffer:
2679 case PhantomNewRegexp:
2680 case BottomValue: {
2681 clearForNode(node);
2682 break;
2683 }
2684
2685 case PutHint:
2686 break;
2687
2688 case MaterializeNewObject: {
2689 setForNode(node, node->structureSet());
2690 break;
2691 }
2692
2693 case PushWithScope:
2694 // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated.
2695 setTypeForNode(node, SpecObjectOther);
2696 break;
2697
2698 case CreateActivation:
2699 case MaterializeCreateActivation:
2700 setForNode(node,
2701 m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
2702 break;
2703
2704 case CreateDirectArguments:
2705 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
2706 break;
2707
2708 case CreateScopedArguments:
2709 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
2710 break;
2711
2712 case CreateClonedArguments:
2713 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
2714 setTypeForNode(node, SpecObject);
2715 break;
2716 }
2717 setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
2718 break;
2719
2720 case NewGeneratorFunction:
2721 setForNode(node,
2722 m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
2723 break;
2724
2725 case NewAsyncGeneratorFunction:
2726 setForNode(node,
2727 m_codeBlock->globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure());
2728 break;
2729
2730 case NewAsyncFunction:
2731 setForNode(node,
2732 m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
2733 break;
2734
2735 case NewFunction: {
2736 JSGlobalObject* globalObject = m_codeBlock->globalObjectFor(node->origin.semantic);
2737 Structure* structure = JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>());
2738 setForNode(node, structure);
2739 break;
2740 }
2741
2742 case GetCallee:
2743 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
2744 InferredValue* singleton = executable->singletonFunction();
2745 if (JSValue value = singleton->inferredValue()) {
2746 m_graph.watchpoints().addLazily(singleton);
2747 JSFunction* function = jsCast<JSFunction*>(value);
2748 setConstant(node, *m_graph.freeze(function));
2749 break;
2750 }
2751 }
2752 setTypeForNode(node, SpecFunction | SpecObjectOther);
2753 break;
2754
2755 case GetArgumentCountIncludingThis:
2756 setTypeForNode(node, SpecInt32Only);
2757 break;
2758
2759 case SetCallee:
2760 case SetArgumentCountIncludingThis:
2761 break;
2762
2763 case GetRestLength:
2764 setNonCellTypeForNode(node, SpecInt32Only);
2765 break;
2766
2767 case GetGetter: {
2768 JSValue base = forNode(node->child1()).m_value;
2769 if (base) {
2770 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2771 if (!getterSetter->isGetterNull()) {
2772 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
2773 break;
2774 }
2775 }
2776
2777 setTypeForNode(node, SpecObject);
2778 break;
2779 }
2780
2781 case GetSetter: {
2782 JSValue base = forNode(node->child1()).m_value;
2783 if (base) {
2784 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
2785 if (!getterSetter->isSetterNull()) {
2786 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
2787 break;
2788 }
2789 }
2790
2791 setTypeForNode(node, SpecObject);
2792 break;
2793 }
2794
2795 case GetScope:
2796 if (JSValue base = forNode(node->child1()).m_value) {
2797 if (JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
2798 setConstant(node, *m_graph.freeze(function->scope()));
2799 break;
2800 }
2801 }
2802 setTypeForNode(node, SpecObjectOther);
2803 break;
2804
2805 case SkipScope: {
2806 JSValue child = forNode(node->child1()).value();
2807 if (child) {
2808 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
2809 break;
2810 }
2811 setTypeForNode(node, SpecObjectOther);
2812 break;
2813 }
2814
2815 case GetGlobalObject: {
2816 JSValue child = forNode(node->child1()).value();
2817 if (child) {
2818 setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject(m_vm))));
2819 break;
2820 }
2821
2822 if (forNode(node->child1()).m_structure.isFinite()) {
2823 JSGlobalObject* globalObject = nullptr;
2824 bool ok = true;
2825 forNode(node->child1()).m_structure.forEach(
2826 [&] (RegisteredStructure structure) {
2827 if (!globalObject)
2828 globalObject = structure->globalObject();
2829 else if (globalObject != structure->globalObject())
2830 ok = false;
2831 });
2832 if (globalObject && ok) {
2833 setConstant(node, *m_graph.freeze(JSValue(globalObject)));
2834 break;
2835 }
2836 }
2837
2838 setTypeForNode(node, SpecObjectOther);
2839 break;
2840 }
2841
2842 case GetGlobalThis: {
2843 setTypeForNode(node, SpecObject);
2844 break;
2845 }
2846
2847 case GetClosureVar:
2848 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
2849 setConstant(node, *m_graph.freeze(value));
2850 break;
2851 }
2852 makeBytecodeTopForNode(node);
2853 break;
2854
2855 case PutClosureVar:
2856 break;
2857
2858 case GetRegExpObjectLastIndex:
2859 makeHeapTopForNode(node);
2860 break;
2861
2862 case SetRegExpObjectLastIndex:
2863 case RecordRegExpCachedResult:
2864 break;
2865
2866 case GetFromArguments:
2867 makeHeapTopForNode(node);
2868 break;
2869
2870 case PutToArguments:
2871 break;
2872
2873 case GetArgument:
2874 makeHeapTopForNode(node);
2875 break;
2876
2877 case TryGetById:
2878 // FIXME: This should constant fold at least as well as the normal GetById case.
2879 // https://bugs.webkit.org/show_bug.cgi?id=156422
2880 makeHeapTopForNode(node);
2881 break;
2882
2883 case GetByIdDirect:
2884 case GetByIdDirectFlush:
2885 case GetById:
2886 case GetByIdFlush: {
2887 AbstractValue& value = forNode(node->child1());
2888 if (value.m_structure.isFinite()
2889 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
2890 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
2891 GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.toStructureSet(), uid);
2892 if (status.isSimple()) {
2893 // Figure out what the result is going to be - is it TOP, a constant, or maybe
2894 // something more subtle?
2895 AbstractValue result;
2896 for (unsigned i = status.numVariants(); i--;) {
2897 // This thing won't give us a variant that involves prototypes. If it did, we'd
2898 // have more work to do here.
2899 DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
2900
2901 result.merge(
2902 m_graph.inferredValueForProperty(
2903 value, status[i].offset(), m_state.structureClobberState()));
2904 }
2905
2906 m_state.setFoundConstants(true);
2907 didFoldClobberWorld();
2908 forNode(node) = result;
2909 break;
2910 }
2911 }
2912
2913 clobberWorld();
2914 makeHeapTopForNode(node);
2915 break;
2916 }
2917
2918 case GetByValWithThis:
2919 case GetByIdWithThis:
2920 clobberWorld();
2921 makeHeapTopForNode(node);
2922 break;
2923
2924 case GetArrayLength: {
2925 JSArrayBufferView* view = m_graph.tryGetFoldableView(
2926 forNode(node->child1()).m_value, node->arrayMode());
2927 if (view) {
2928 setConstant(node, jsNumber(view->length()));
2929 break;
2930 }
2931 setNonCellTypeForNode(node, SpecInt32Only);
2932 break;
2933 }
2934
2935 case GetVectorLength: {
2936 setNonCellTypeForNode(node, SpecInt32Only);
2937 break;
2938 }
2939
2940 case DeleteById:
2941 case DeleteByVal: {
2942 // FIXME: This could decide if the delete will be successful based on the set of structures that
2943 // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
2944 clobberWorld();
2945 setNonCellTypeForNode(node, SpecBoolean);
2946 break;
2947 }
2948
2949 case CheckStructure: {
2950 AbstractValue& value = forNode(node->child1());
2951
2952 const RegisteredStructureSet& set = node->structureSet();
2953
2954 // It's interesting that we could have proven that the object has a larger structure set
2955 // that includes the set we're testing. In that case we could make the structure check
2956 // more efficient. We currently don't.
2957
2958 if (value.m_structure.isSubsetOf(set))
2959 m_state.setFoundConstants(true);
2960
2961 SpeculatedType admittedTypes = SpecNone;
2962 switch (node->child1().useKind()) {
2963 case CellUse:
2964 case KnownCellUse:
2965 admittedTypes = SpecNone;
2966 break;
2967 case CellOrOtherUse:
2968 admittedTypes = SpecOther;
2969 break;
2970 default:
2971 DFG_CRASH(m_graph, node, "Bad use kind");
2972 break;
2973 }
2974
2975 filter(value, set, admittedTypes);
2976 break;
2977 }
2978
2979 case CheckStructureOrEmpty: {
2980 AbstractValue& value = forNode(node->child1());
2981
2982 bool mayBeEmpty = value.m_type & SpecEmpty;
2983 if (!mayBeEmpty)
2984 m_state.setFoundConstants(true);
2985
2986 SpeculatedType admittedTypes = mayBeEmpty ? SpecEmpty : SpecNone;
2987 filter(value, node->structureSet(), admittedTypes);
2988 break;
2989 }
2990
2991 case CheckStructureImmediate: {
2992 // FIXME: This currently can only reason about one structure at a time.
2993 // https://bugs.webkit.org/show_bug.cgi?id=136988
2994
2995 AbstractValue& value = forNode(node->child1());
2996 const RegisteredStructureSet& set = node->structureSet();
2997
2998 if (value.value()) {
2999 if (Structure* structure = jsDynamicCast<Structure*>(m_vm, value.value())) {
3000 if (set.contains(m_graph.registerStructure(structure))) {
3001 m_state.setFoundConstants(true);
3002 break;
3003 }
3004 }
3005 m_state.setIsValid(false);
3006 break;
3007 }
3008
3009 if (m_phiChildren) {
3010 bool allGood = true;
3011 m_phiChildren->forAllTransitiveIncomingValues(
3012 node,
3013 [&] (Node* incoming) {
3014 if (Structure* structure = incoming->dynamicCastConstant<Structure*>(m_vm)) {
3015 if (set.contains(m_graph.registerStructure(structure)))
3016 return;
3017 }
3018 allGood = false;
3019 });
3020 if (allGood) {
3021 m_state.setFoundConstants(true);
3022 break;
3023 }
3024 }
3025
3026 if (RegisteredStructure structure = set.onlyStructure()) {
3027 filterByValue(node->child1(), *m_graph.freeze(structure.get()));
3028 break;
3029 }
3030
3031 // Aw shucks, we can't do anything!
3032 break;
3033 }
3034
3035 case PutStructure:
3036 if (!forNode(node->child1()).m_structure.isClear()) {
3037 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) {
3038 didFoldClobberStructures();
3039 m_state.setFoundConstants(true);
3040 } else {
3041 observeTransition(
3042 clobberLimit, node->transition()->previous, node->transition()->next);
3043 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
3044 }
3045 } else {
3046 // We're going to exit before we get here, but for the sake of validation, we've folded our write to StructureID.
3047 didFoldClobberStructures();
3048 }
3049 break;
3050 case GetButterfly:
3051 case AllocatePropertyStorage:
3052 case ReallocatePropertyStorage:
3053 case NukeStructureAndSetButterfly:
3054 // FIXME: We don't model the fact that the structureID is nuked, simply because currently
3055 // nobody would currently benefit from having that information. But it's a bug nonetheless.
3056 if (node->op() == NukeStructureAndSetButterfly)
3057 didFoldClobberStructures();
3058 clearForNode(node); // The result is not a JS value.
3059 break;
3060 case CheckSubClass: {
3061 JSValue constant = forNode(node->child1()).value();
3062 if (constant) {
3063 if (constant.isCell() && constant.asCell()->inherits(m_vm, node->classInfo())) {
3064 m_state.setFoundConstants(true);
3065 ASSERT(constant);
3066 break;
3067 }
3068 }
3069
3070 AbstractValue& value = forNode(node->child1());
3071
3072 if (value.m_structure.isSubClassOf(node->classInfo()))
3073 m_state.setFoundConstants(true);
3074
3075 filterClassInfo(value, node->classInfo());
3076 break;
3077 }
3078 case CallDOMGetter: {
3079 CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
3080 DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet;
3081 if (!snippet || snippet->effect.writes)
3082 clobberWorld();
3083 if (callDOMGetterData->domJIT)
3084 setTypeForNode(node, callDOMGetterData->domJIT->resultType());
3085 else
3086 makeBytecodeTopForNode(node);
3087 break;
3088 }
3089 case CallDOM: {
3090 const DOMJIT::Signature* signature = node->signature();
3091 if (signature->effect.writes)
3092 clobberWorld();
3093 setTypeForNode(node, signature->result);
3094 break;
3095 }
3096 case CheckArray: {
3097 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
3098 m_state.setFoundConstants(true);
3099 break;
3100 }
3101 switch (node->arrayMode().type()) {
3102 case Array::String:
3103 filter(node->child1(), SpecString);
3104 break;
3105 case Array::Int32:
3106 case Array::Double:
3107 case Array::Contiguous:
3108 case Array::Undecided:
3109 case Array::ArrayStorage:
3110 case Array::SlowPutArrayStorage:
3111 break;
3112 case Array::DirectArguments:
3113 filter(node->child1(), SpecDirectArguments);
3114 break;
3115 case Array::ScopedArguments:
3116 filter(node->child1(), SpecScopedArguments);
3117 break;
3118 case Array::Int8Array:
3119 filter(node->child1(), SpecInt8Array);
3120 break;
3121 case Array::Int16Array:
3122 filter(node->child1(), SpecInt16Array);
3123 break;
3124 case Array::Int32Array:
3125 filter(node->child1(), SpecInt32Array);
3126 break;
3127 case Array::Uint8Array:
3128 filter(node->child1(), SpecUint8Array);
3129 break;
3130 case Array::Uint8ClampedArray:
3131 filter(node->child1(), SpecUint8ClampedArray);
3132 break;
3133 case Array::Uint16Array:
3134 filter(node->child1(), SpecUint16Array);
3135 break;
3136 case Array::Uint32Array:
3137 filter(node->child1(), SpecUint32Array);
3138 break;
3139 case Array::Float32Array:
3140 filter(node->child1(), SpecFloat32Array);
3141 break;
3142 case Array::Float64Array:
3143 filter(node->child1(), SpecFloat64Array);
3144 break;
3145 case Array::AnyTypedArray:
3146 filter(node->child1(), SpecTypedArrayView);
3147 break;
3148 default:
3149 RELEASE_ASSERT_NOT_REACHED();
3150 break;
3151 }
3152 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
3153 break;
3154 }
3155 case Arrayify: {
3156 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
3157 didFoldClobberStructures();
3158 m_state.setFoundConstants(true);
3159 break;
3160 }
3161 ASSERT(node->arrayMode().conversion() == Array::Convert);
3162 clobberStructures();
3163 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
3164 break;
3165 }
3166 case ArrayifyToStructure: {
3167 AbstractValue& value = forNode(node->child1());
3168 if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
3169 m_state.setFoundConstants(true);
3170 clobberStructures();
3171
3172 // We have a bunch of options of how to express the abstract set at this point. Let set S
3173 // be the set of structures that the value had before clobbering and assume that all of
3174 // them are watchable. The new value should be the least expressible upper bound of the
3175 // intersection of "values that currently have structure = node->structure()" and "values
3176 // that have structure in S plus any structure transition-reachable from S". Assume that
3177 // node->structure() is not in S but it is transition-reachable from S. Then we would
3178 // like to say that the result is "values that have structure = node->structure() until
3179 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
3180 // we must choose between:
3181 //
3182 // 1) "values that currently have structure = node->structure()". This is a valid
3183 // superset of the value that we really want, and it's specific enough to satisfy the
3184 // preconditions of the array access that this is guarding. It's also specific enough
3185 // to allow relevant optimizations in the case that we didn't have a contradiction
3186 // like in this example. Notice that in the abscence of any contradiction, this result
3187 // is precise rather than being a conservative LUB.
3188 //
3189 // 2) "values that currently hava structure in S plus any structure transition-reachable
3190 // from S". This is also a valid superset of the value that we really want, but it's
3191 // not specific enough to satisfy the preconditions of the array access that this is
3192 // guarding - so playing such shenanigans would preclude us from having assertions on
3193 // the typing preconditions of any array accesses. This would also not be a desirable
3194 // answer in the absence of a contradiction.
3195 //
3196 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
3197 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
3198 // yet.
3199 forNode(node->child1()).set(m_graph, node->structure());
3200 break;
3201 }
3202 case GetIndexedPropertyStorage: {
3203 JSArrayBufferView* view = m_graph.tryGetFoldableView(
3204 forNode(node->child1()).m_value, node->arrayMode());
3205 if (view)
3206 m_state.setFoundConstants(true);
3207 clearForNode(node);
3208 break;
3209 }
3210 case ConstantStoragePointer: {
3211 clearForNode(node);
3212 break;
3213 }
3214
3215 case GetTypedArrayByteOffset: {
3216 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
3217 if (view) {
3218 setConstant(node, jsNumber(view->byteOffset()));
3219 break;
3220 }
3221 setNonCellTypeForNode(node, SpecInt32Only);
3222 break;
3223 }
3224
3225 case GetPrototypeOf: {
3226 AbstractValue& value = forNode(node->child1());
3227 if ((value.m_type && !(value.m_type & ~SpecObject)) && value.m_structure.isFinite()) {
3228 bool canFold = !value.m_structure.isClear();
3229 JSValue prototype;
3230 value.m_structure.forEach([&] (RegisteredStructure structure) {
3231 auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3232 MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3233 if (getPrototypeMethod != defaultGetPrototype) {
3234 canFold = false;
3235 return;
3236 }
3237
3238 if (structure->hasPolyProto()) {
3239 canFold = false;
3240 return;
3241 }
3242 if (!prototype)
3243 prototype = structure->storedPrototype();
3244 else if (prototype != structure->storedPrototype())
3245 canFold = false;
3246 });
3247
3248 if (prototype && canFold) {
3249 switch (node->child1().useKind()) {
3250 case ArrayUse:
3251 case FunctionUse:
3252 case FinalObjectUse:
3253 break;
3254 default:
3255 didFoldClobberWorld();
3256 break;
3257 }
3258 setConstant(node, *m_graph.freeze(prototype));
3259 break;
3260 }
3261 }
3262
3263 switch (node->child1().useKind()) {
3264 case ArrayUse:
3265 case FunctionUse:
3266 case FinalObjectUse:
3267 break;
3268 default:
3269 clobberWorld();
3270 break;
3271 }
3272 setTypeForNode(node, SpecObject | SpecOther);
3273 break;
3274 }
3275
3276 case GetByOffset: {
3277 StorageAccessData& data = node->storageAccessData();
3278
3279 // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
3280 // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
3281 // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
3282 // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
3283 // on the type that ByteCodeParser was able to prove.
3284 AbstractValue value = m_graph.inferredValueForProperty(
3285 forNode(node->child2()), data.offset, m_state.structureClobberState());
3286
3287 // If we decide that there does not exist any value that this can return, then it's probably
3288 // because the compilation was already invalidated.
3289 if (value.isClear())
3290 m_state.setIsValid(false);
3291
3292 setForNode(node, value);
3293 if (value.m_value)
3294 m_state.setFoundConstants(true);
3295 break;
3296 }
3297
3298 case GetGetterSetterByOffset: {
3299 StorageAccessData& data = node->storageAccessData();
3300 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
3301 if (result && jsDynamicCast<GetterSetter*>(m_vm, result)) {
3302 setConstant(node, *m_graph.freeze(result));
3303 break;
3304 }
3305
3306 setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
3307 break;
3308 }
3309
3310 case MultiGetByOffset: {
3311 // This code will filter the base value in a manner that is possibly different (either more
3312 // or less precise) than the way it would be filtered if this was strength-reduced to a
3313 // CheckStructure. This is fine. It's legal for different passes over the code to prove
3314 // different things about the code, so long as all of them are sound. That even includes
3315 // one guy proving that code should never execute (due to a contradiction) and another guy
3316 // not finding that contradiction. If someone ever proved that there would be a
3317 // contradiction then there must always be a contradiction even if subsequent passes don't
3318 // realize it. This is the case here.
3319
3320 // Ordinarily you have to be careful with calling setFoundConstants()
3321 // because of the effect on compile times, but this node is FTL-only.
3322 m_state.setFoundConstants(true);
3323
3324 AbstractValue base = forNode(node->child1());
3325 RegisteredStructureSet baseSet;
3326 AbstractValue result;
3327 for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
3328 RegisteredStructureSet set = getCase.set();
3329 set.filter(base);
3330 if (set.isEmpty())
3331 continue;
3332 baseSet.merge(set);
3333
3334 switch (getCase.method().kind()) {
3335 case GetByOffsetMethod::Constant: {
3336 AbstractValue thisResult;
3337 thisResult.set(
3338 m_graph,
3339 *getCase.method().constant(),
3340 m_state.structureClobberState());
3341 result.merge(thisResult);
3342 break;
3343 }
3344
3345 default: {
3346 result.makeHeapTop();
3347 break;
3348 } }
3349 }
3350
3351 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
3352 m_state.setIsValid(false);
3353
3354 setForNode(node, result);
3355 break;
3356 }
3357
3358 case PutByOffset: {
3359 break;
3360 }
3361
3362 case MultiPutByOffset: {
3363 RegisteredStructureSet newSet;
3364 TransitionVector transitions;
3365
3366 // Ordinarily you have to be careful with calling setFoundConstants()
3367 // because of the effect on compile times, but this node is FTL-only.
3368 m_state.setFoundConstants(true);
3369
3370 AbstractValue base = forNode(node->child1());
3371 AbstractValue originalValue = forNode(node->child2());
3372 AbstractValue resultingValue;
3373
3374 if (node->multiPutByOffsetData().writesStructures())
3375 didFoldClobberStructures();
3376
3377 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
3378 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
3379 RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
3380 thisSet.filter(base);
3381 if (thisSet.isEmpty())
3382 continue;
3383
3384 AbstractValue thisValue = originalValue;
3385 resultingValue.merge(thisValue);
3386
3387 if (variant.kind() == PutByIdVariant::Transition) {
3388 RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
3389 if (thisSet.onlyStructure() != newStructure) {
3390 transitions.append(
3391 Transition(m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
3392 } // else this is really a replace.
3393 newSet.add(newStructure);
3394 } else {
3395 ASSERT(variant.kind() == PutByIdVariant::Replace);
3396 newSet.merge(thisSet);
3397 }
3398 }
3399
3400 // We need to order AI executing these effects in the same order as they're executed
3401 // at runtime. This is critical when you have JS code like `o.f = o;`. We first
3402 // filter types on o, then transition o. Not the other way around. If we got
3403 // this ordering wrong, we could end up with the wrong type representing o.
3404 setForNode(node->child2(), resultingValue);
3405 if (!!originalValue && !resultingValue)
3406 m_state.setIsValid(false);
3407
3408 observeTransitions(clobberLimit, transitions);
3409 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
3410 m_state.setIsValid(false);
3411 break;
3412 }
3413
3414 case GetExecutable: {
3415 JSValue value = forNode(node->child1()).value();
3416 if (value) {
3417 JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, value);
3418 if (function) {
3419 setConstant(node, *m_graph.freeze(function->executable()));
3420 break;
3421 }
3422 }
3423 setTypeForNode(node, SpecCellOther);
3424 break;
3425 }
3426
3427 case CheckCell: {
3428 JSValue value = forNode(node->child1()).value();
3429 if (value == node->cellOperand()->value()) {
3430 m_state.setFoundConstants(true);
3431 ASSERT(value);
3432 break;
3433 }
3434 filterByValue(node->child1(), *node->cellOperand());
3435 break;
3436 }
3437
3438 case AssertNotEmpty:
3439 case CheckNotEmpty: {
3440 AbstractValue& value = forNode(node->child1());
3441 if (!(value.m_type & SpecEmpty)) {
3442 m_state.setFoundConstants(true);
3443 break;
3444 }
3445
3446 filter(value, ~SpecEmpty);
3447 break;
3448 }
3449
3450 case CheckStringIdent: {
3451 AbstractValue& value = forNode(node->child1());
3452 UniquedStringImpl* uid = node->uidOperand();
3453 ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
3454
3455 JSValue childConstant = value.value();
3456 if (childConstant) {
3457 ASSERT(childConstant.isString());
3458 if (asString(childConstant)->tryGetValueImpl() == uid) {
3459 m_state.setFoundConstants(true);
3460 break;
3461 }
3462 }
3463
3464 filter(value, SpecStringIdent);
3465 break;
3466 }
3467
3468 case CheckInBounds: {
3469 JSValue left = forNode(node->child1()).value();
3470 JSValue right = forNode(node->child2()).value();
3471 if (left && right && left.isInt32() && right.isInt32() && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32()))
3472 m_state.setFoundConstants(true);
3473
3474 // We claim we result in Int32. It's not really important what our result is (though we
3475 // don't want to claim we may result in the empty value), other nodes with data flow edges
3476 // to us just do that to maintain the invariant that they can't be hoisted higher than us.
3477 // So we just arbitrarily pick Int32. In some ways, StorageResult may be the more correct
3478 // thing to do here. We pick NodeResultJS because it makes converting this to an identity
3479 // easier.
3480 setNonCellTypeForNode(node, SpecInt32Only);
3481 break;
3482 }
3483
3484 case PutById:
3485 case PutByIdFlush:
3486 case PutByIdDirect: {
3487 AbstractValue& value = forNode(node->child1());
3488 if (value.m_structure.isFinite()) {
3489 PutByIdStatus status = PutByIdStatus::computeFor(
3490 m_graph.globalObjectFor(node->origin.semantic),
3491 value.m_structure.toStructureSet(),
3492 m_graph.identifiers()[node->identifierNumber()],
3493 node->op() == PutByIdDirect);
3494
3495 if (status.isSimple()) {
3496 RegisteredStructureSet newSet;
3497 TransitionVector transitions;
3498
3499 for (unsigned i = status.numVariants(); i--;) {
3500 const PutByIdVariant& variant = status[i];
3501 if (variant.kind() == PutByIdVariant::Transition) {
3502 RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
3503 transitions.append(
3504 Transition(
3505 m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
3506 newSet.add(newStructure);
3507 } else {
3508 ASSERT(variant.kind() == PutByIdVariant::Replace);
3509 newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
3510 }
3511 }
3512
3513 if (status.numVariants() == 1 || m_graph.m_plan.isFTL())
3514 m_state.setFoundConstants(true);
3515
3516 didFoldClobberWorld();
3517 observeTransitions(clobberLimit, transitions);
3518 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
3519 m_state.setIsValid(false);
3520 break;
3521 }
3522 }
3523
3524 clobberWorld();
3525 break;
3526 }
3527
3528 case PutByValWithThis:
3529 case PutByIdWithThis:
3530 clobberWorld();
3531 break;
3532
3533 case PutGetterById:
3534 case PutSetterById:
3535 case PutGetterSetterById:
3536 case PutGetterByVal:
3537 case PutSetterByVal: {
3538 clobberWorld();
3539 break;
3540 }
3541
3542 case DefineDataProperty:
3543 case DefineAccessorProperty:
3544 clobberWorld();
3545 break;
3546
3547 case InById: {
3548 // FIXME: We can determine when the property definitely exists based on abstract
3549 // value information.
3550 clobberWorld();
3551 filter(node->child1(), SpecObject);
3552 setNonCellTypeForNode(node, SpecBoolean);
3553 break;
3554 }
3555
3556 case InByVal: {
3557 AbstractValue& property = forNode(node->child2());
3558 if (JSValue constant = property.value()) {
3559 if (constant.isString()) {
3560 JSString* string = asString(constant);
3561 const StringImpl* impl = string->tryGetValueImpl();
3562 if (impl && impl->isAtomic())
3563 m_state.setFoundConstants(true);
3564 }
3565 }
3566
3567 // FIXME: We can determine when the property definitely exists based on abstract
3568 // value information.
3569 clobberWorld();
3570 filter(node->child1(), SpecObject);
3571 setNonCellTypeForNode(node, SpecBoolean);
3572 break;
3573 }
3574
3575 case HasOwnProperty: {
3576 clobberWorld();
3577 setNonCellTypeForNode(node, SpecBoolean);
3578 break;
3579 }
3580
3581 case GetEnumerableLength: {
3582 setNonCellTypeForNode(node, SpecInt32Only);
3583 break;
3584 }
3585 case HasGenericProperty: {
3586 setNonCellTypeForNode(node, SpecBoolean);
3587 clobberWorld();
3588 break;
3589 }
3590 case HasStructureProperty: {
3591 setNonCellTypeForNode(node, SpecBoolean);
3592 clobberWorld();
3593 break;
3594 }
3595 case HasIndexedProperty: {
3596 ArrayMode mode = node->arrayMode();
3597 switch (mode.type()) {
3598 case Array::Int32:
3599 case Array::Double:
3600 case Array::Contiguous:
3601 case Array::ArrayStorage: {
3602 break;
3603 }
3604 default: {
3605 clobberWorld();
3606 break;
3607 }
3608 }
3609 setNonCellTypeForNode(node, SpecBoolean);
3610 break;
3611 }
3612 case GetDirectPname: {
3613 clobberWorld();
3614 makeHeapTopForNode(node);
3615 break;
3616 }
3617 case GetPropertyEnumerator: {
3618 setTypeForNode(node, SpecCell);
3619 clobberWorld();
3620 break;
3621 }
3622 case GetEnumeratorStructurePname: {
3623 setTypeForNode(node, SpecString | SpecOther);
3624 break;
3625 }
3626 case GetEnumeratorGenericPname: {
3627 setTypeForNode(node, SpecString | SpecOther);
3628 break;
3629 }
3630 case ToIndexString: {
3631 setTypeForNode(node, SpecString);
3632 break;
3633 }
3634
3635 case GetGlobalVar:
3636 makeHeapTopForNode(node);
3637 break;
3638
3639 case GetGlobalLexicalVariable:
3640 makeBytecodeTopForNode(node);
3641 break;
3642
3643 case GetDynamicVar:
3644 clobberWorld();
3645 makeBytecodeTopForNode(node);
3646 break;
3647
3648 case PutDynamicVar:
3649 clobberWorld();
3650 break;
3651
3652 case ResolveScope:
3653 clobberWorld();
3654 setTypeForNode(node, SpecObject);
3655 break;
3656
3657 case ResolveScopeForHoistingFuncDeclInEval:
3658 clobberWorld();
3659 makeBytecodeTopForNode(node);
3660 break;
3661
3662 case PutGlobalVariable:
3663 case NotifyWrite:
3664 break;
3665
3666 case OverridesHasInstance:
3667 setNonCellTypeForNode(node, SpecBoolean);
3668 break;
3669
3670 case InstanceOf:
3671 clobberWorld();
3672 setNonCellTypeForNode(node, SpecBoolean);
3673 break;
3674
3675 case InstanceOfCustom:
3676 clobberWorld();
3677 setNonCellTypeForNode(node, SpecBoolean);
3678 break;
3679
3680 case MatchStructure: {
3681 AbstractValue base = forNode(node->child1());
3682 RegisteredStructureSet baseSet;
3683
3684 BooleanLattice result = BooleanLattice::Bottom;
3685 for (MatchStructureVariant& variant : node->matchStructureData().variants) {
3686 RegisteredStructure structure = variant.structure;
3687 if (!base.contains(structure)) {
3688 m_state.setFoundConstants(true);
3689 continue;
3690 }
3691
3692 baseSet.add(structure);
3693 result = leastUpperBoundOfBooleanLattices(
3694 result, variant.result ? BooleanLattice::True : BooleanLattice::False);
3695 }
3696
3697 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
3698 m_state.setIsValid(false);
3699
3700 switch (result) {
3701 case BooleanLattice::False:
3702 setConstant(node, jsBoolean(false));
3703 break;
3704 case BooleanLattice::True:
3705 setConstant(node, jsBoolean(true));
3706 break;
3707 default:
3708 setNonCellTypeForNode(node, SpecBoolean);
3709 break;
3710 }
3711 break;
3712 }
3713
3714 case Phi:
3715 RELEASE_ASSERT(m_graph.m_form == SSA);
3716 setForNode(node, forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow)));
3717 // The state of this node would have already been decided, but it may have become a
3718 // constant, in which case we'd like to know.
3719 if (forNode(node).m_value)
3720 m_state.setFoundConstants(true);
3721 break;
3722
3723 case Upsilon: {
3724 NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
3725 if (shadow.isStillValid()) {
3726 m_state.createValueForNode(shadow);
3727 setForNode(shadow, forNode(node->child1()));
3728 }
3729 break;
3730 }
3731
3732 case Flush:
3733 case PhantomLocal:
3734 break;
3735
3736 case Call:
3737 case TailCallInlinedCaller:
3738 case Construct:
3739 case CallVarargs:
3740 case CallForwardVarargs:
3741 case TailCallVarargsInlinedCaller:
3742 case ConstructVarargs:
3743 case ConstructForwardVarargs:
3744 case TailCallForwardVarargsInlinedCaller:
3745 case CallEval:
3746 case DirectCall:
3747 case DirectConstruct:
3748 case DirectTailCallInlinedCaller:
3749 clobberWorld();
3750 makeHeapTopForNode(node);
3751 break;
3752
3753 case ForceOSRExit:
3754 case CheckBadCell:
3755 m_state.setIsValid(false);
3756 break;
3757
3758 case InvalidationPoint:
3759 m_state.setStructureClobberState(StructuresAreWatched);
3760 m_state.observeInvalidationPoint();
3761 break;
3762
3763 case CPUIntrinsic:
3764 if (node->intrinsic() == CPURdtscIntrinsic)
3765 setNonCellTypeForNode(node, SpecInt32Only);
3766 else
3767 setNonCellTypeForNode(node, SpecOther);
3768 break;
3769
3770 case CheckTraps:
3771 case LogShadowChickenPrologue:
3772 case LogShadowChickenTail:
3773 case ProfileType:
3774 case ProfileControlFlow:
3775 case Phantom:
3776 case CountExecution:
3777 case CheckTierUpInLoop:
3778 case CheckTierUpAtReturn:
3779 case SuperSamplerBegin:
3780 case SuperSamplerEnd:
3781 case CheckTierUpAndOSREnter:
3782 case LoopHint:
3783 case ZombieHint:
3784 case ExitOK:
3785 case FilterCallLinkStatus:
3786 case FilterGetByIdStatus:
3787 case FilterPutByIdStatus:
3788 case FilterInByIdStatus:
3789 case ClearCatchLocals:
3790 break;
3791
3792 case CheckTypeInfoFlags: {
3793 const AbstractValue& abstractValue = forNode(node->child1());
3794 unsigned bits = node->typeInfoOperand();
3795 ASSERT(bits);
3796 if (bits == ImplementsDefaultHasInstance) {
3797 if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
3798 m_state.setFoundConstants(true);
3799 break;
3800 }
3801 }
3802
3803 if (JSValue value = abstractValue.value()) {
3804 if (value.isCell()) {
3805 // This works because if we see a cell here, we know it's fully constructed
3806 // and we can read its inline type info flags. These flags don't change over the
3807 // object's lifetime.
3808 if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
3809 m_state.setFoundConstants(true);
3810 break;
3811 }
3812 }
3813 }
3814
3815 if (abstractValue.m_structure.isFinite()) {
3816 bool ok = true;
3817 abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
3818 ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
3819 });
3820 if (ok) {
3821 m_state.setFoundConstants(true);
3822 break;
3823 }
3824 }
3825
3826 break;
3827 }
3828
3829 case ParseInt: {
3830 AbstractValue value = forNode(node->child1());
3831 if (value.m_type && !(value.m_type & ~SpecInt32Only)) {
3832 JSValue radix;
3833 if (!node->child2())
3834 radix = jsNumber(0);
3835 else
3836 radix = forNode(node->child2()).m_value;
3837
3838 if (radix.isNumber()
3839 && (radix.asNumber() == 0 || radix.asNumber() == 10)) {
3840 m_state.setFoundConstants(true);
3841 if (node->child1().useKind() == UntypedUse)
3842 didFoldClobberWorld();
3843 setNonCellTypeForNode(node, SpecInt32Only);
3844 break;
3845 }
3846 }
3847
3848 if (node->child1().useKind() == UntypedUse)
3849 clobberWorld();
3850 setNonCellTypeForNode(node, SpecBytecodeNumber);
3851 break;
3852 }
3853
3854 case CreateRest:
3855 if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
3856 // This means we're already having a bad time.
3857 clobberWorld();
3858 setTypeForNode(node, SpecArray);
3859 break;
3860 }
3861 setForNode(node,
3862 m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
3863 break;
3864
3865 case CheckVarargs:
3866 case Check: {
3867 // Simplify out checks that don't actually do checking.
3868 m_graph.doToChildren(node, [&] (Edge edge) {
3869 if (!edge)
3870 return;
3871 if (edge.isProved() || edge.willNotHaveCheck())
3872 m_state.setFoundConstants(true);
3873 });
3874 break;
3875 }
3876
3877 case SetFunctionName: {
3878 clobberWorld();
3879 break;
3880 }
3881
3882 case StoreBarrier:
3883 case FencedStoreBarrier: {
3884 filter(node->child1(), SpecCell);
3885 break;
3886 }
3887
3888 case DataViewGetInt: {
3889 DataViewData data = node->dataViewData();
3890 if (data.byteSize < 4)
3891 setNonCellTypeForNode(node, SpecInt32Only);
3892 else {
3893 ASSERT(data.byteSize == 4);
3894 if (data.isSigned)
3895 setNonCellTypeForNode(node, SpecInt32Only);
3896 else
3897 setNonCellTypeForNode(node, SpecInt52Any);
3898 }
3899 break;
3900 }
3901
3902 case DataViewGetFloat: {
3903 setNonCellTypeForNode(node, SpecFullDouble);
3904 break;
3905 }
3906
3907 case DataViewSet: {
3908 break;
3909 }
3910
3911 case Unreachable:
3912 // It may be that during a previous run of AI we proved that something was unreachable, but
3913 // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
3914 // monotonically stronger over time. So, we don't assert that AI doesn't reach the
3915 // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
3916 // crash whenever AI fails to be as powerful on run K as it was on run K-1.
3917 m_state.setIsValid(false);
3918 break;
3919
3920 case LastNodeType:
3921 case ArithIMul:
3922 case FiatInt52:
3923 DFG_CRASH(m_graph, node, "Unexpected node type");
3924 break;
3925 }
3926
3927 return m_state.isValid();
3928}
3929
3930template<typename AbstractStateType>
3931void AbstractInterpreter<AbstractStateType>::filterICStatus(Node* node)
3932{
3933 switch (node->op()) {
3934 case FilterCallLinkStatus:
3935 if (JSValue value = forNode(node->child1()).m_value)
3936 node->callLinkStatus()->filter(m_vm, value);
3937 break;
3938
3939 case FilterGetByIdStatus: {
3940 AbstractValue& value = forNode(node->child1());
3941 if (value.m_structure.isFinite())
3942 node->getByIdStatus()->filter(value.m_structure.toStructureSet());
3943 break;
3944 }
3945
3946 case FilterInByIdStatus: {
3947 AbstractValue& value = forNode(node->child1());
3948 if (value.m_structure.isFinite())
3949 node->inByIdStatus()->filter(value.m_structure.toStructureSet());
3950 break;
3951 }
3952
3953 case FilterPutByIdStatus: {
3954 AbstractValue& value = forNode(node->child1());
3955 if (value.m_structure.isFinite())
3956 node->putByIdStatus()->filter(value.m_structure.toStructureSet());
3957 break;
3958 }
3959
3960 default:
3961 RELEASE_ASSERT_NOT_REACHED();
3962 break;
3963 }
3964}
3965
3966template<typename AbstractStateType>
3967bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
3968{
3969 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
3970}
3971
3972template<typename AbstractStateType>
3973bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
3974{
3975 Node* node = m_state.block()->at(indexInBlock);
3976
3977 startExecuting();
3978 executeEdges(node);
3979 return executeEffects(indexInBlock, node);
3980}
3981
3982template<typename AbstractStateType>
3983bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
3984{
3985 startExecuting();
3986 executeEdges(node);
3987 return executeEffects(UINT_MAX, node);
3988}
3989
3990template<typename AbstractStateType>
3991void AbstractInterpreter<AbstractStateType>::clobberWorld()
3992{
3993 clobberStructures();
3994}
3995
3996template<typename AbstractStateType>
3997void AbstractInterpreter<AbstractStateType>::didFoldClobberWorld()
3998{
3999 didFoldClobberStructures();
4000}
4001
4002template<typename AbstractStateType>
4003template<typename Functor>
4004void AbstractInterpreter<AbstractStateType>::forAllValues(
4005 unsigned clobberLimit, Functor& functor)
4006{
4007 if (clobberLimit >= m_state.block()->size())
4008 clobberLimit = m_state.block()->size();
4009 else
4010 clobberLimit++;
4011 ASSERT(clobberLimit <= m_state.block()->size());
4012 for (size_t i = clobberLimit; i--;) {
4013 NodeFlowProjection::forEach(
4014 m_state.block()->at(i),
4015 [&] (NodeFlowProjection nodeProjection) {
4016 functor(forNode(nodeProjection));
4017 });
4018 }
4019 if (m_graph.m_form == SSA) {
4020 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
4021 if (node.isStillValid())
4022 functor(forNode(node));
4023 }
4024 }
4025 for (size_t i = m_state.numberOfArguments(); i--;)
4026 functor(m_state.argument(i));
4027 for (size_t i = m_state.numberOfLocals(); i--;)
4028 functor(m_state.local(i));
4029}
4030
4031template<typename AbstractStateType>
4032void AbstractInterpreter<AbstractStateType>::clobberStructures()
4033{
4034 m_state.clobberStructures();
4035 m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures);
4036 m_state.setStructureClobberState(StructuresAreClobbered);
4037}
4038
4039template<typename AbstractStateType>
4040void AbstractInterpreter<AbstractStateType>::didFoldClobberStructures()
4041{
4042 m_state.mergeClobberState(AbstractInterpreterClobberState::FoldedClobber);
4043}
4044
4045template<typename AbstractStateType>
4046void AbstractInterpreter<AbstractStateType>::observeTransition(
4047 unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
4048{
4049 AbstractValue::TransitionObserver transitionObserver(from, to);
4050 forAllValues(clobberLimit, transitionObserver);
4051
4052 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.
4053
4054 m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
4055}
4056
4057template<typename AbstractStateType>
4058void AbstractInterpreter<AbstractStateType>::observeTransitions(
4059 unsigned clobberLimit, const TransitionVector& vector)
4060{
4061 if (vector.isEmpty())
4062 return;
4063
4064 AbstractValue::TransitionsObserver transitionsObserver(vector);
4065 forAllValues(clobberLimit, transitionsObserver);
4066
4067 if (!ASSERT_DISABLED) {
4068 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
4069 for (unsigned i = vector.size(); i--;)
4070 ASSERT(!vector[i].previous->dfgShouldWatch());
4071 }
4072
4073 m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
4074}
4075
4076template<typename AbstractStateType>
4077void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
4078{
4079 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
4080}
4081
4082template<typename AbstractStateType>
4083void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
4084{
4085 CommaPrinter comma(" ");
4086 HashSet<NodeFlowProjection> seen;
4087 if (m_graph.m_form == SSA) {
4088 for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
4089 seen.add(node);
4090 AbstractValue& value = forNode(node);
4091 if (value.isClear())
4092 continue;
4093 out.print(comma, node, ":", value);
4094 }
4095 }
4096 for (size_t i = 0; i < m_state.block()->size(); ++i) {
4097 NodeFlowProjection::forEach(
4098 m_state.block()->at(i), [&] (NodeFlowProjection nodeProjection) {
4099 seen.add(nodeProjection);
4100 AbstractValue& value = forNode(nodeProjection);
4101 if (value.isClear())
4102 return;
4103 out.print(comma, nodeProjection, ":", value);
4104 });
4105 }
4106 if (m_graph.m_form == SSA) {
4107 for (NodeFlowProjection node : m_state.block()->ssa->liveAtTail) {
4108 if (seen.contains(node))
4109 continue;
4110 AbstractValue& value = forNode(node);
4111 if (value.isClear())
4112 continue;
4113 out.print(comma, node, ":", value);
4114 }
4115 }
4116}
4117
4118template<typename AbstractStateType>
4119FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
4120 AbstractValue& value, const RegisteredStructureSet& set, SpeculatedType admittedTypes)
4121{
4122 if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
4123 return FiltrationOK;
4124 m_state.setIsValid(false);
4125 return Contradiction;
4126}
4127
4128template<typename AbstractStateType>
4129FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
4130 AbstractValue& value, ArrayModes arrayModes)
4131{
4132 if (value.filterArrayModes(arrayModes) == FiltrationOK)
4133 return FiltrationOK;
4134 m_state.setIsValid(false);
4135 return Contradiction;
4136}
4137
4138template<typename AbstractStateType>
4139FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
4140 AbstractValue& value, SpeculatedType type)
4141{
4142 if (value.filter(type) == FiltrationOK)
4143 return FiltrationOK;
4144 m_state.setIsValid(false);
4145 return Contradiction;
4146}
4147
4148template<typename AbstractStateType>
4149FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
4150 AbstractValue& abstractValue, FrozenValue concreteValue)
4151{
4152 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
4153 return FiltrationOK;
4154 m_state.setIsValid(false);
4155 return Contradiction;
4156}
4157
4158template<typename AbstractStateType>
4159FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo(
4160 AbstractValue& value, const ClassInfo* classInfo)
4161{
4162 if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK)
4163 return FiltrationOK;
4164 m_state.setIsValid(false);
4165 return Contradiction;
4166}
4167
4168template<typename AbstractStateType>
4169void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
4170{
4171 JSValue child = forNode(node->child1()).value();
4172 if (Optional<double> number = child.toNumberFromPrimitive()) {
4173 if (node->child1().useKind() != DoubleRepUse)
4174 didFoldClobberWorld();
4175 setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
4176 return;
4177 }
4178 SpeculatedType type;
4179 if (node->child1().useKind() == DoubleRepUse)
4180 type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
4181 else {
4182 clobberWorld();
4183 type = SpecBytecodeNumber;
4184 }
4185 setNonCellTypeForNode(node, type);
4186}
4187
4188} } // namespace JSC::DFG
4189
4190#endif // ENABLE(DFG_JIT)
4191