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