]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGAbstractInterpreterInlines.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGAbstractInterpreterInlines.h
CommitLineData
81345200 1/*
ed1e77d3 2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
81345200
A
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#ifndef DFGAbstractInterpreterInlines_h
27#define DFGAbstractInterpreterInlines_h
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGAbstractInterpreter.h"
32#include "GetByIdStatus.h"
ed1e77d3
A
33#include "GetterSetter.h"
34#include "JITOperations.h"
35#include "MathCommon.h"
81345200
A
36#include "Operations.h"
37#include "PutByIdStatus.h"
38#include "StringObject.h"
39
40namespace JSC { namespace DFG {
41
42template<typename AbstractStateType>
43AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
44 : m_codeBlock(graph.m_codeBlock)
45 , m_graph(graph)
46 , m_state(state)
47{
ed1e77d3
A
48 if (m_graph.m_form == SSA)
49 m_phiChildren = std::make_unique<PhiChildren>(m_graph);
81345200
A
50}
51
52template<typename AbstractStateType>
53AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
54{
55}
56
57template<typename AbstractStateType>
58typename AbstractInterpreter<AbstractStateType>::BooleanResult
59AbstractInterpreter<AbstractStateType>::booleanResult(
60 Node* node, AbstractValue& value)
61{
62 JSValue childConst = value.value();
63 if (childConst) {
64 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
65 return DefinitelyTrue;
66 return DefinitelyFalse;
67 }
68
69 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
ed1e77d3
A
70 if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
71 bool allTrue = true;
72 for (unsigned i = value.m_structure.size(); i--;) {
73 Structure* structure = value.m_structure[i];
74 if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
75 || structure->typeInfo().type() == StringType) {
76 allTrue = false;
77 break;
78 }
79 }
80 if (allTrue)
81345200
A
81 return DefinitelyTrue;
82 }
83
84 return UnknownBooleanResult;
85}
86
87template<typename AbstractStateType>
ed1e77d3 88void AbstractInterpreter<AbstractStateType>::startExecuting()
81345200
A
89{
90 ASSERT(m_state.block());
91 ASSERT(m_state.isValid());
92
93 m_state.setDidClobber(false);
81345200
A
94}
95
96template<typename AbstractStateType>
97void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
98{
99 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
100}
101
102template<typename AbstractStateType>
103void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
104{
105 executeEdges(m_state.block()->at(indexInBlock));
106}
107
108template<typename AbstractStateType>
ed1e77d3 109void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
81345200 110{
ed1e77d3
A
111 if (!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())))
112 return;
113
114 DFG_CRASH(m_graph, node, toCString("Edge verification error: ", node, "->", edge, " was expected to have type ", SpeculationDump(typeFilterFor(edge.useKind())), " but has type ", SpeculationDump(forNode(edge).m_type), " (", forNode(edge).m_type, ")").data());
81345200
A
115}
116
117template<typename AbstractStateType>
118void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
119{
120 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
121}
122
123template<typename AbstractStateType>
124bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
125{
126 if (!ASSERT_DISABLED)
127 verifyEdges(node);
128
129 m_state.createValueForNode(node);
130
131 switch (node->op()) {
132 case JSConstant:
133 case DoubleConstant:
ed1e77d3
A
134 case Int52Constant: {
135 setBuiltInConstant(node, *node->constant());
81345200
A
136 break;
137 }
138
139 case Identity: {
140 forNode(node) = forNode(node->child1());
ed1e77d3
A
141 if (forNode(node).value())
142 m_state.setFoundConstants(true);
81345200
A
143 break;
144 }
145
146 case ExtractOSREntryLocal: {
ed1e77d3 147 forNode(node).makeBytecodeTop();
81345200
A
148 break;
149 }
150
151 case GetLocal: {
152 VariableAccessData* variableAccessData = node->variableAccessData();
153 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
ed1e77d3
A
154 // The value in the local should already be checked.
155 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
156 if (value.value())
157 m_state.setFoundConstants(true);
158 forNode(node) = value;
159 break;
160 }
161
162 case GetStack: {
163 StackAccessData* data = node->stackAccessData();
164 AbstractValue value = m_state.variables().operand(data->local);
165 // The value in the local should already be checked.
166 DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
81345200
A
167 if (value.value())
168 m_state.setFoundConstants(true);
169 forNode(node) = value;
170 break;
171 }
172
173 case GetLocalUnlinked: {
174 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
175 if (value.value())
176 m_state.setFoundConstants(true);
177 forNode(node) = value;
178 break;
179 }
180
181 case SetLocal: {
ed1e77d3
A
182 m_state.variables().operand(node->local()) = forNode(node->child1());
183 break;
184 }
185
186 case PutStack: {
187 m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1());
81345200
A
188 break;
189 }
190
191 case MovHint: {
192 // Don't need to do anything. A MovHint only informs us about what would have happened
193 // in bytecode, but this code is just concerned with what is actually happening during
194 // DFG execution.
195 break;
196 }
197
ed1e77d3
A
198 case KillStack: {
199 // This is just a hint telling us that the OSR state of the local is no longer inside the
200 // flushed data.
201 break;
202 }
203
81345200 204 case SetArgument:
ed1e77d3
A
205 // Assert that the state of arguments has been set. SetArgument means that someone set
206 // the argument values out-of-band, and currently this always means setting to a
207 // non-clear value.
208 ASSERT(!m_state.variables().operand(node->local()).isClear());
81345200 209 break;
ed1e77d3
A
210
211 case LoadVarargs:
212 case ForwardVarargs: {
213 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
214 // itself into a straight-line sequence of GetStack/PutStack.
215 // https://bugs.webkit.org/show_bug.cgi?id=143071
216 clobberWorld(node->origin.semantic, clobberLimit);
217 LoadVarargsData* data = node->loadVarargsData();
218 m_state.variables().operand(data->count).setType(SpecInt32);
219 for (unsigned i = data->limit - 1; i--;)
220 m_state.variables().operand(data->start.offset() + i).makeHeapTop();
221 break;
222 }
81345200
A
223
224 case BitAnd:
225 case BitOr:
226 case BitXor:
227 case BitRShift:
228 case BitLShift:
229 case BitURShift: {
230 JSValue left = forNode(node->child1()).value();
231 JSValue right = forNode(node->child2()).value();
232 if (left && right && left.isInt32() && right.isInt32()) {
233 int32_t a = left.asInt32();
234 int32_t b = right.asInt32();
235 switch (node->op()) {
236 case BitAnd:
237 setConstant(node, JSValue(a & b));
238 break;
239 case BitOr:
240 setConstant(node, JSValue(a | b));
241 break;
242 case BitXor:
243 setConstant(node, JSValue(a ^ b));
244 break;
245 case BitRShift:
246 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
247 break;
248 case BitLShift:
249 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
250 break;
251 case BitURShift:
252 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
253 break;
254 default:
255 RELEASE_ASSERT_NOT_REACHED();
256 break;
257 }
258 break;
259 }
ed1e77d3
A
260
261 if (node->op() == BitAnd
262 && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
263 isBoolInt32Speculation(forNode(node->child2()).m_type))) {
264 forNode(node).setType(SpecBoolInt32);
265 break;
266 }
267
81345200
A
268 forNode(node).setType(SpecInt32);
269 break;
270 }
271
272 case UInt32ToNumber: {
273 JSValue child = forNode(node->child1()).value();
274 if (doesOverflow(node->arithMode())) {
275 if (child && child.isInt32()) {
276 uint32_t value = child.asInt32();
277 setConstant(node, jsNumber(value));
278 break;
279 }
280 forNode(node).setType(SpecInt52AsDouble);
281 break;
282 }
283 if (child && child.isInt32()) {
284 int32_t value = child.asInt32();
285 if (value >= 0) {
286 setConstant(node, jsNumber(value));
287 break;
288 }
289 }
290 forNode(node).setType(SpecInt32);
81345200
A
291 break;
292 }
293
294 case BooleanToNumber: {
295 JSValue concreteValue = forNode(node->child1()).value();
296 if (concreteValue) {
297 if (concreteValue.isBoolean())
298 setConstant(node, jsNumber(concreteValue.asBoolean()));
299 else
ed1e77d3 300 setConstant(node, *m_graph.freeze(concreteValue));
81345200
A
301 break;
302 }
303 AbstractValue& value = forNode(node);
304 value = forNode(node->child1());
305 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
306 m_state.setFoundConstants(true);
307 if (value.m_type & SpecBoolean) {
ed1e77d3 308 value.merge(SpecBoolInt32);
81345200
A
309 value.filter(~SpecBoolean);
310 }
311 break;
312 }
313
314 case DoubleAsInt32: {
315 JSValue child = forNode(node->child1()).value();
316 if (child && child.isNumber()) {
317 double asDouble = child.asNumber();
318 int32_t asInt = JSC::toInt32(asDouble);
319 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
320 setConstant(node, JSValue(asInt));
321 break;
322 }
323 }
81345200
A
324 forNode(node).setType(SpecInt32);
325 break;
326 }
327
328 case ValueToInt32: {
329 JSValue child = forNode(node->child1()).value();
330 if (child) {
331 if (child.isNumber()) {
332 if (child.isInt32())
333 setConstant(node, child);
334 else
335 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
336 break;
337 }
338 if (child.isBoolean()) {
339 setConstant(node, jsNumber(child.asBoolean()));
340 break;
341 }
342 if (child.isUndefinedOrNull()) {
343 setConstant(node, jsNumber(0));
344 break;
345 }
346 }
347
ed1e77d3
A
348 if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
349 forNode(node).setType(SpecBoolInt32);
350 break;
351 }
352
81345200
A
353 forNode(node).setType(SpecInt32);
354 break;
355 }
356
357 case DoubleRep: {
358 JSValue child = forNode(node->child1()).value();
359 if (child && child.isNumber()) {
360 setConstant(node, jsDoubleNumber(child.asNumber()));
361 break;
362 }
ed1e77d3
A
363
364 SpeculatedType type = forNode(node->child1()).m_type;
365 switch (node->child1().useKind()) {
366 case NotCellUse: {
367 if (type & SpecOther) {
368 type &= ~SpecOther;
369 type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
370 }
371 if (type & SpecBoolean) {
372 type &= ~SpecBoolean;
373 type |= SpecBoolInt32; // True becomes 1, false becomes 0.
374 }
375 type &= SpecBytecodeNumber;
376 break;
377 }
378
379 case Int52RepUse:
380 case NumberUse:
381 case RealNumberUse:
382 break;
383
384 default:
385 RELEASE_ASSERT_NOT_REACHED();
386 }
387 forNode(node).setType(type);
388 forNode(node).fixTypeForRepresentation(m_graph, node);
81345200
A
389 break;
390 }
391
392 case Int52Rep: {
393 JSValue child = forNode(node->child1()).value();
394 if (child && child.isMachineInt()) {
395 setConstant(node, child);
396 break;
397 }
398
399 forNode(node).setType(SpecInt32);
400 break;
401 }
402
403 case ValueRep: {
404 JSValue value = forNode(node->child1()).value();
405 if (value) {
406 setConstant(node, value);
407 break;
408 }
409
ed1e77d3
A
410 forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
411 forNode(node).fixTypeForRepresentation(m_graph, node);
81345200
A
412 break;
413 }
414
415 case ValueAdd: {
416 ASSERT(node->binaryUseKind() == UntypedUse);
417 clobberWorld(node->origin.semantic, clobberLimit);
ed1e77d3 418 forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
81345200
A
419 break;
420 }
421
422 case ArithAdd: {
423 JSValue left = forNode(node->child1()).value();
424 JSValue right = forNode(node->child2()).value();
425 switch (node->binaryUseKind()) {
426 case Int32Use:
427 if (left && right && left.isInt32() && right.isInt32()) {
428 if (!shouldCheckOverflow(node->arithMode())) {
429 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
430 break;
431 }
432 JSValue result = jsNumber(left.asNumber() + right.asNumber());
433 if (result.isInt32()) {
434 setConstant(node, result);
435 break;
436 }
437 }
438 forNode(node).setType(SpecInt32);
81345200
A
439 break;
440 case Int52RepUse:
441 if (left && right && left.isMachineInt() && right.isMachineInt()) {
442 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt());
443 if (result.isMachineInt()) {
444 setConstant(node, result);
445 break;
446 }
447 }
448 forNode(node).setType(SpecMachineInt);
81345200
A
449 break;
450 case DoubleRepUse:
451 if (left && right && left.isNumber() && right.isNumber()) {
452 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
453 break;
454 }
455 forNode(node).setType(
456 typeOfDoubleSum(
457 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
458 break;
459 default:
460 RELEASE_ASSERT_NOT_REACHED();
461 break;
462 }
463 break;
464 }
ed1e77d3
A
465
466 case ArithClz32: {
467 JSValue operand = forNode(node->child1()).value();
468 if (operand && operand.isNumber()) {
469 uint32_t value = toUInt32(operand.asNumber());
470 setConstant(node, jsNumber(clz32(value)));
471 break;
472 }
473 forNode(node).setType(SpecInt32);
474 break;
475 }
476
81345200 477 case MakeRope: {
81345200
A
478 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
479 break;
480 }
481
482 case ArithSub: {
483 JSValue left = forNode(node->child1()).value();
484 JSValue right = forNode(node->child2()).value();
485 switch (node->binaryUseKind()) {
486 case Int32Use:
487 if (left && right && left.isInt32() && right.isInt32()) {
488 if (!shouldCheckOverflow(node->arithMode())) {
489 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
490 break;
491 }
492 JSValue result = jsNumber(left.asNumber() - right.asNumber());
493 if (result.isInt32()) {
494 setConstant(node, result);
495 break;
496 }
497 }
498 forNode(node).setType(SpecInt32);
81345200
A
499 break;
500 case Int52RepUse:
501 if (left && right && left.isMachineInt() && right.isMachineInt()) {
502 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt());
503 if (result.isMachineInt() || !shouldCheckOverflow(node->arithMode())) {
504 setConstant(node, result);
505 break;
506 }
507 }
508 forNode(node).setType(SpecMachineInt);
81345200
A
509 break;
510 case DoubleRepUse:
511 if (left && right && left.isNumber() && right.isNumber()) {
512 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
513 break;
514 }
515 forNode(node).setType(
516 typeOfDoubleDifference(
517 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
518 break;
519 default:
520 RELEASE_ASSERT_NOT_REACHED();
521 break;
522 }
523 break;
524 }
525
526 case ArithNegate: {
527 JSValue child = forNode(node->child1()).value();
528 switch (node->child1().useKind()) {
529 case Int32Use:
530 if (child && child.isInt32()) {
531 if (!shouldCheckOverflow(node->arithMode())) {
532 setConstant(node, jsNumber(-child.asInt32()));
533 break;
534 }
535 double doubleResult;
536 if (shouldCheckNegativeZero(node->arithMode()))
537 doubleResult = -child.asNumber();
538 else
539 doubleResult = 0 - child.asNumber();
540 JSValue valueResult = jsNumber(doubleResult);
541 if (valueResult.isInt32()) {
542 setConstant(node, valueResult);
543 break;
544 }
545 }
546 forNode(node).setType(SpecInt32);
81345200
A
547 break;
548 case Int52RepUse:
549 if (child && child.isMachineInt()) {
550 double doubleResult;
551 if (shouldCheckNegativeZero(node->arithMode()))
552 doubleResult = -child.asNumber();
553 else
554 doubleResult = 0 - child.asNumber();
555 JSValue valueResult = jsNumber(doubleResult);
556 if (valueResult.isMachineInt()) {
557 setConstant(node, valueResult);
558 break;
559 }
560 }
561 forNode(node).setType(SpecMachineInt);
81345200
A
562 break;
563 case DoubleRepUse:
564 if (child && child.isNumber()) {
565 setConstant(node, jsDoubleNumber(-child.asNumber()));
566 break;
567 }
568 forNode(node).setType(
569 typeOfDoubleNegation(
570 forNode(node->child1()).m_type));
571 break;
572 default:
573 RELEASE_ASSERT_NOT_REACHED();
574 break;
575 }
576 break;
577 }
578
579 case ArithMul: {
580 JSValue left = forNode(node->child1()).value();
581 JSValue right = forNode(node->child2()).value();
582 switch (node->binaryUseKind()) {
583 case Int32Use:
584 if (left && right && left.isInt32() && right.isInt32()) {
585 if (!shouldCheckOverflow(node->arithMode())) {
586 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
587 break;
588 }
589 double doubleResult = left.asNumber() * right.asNumber();
590 if (!shouldCheckNegativeZero(node->arithMode()))
591 doubleResult += 0; // Sanitizes zero.
592 JSValue valueResult = jsNumber(doubleResult);
593 if (valueResult.isInt32()) {
594 setConstant(node, valueResult);
595 break;
596 }
597 }
598 forNode(node).setType(SpecInt32);
81345200
A
599 break;
600 case Int52RepUse:
601 if (left && right && left.isMachineInt() && right.isMachineInt()) {
602 double doubleResult = left.asNumber() * right.asNumber();
603 if (!shouldCheckNegativeZero(node->arithMode()))
604 doubleResult += 0;
605 JSValue valueResult = jsNumber(doubleResult);
606 if (valueResult.isMachineInt()) {
607 setConstant(node, valueResult);
608 break;
609 }
610 }
611 forNode(node).setType(SpecMachineInt);
81345200
A
612 break;
613 case DoubleRepUse:
614 if (left && right && left.isNumber() && right.isNumber()) {
615 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
616 break;
617 }
618 forNode(node).setType(
619 typeOfDoubleProduct(
620 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
621 break;
622 default:
623 RELEASE_ASSERT_NOT_REACHED();
624 break;
625 }
626 break;
627 }
628
629 case ArithDiv: {
630 JSValue left = forNode(node->child1()).value();
631 JSValue right = forNode(node->child2()).value();
632 switch (node->binaryUseKind()) {
633 case Int32Use:
634 if (left && right && left.isInt32() && right.isInt32()) {
635 double doubleResult = left.asNumber() / right.asNumber();
636 if (!shouldCheckOverflow(node->arithMode()))
637 doubleResult = toInt32(doubleResult);
638 else if (!shouldCheckNegativeZero(node->arithMode()))
639 doubleResult += 0; // Sanitizes zero.
640 JSValue valueResult = jsNumber(doubleResult);
641 if (valueResult.isInt32()) {
642 setConstant(node, valueResult);
643 break;
644 }
645 }
646 forNode(node).setType(SpecInt32);
81345200
A
647 break;
648 case DoubleRepUse:
649 if (left && right && left.isNumber() && right.isNumber()) {
650 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
651 break;
652 }
653 forNode(node).setType(
654 typeOfDoubleQuotient(
655 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
656 break;
657 default:
658 RELEASE_ASSERT_NOT_REACHED();
659 break;
660 }
661 break;
662 }
663
664 case ArithMod: {
665 JSValue left = forNode(node->child1()).value();
666 JSValue right = forNode(node->child2()).value();
667 switch (node->binaryUseKind()) {
668 case Int32Use:
669 if (left && right && left.isInt32() && right.isInt32()) {
670 double doubleResult = fmod(left.asNumber(), right.asNumber());
671 if (!shouldCheckOverflow(node->arithMode()))
672 doubleResult = toInt32(doubleResult);
673 else if (!shouldCheckNegativeZero(node->arithMode()))
674 doubleResult += 0; // Sanitizes zero.
675 JSValue valueResult = jsNumber(doubleResult);
676 if (valueResult.isInt32()) {
677 setConstant(node, valueResult);
678 break;
679 }
680 }
681 forNode(node).setType(SpecInt32);
81345200
A
682 break;
683 case DoubleRepUse:
684 if (left && right && left.isNumber() && right.isNumber()) {
685 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
686 break;
687 }
688 forNode(node).setType(
689 typeOfDoubleBinaryOp(
690 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
691 break;
692 default:
693 RELEASE_ASSERT_NOT_REACHED();
694 break;
695 }
696 break;
697 }
698
699 case ArithMin: {
700 JSValue left = forNode(node->child1()).value();
701 JSValue right = forNode(node->child2()).value();
702 switch (node->binaryUseKind()) {
703 case Int32Use:
704 if (left && right && left.isInt32() && right.isInt32()) {
705 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
706 break;
707 }
708 forNode(node).setType(SpecInt32);
81345200
A
709 break;
710 case DoubleRepUse:
711 if (left && right && left.isNumber() && right.isNumber()) {
712 double a = left.asNumber();
713 double b = right.asNumber();
714 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
715 break;
716 }
717 forNode(node).setType(
718 typeOfDoubleMinMax(
719 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
720 break;
721 default:
722 RELEASE_ASSERT_NOT_REACHED();
723 break;
724 }
725 break;
726 }
727
728 case ArithMax: {
729 JSValue left = forNode(node->child1()).value();
730 JSValue right = forNode(node->child2()).value();
731 switch (node->binaryUseKind()) {
732 case Int32Use:
733 if (left && right && left.isInt32() && right.isInt32()) {
734 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
735 break;
736 }
737 forNode(node).setType(SpecInt32);
81345200
A
738 break;
739 case DoubleRepUse:
740 if (left && right && left.isNumber() && right.isNumber()) {
741 double a = left.asNumber();
742 double b = right.asNumber();
743 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
744 break;
745 }
746 forNode(node).setType(
747 typeOfDoubleMinMax(
748 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
749 break;
750 default:
751 RELEASE_ASSERT_NOT_REACHED();
752 break;
753 }
754 break;
755 }
756
757 case ArithAbs: {
758 JSValue child = forNode(node->child1()).value();
759 switch (node->child1().useKind()) {
760 case Int32Use:
761 if (child && child.isInt32()) {
762 JSValue result = jsNumber(fabs(child.asNumber()));
763 if (result.isInt32()) {
764 setConstant(node, result);
765 break;
766 }
767 }
768 forNode(node).setType(SpecInt32);
81345200
A
769 break;
770 case DoubleRepUse:
771 if (child && child.isNumber()) {
ed1e77d3 772 setConstant(node, jsDoubleNumber(fabs(child.asNumber())));
81345200
A
773 break;
774 }
775 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
776 break;
777 default:
778 RELEASE_ASSERT_NOT_REACHED();
779 break;
780 }
781 break;
782 }
ed1e77d3
A
783
784 case ArithPow: {
785 JSValue childY = forNode(node->child2()).value();
786 if (childY && childY.isNumber()) {
787 if (!childY.asNumber()) {
788 setConstant(node, jsDoubleNumber(1));
789 break;
790 }
791
792 JSValue childX = forNode(node->child1()).value();
793 if (childX && childX.isNumber()) {
794 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
795 break;
796 }
797 }
798 forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
799 break;
800 }
801
802 case ArithRound: {
803 JSValue operand = forNode(node->child1()).value();
804 if (operand && operand.isNumber()) {
805 double roundedValue = jsRound(operand.asNumber());
806
807 if (producesInteger(node->arithRoundingMode())) {
808 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
809 if (roundedValueAsInt32 == roundedValue) {
810 if (shouldCheckNegativeZero(node->arithRoundingMode())) {
811 if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
812 setConstant(node, jsNumber(roundedValueAsInt32));
813 break;
814 }
815 } else {
816 setConstant(node, jsNumber(roundedValueAsInt32));
817 break;
818 }
819 }
820 } else {
821 setConstant(node, jsDoubleNumber(roundedValue));
822 break;
823 }
824 }
825 if (producesInteger(node->arithRoundingMode()))
826 forNode(node).setType(SpecInt32);
827 else
828 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
829 break;
830 }
81345200
A
831
832 case ArithSqrt: {
833 JSValue child = forNode(node->child1()).value();
834 if (child && child.isNumber()) {
835 setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
836 break;
837 }
838 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
839 break;
840 }
841
842 case ArithFRound: {
843 JSValue child = forNode(node->child1()).value();
844 if (child && child.isNumber()) {
845 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
846 break;
847 }
ed1e77d3 848 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
81345200
A
849 break;
850 }
851
852 case ArithSin: {
853 JSValue child = forNode(node->child1()).value();
854 if (child && child.isNumber()) {
855 setConstant(node, jsDoubleNumber(sin(child.asNumber())));
856 break;
857 }
858 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
859 break;
860 }
861
862 case ArithCos: {
863 JSValue child = forNode(node->child1()).value();
864 if (child && child.isNumber()) {
865 setConstant(node, jsDoubleNumber(cos(child.asNumber())));
866 break;
867 }
868 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
869 break;
870 }
ed1e77d3
A
871
872 case ArithLog: {
873 JSValue child = forNode(node->child1()).value();
874 if (child && child.isNumber()) {
875 setConstant(node, jsDoubleNumber(log(child.asNumber())));
876 break;
877 }
878 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
879 break;
880 }
81345200
A
881
882 case LogicalNot: {
883 switch (booleanResult(node, forNode(node->child1()))) {
884 case DefinitelyTrue:
885 setConstant(node, jsBoolean(false));
886 break;
887 case DefinitelyFalse:
888 setConstant(node, jsBoolean(true));
889 break;
890 default:
81345200
A
891 forNode(node).setType(SpecBoolean);
892 break;
893 }
894 break;
895 }
896
897 case IsUndefined:
898 case IsBoolean:
899 case IsNumber:
900 case IsString:
901 case IsObject:
ed1e77d3 902 case IsObjectOrNull:
81345200 903 case IsFunction: {
ed1e77d3
A
904 AbstractValue child = forNode(node->child1());
905 if (child.value()) {
81345200
A
906 bool constantWasSet = true;
907 switch (node->op()) {
908 case IsUndefined:
909 setConstant(node, jsBoolean(
ed1e77d3
A
910 child.value().isCell()
911 ? child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
912 : child.value().isUndefined()));
81345200
A
913 break;
914 case IsBoolean:
ed1e77d3 915 setConstant(node, jsBoolean(child.value().isBoolean()));
81345200
A
916 break;
917 case IsNumber:
ed1e77d3 918 setConstant(node, jsBoolean(child.value().isNumber()));
81345200
A
919 break;
920 case IsString:
ed1e77d3 921 setConstant(node, jsBoolean(isJSString(child.value())));
81345200
A
922 break;
923 case IsObject:
ed1e77d3
A
924 setConstant(node, jsBoolean(child.value().isObject()));
925 break;
926 case IsObjectOrNull:
927 if (child.value().isObject()) {
928 JSObject* object = asObject(child.value());
929 if (object->type() == JSFunctionType)
930 setConstant(node, jsBoolean(false));
931 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
932 setConstant(node, jsBoolean(!child.value().asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
933 else {
934 // FIXME: This could just call getCallData.
935 // https://bugs.webkit.org/show_bug.cgi?id=144457
936 constantWasSet = false;
937 }
938 } else
939 setConstant(node, jsBoolean(child.value().isNull()));
940 break;
941 case IsFunction:
942 if (child.value().isObject()) {
943 JSObject* object = asObject(child.value());
944 if (object->type() == JSFunctionType)
945 setConstant(node, jsBoolean(true));
946 else if (!(object->inlineTypeFlags() & TypeOfShouldCallGetCallData))
947 setConstant(node, jsBoolean(false));
948 else {
949 // FIXME: This could just call getCallData.
950 // https://bugs.webkit.org/show_bug.cgi?id=144457
951 constantWasSet = false;
952 }
953 } else
954 setConstant(node, jsBoolean(false));
81345200
A
955 break;
956 default:
957 constantWasSet = false;
958 break;
959 }
960 if (constantWasSet)
961 break;
962 }
ed1e77d3
A
963
964 // FIXME: This code should really use AbstractValue::isType() and
965 // AbstractValue::couldBeType().
966 // https://bugs.webkit.org/show_bug.cgi?id=146870
967
968 bool constantWasSet = false;
969 switch (node->op()) {
970 case IsUndefined:
971 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
972 // https://bugs.webkit.org/show_bug.cgi?id=144456
973
974 if (!(child.m_type & (SpecOther | SpecObjectOther))) {
975 setConstant(node, jsBoolean(false));
976 constantWasSet = true;
977 break;
978 }
979
980 break;
981 case IsBoolean:
982 if (!(child.m_type & ~SpecBoolean)) {
983 setConstant(node, jsBoolean(true));
984 constantWasSet = true;
985 break;
986 }
987
988 if (!(child.m_type & SpecBoolean)) {
989 setConstant(node, jsBoolean(false));
990 constantWasSet = true;
991 break;
992 }
993
994 break;
995 case IsNumber:
996 if (!(child.m_type & ~SpecFullNumber)) {
997 setConstant(node, jsBoolean(true));
998 constantWasSet = true;
999 break;
1000 }
1001
1002 if (!(child.m_type & SpecFullNumber)) {
1003 setConstant(node, jsBoolean(false));
1004 constantWasSet = true;
1005 break;
1006 }
1007
1008 break;
1009 case IsString:
1010 if (!(child.m_type & ~SpecString)) {
1011 setConstant(node, jsBoolean(true));
1012 constantWasSet = true;
1013 break;
1014 }
1015
1016 if (!(child.m_type & SpecString)) {
1017 setConstant(node, jsBoolean(false));
1018 constantWasSet = true;
1019 break;
1020 }
1021
1022 break;
1023 case IsObject:
1024 if (!(child.m_type & ~SpecObject)) {
1025 setConstant(node, jsBoolean(true));
1026 constantWasSet = true;
1027 break;
1028 }
1029
1030 if (!(child.m_type & SpecObject)) {
1031 setConstant(node, jsBoolean(false));
1032 constantWasSet = true;
1033 break;
1034 }
1035
1036 break;
1037 case IsObjectOrNull:
1038 // FIXME: Use the masquerades-as-undefined watchpoint thingy.
1039 // https://bugs.webkit.org/show_bug.cgi?id=144456
1040
1041 // These expressions are complicated to parse. A helpful way to parse this is that
1042 // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
1043 // disjoint set from S". Things like "T - S" means that, provided that S is a
1044 // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
1045 // mean the "union of T and S".
1046
1047 // Is the child's type an object that isn't an other-object (i.e. object that could
1048 // have masquaredes-as-undefined traps) and isn't a function? Then: we should fold
1049 // this to true.
1050 if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
1051 setConstant(node, jsBoolean(true));
1052 constantWasSet = true;
1053 break;
1054 }
1055
1056 // Is the child's type definitely not either of: an object that isn't a function,
1057 // or either undefined or null? Then: we should fold this to false. This means
1058 // for example that if it's any non-function object, including those that have
1059 // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
1060 // if it's undefined-or-null, since the type bits don't distinguish between
1061 // undefined (which should fold to false) and null (which should fold to true).
1062 if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
1063 setConstant(node, jsBoolean(false));
1064 constantWasSet = true;
1065 break;
1066 }
1067
1068 break;
1069 case IsFunction:
1070 if (!(child.m_type & ~SpecFunction)) {
1071 setConstant(node, jsBoolean(true));
1072 constantWasSet = true;
1073 break;
1074 }
1075
1076 if (!(child.m_type & (SpecFunction | SpecObjectOther))) {
1077 setConstant(node, jsBoolean(false));
1078 constantWasSet = true;
1079 break;
1080 }
1081 break;
1082 default:
1083 break;
1084 }
1085 if (constantWasSet)
1086 break;
1087
81345200
A
1088 forNode(node).setType(SpecBoolean);
1089 break;
1090 }
1091
1092 case TypeOf: {
1093 VM* vm = m_codeBlock->vm();
1094 JSValue child = forNode(node->child1()).value();
1095 AbstractValue& abstractChild = forNode(node->child1());
1096 if (child) {
1097 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
ed1e77d3 1098 setConstant(node, *m_graph.freeze(typeString));
81345200
A
1099 break;
1100 }
1101
1102 if (isFullNumberSpeculation(abstractChild.m_type)) {
ed1e77d3 1103 setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
81345200
A
1104 break;
1105 }
1106
1107 if (isStringSpeculation(abstractChild.m_type)) {
ed1e77d3 1108 setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
81345200
A
1109 break;
1110 }
ed1e77d3
A
1111
1112 // FIXME: We could use the masquerades-as-undefined watchpoint here.
1113 // https://bugs.webkit.org/show_bug.cgi?id=144456
1114 if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther))) {
1115 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
81345200
A
1116 break;
1117 }
1118
1119 if (isFunctionSpeculation(abstractChild.m_type)) {
ed1e77d3 1120 setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
81345200
A
1121 break;
1122 }
1123
1124 if (isBooleanSpeculation(abstractChild.m_type)) {
ed1e77d3 1125 setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
81345200
A
1126 break;
1127 }
1128
ed1e77d3
A
1129 if (isSymbolSpeculation(abstractChild.m_type)) {
1130 setConstant(node, *m_graph.freeze(vm->smallStrings.symbolString()));
81345200
A
1131 break;
1132 }
ed1e77d3
A
1133
1134 forNode(node).setType(m_graph, SpecStringIdent);
81345200
A
1135 break;
1136 }
1137
1138 case CompareLess:
1139 case CompareLessEq:
1140 case CompareGreater:
1141 case CompareGreaterEq:
1142 case CompareEq:
1143 case CompareEqConstant: {
1144 JSValue leftConst = forNode(node->child1()).value();
1145 JSValue rightConst = forNode(node->child2()).value();
1146 if (leftConst && rightConst) {
1147 if (leftConst.isNumber() && rightConst.isNumber()) {
1148 double a = leftConst.asNumber();
1149 double b = rightConst.asNumber();
1150 switch (node->op()) {
1151 case CompareLess:
1152 setConstant(node, jsBoolean(a < b));
1153 break;
1154 case CompareLessEq:
1155 setConstant(node, jsBoolean(a <= b));
1156 break;
1157 case CompareGreater:
1158 setConstant(node, jsBoolean(a > b));
1159 break;
1160 case CompareGreaterEq:
1161 setConstant(node, jsBoolean(a >= b));
1162 break;
1163 case CompareEq:
1164 setConstant(node, jsBoolean(a == b));
1165 break;
1166 default:
1167 RELEASE_ASSERT_NOT_REACHED();
1168 break;
1169 }
1170 break;
1171 }
1172
1173 if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) {
1174 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
1175 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
1176 if (a && b) {
1177 setConstant(node, jsBoolean(WTF::equal(a, b)));
1178 break;
1179 }
1180 }
1181 }
1182
1183 if (node->op() == CompareEqConstant || node->op() == CompareEq) {
1184 SpeculatedType leftType = forNode(node->child1()).m_type;
1185 SpeculatedType rightType = forNode(node->child2()).m_type;
1186 if (!valuesCouldBeEqual(leftType, rightType)) {
1187 setConstant(node, jsBoolean(false));
1188 break;
1189 }
1190 }
1191
1192 forNode(node).setType(SpecBoolean);
81345200
A
1193 break;
1194 }
1195
1196 case CompareStrictEq: {
1197 Node* leftNode = node->child1().node();
1198 Node* rightNode = node->child2().node();
1199 JSValue left = forNode(leftNode).value();
1200 JSValue right = forNode(rightNode).value();
1201 if (left && right) {
1202 if (left.isString() && right.isString()) {
1203 // We need this case because JSValue::strictEqual is otherwise too racy for
1204 // string comparisons.
1205 const StringImpl* a = asString(left)->tryGetValueImpl();
1206 const StringImpl* b = asString(right)->tryGetValueImpl();
1207 if (a && b) {
1208 setConstant(node, jsBoolean(WTF::equal(a, b)));
1209 break;
1210 }
1211 } else {
1212 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
1213 break;
1214 }
1215 }
1216
1217 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
1218 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1219 if (!(leftLUB & rightLUB)) {
1220 setConstant(node, jsBoolean(false));
1221 break;
1222 }
1223
1224 forNode(node).setType(SpecBoolean);
81345200
A
1225 break;
1226 }
1227
1228 case StringCharCodeAt:
81345200
A
1229 forNode(node).setType(SpecInt32);
1230 break;
1231
1232 case StringFromCharCode:
ed1e77d3 1233 forNode(node).setType(m_graph, SpecString);
81345200
A
1234 break;
1235
1236 case StringCharAt:
81345200
A
1237 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1238 break;
1239
1240 case GetByVal: {
81345200
A
1241 switch (node->arrayMode().type()) {
1242 case Array::SelectUsingPredictions:
1243 case Array::Unprofiled:
1244 case Array::Undecided:
1245 RELEASE_ASSERT_NOT_REACHED();
1246 break;
1247 case Array::ForceExit:
1248 m_state.setIsValid(false);
1249 break;
1250 case Array::Generic:
1251 clobberWorld(node->origin.semantic, clobberLimit);
1252 forNode(node).makeHeapTop();
1253 break;
1254 case Array::String:
1255 if (node->arrayMode().isOutOfBounds()) {
1256 // If the watchpoint was still valid we could totally set this to be
1257 // SpecString | SpecOther. Except that we'd have to be careful. If we
1258 // tested the watchpoint state here then it could change by the time
1259 // we got to the backend. So to do this right, we'd have to get the
1260 // fixup phase to check the watchpoint state and then bake into the
1261 // GetByVal operation the fact that we're using a watchpoint, using
1262 // something like Array::SaneChain (except not quite, because that
1263 // implies an in-bounds access). None of this feels like it's worth it,
1264 // so we're going with TOP for now. The same thing applies to
1265 // clobbering the world.
1266 clobberWorld(node->origin.semantic, clobberLimit);
1267 forNode(node).makeHeapTop();
1268 } else
1269 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1270 break;
ed1e77d3
A
1271 case Array::DirectArguments:
1272 case Array::ScopedArguments:
81345200
A
1273 forNode(node).makeHeapTop();
1274 break;
1275 case Array::Int32:
1276 if (node->arrayMode().isOutOfBounds()) {
1277 clobberWorld(node->origin.semantic, clobberLimit);
1278 forNode(node).makeHeapTop();
1279 } else
1280 forNode(node).setType(SpecInt32);
1281 break;
1282 case Array::Double:
1283 if (node->arrayMode().isOutOfBounds()) {
1284 clobberWorld(node->origin.semantic, clobberLimit);
1285 forNode(node).makeHeapTop();
1286 } else if (node->arrayMode().isSaneChain())
1287 forNode(node).setType(SpecBytecodeDouble);
1288 else
1289 forNode(node).setType(SpecDoubleReal);
1290 break;
1291 case Array::Contiguous:
1292 case Array::ArrayStorage:
1293 case Array::SlowPutArrayStorage:
1294 if (node->arrayMode().isOutOfBounds())
1295 clobberWorld(node->origin.semantic, clobberLimit);
1296 forNode(node).makeHeapTop();
1297 break;
1298 case Array::Int8Array:
1299 forNode(node).setType(SpecInt32);
1300 break;
1301 case Array::Int16Array:
1302 forNode(node).setType(SpecInt32);
1303 break;
1304 case Array::Int32Array:
1305 forNode(node).setType(SpecInt32);
1306 break;
1307 case Array::Uint8Array:
1308 forNode(node).setType(SpecInt32);
1309 break;
1310 case Array::Uint8ClampedArray:
1311 forNode(node).setType(SpecInt32);
1312 break;
1313 case Array::Uint16Array:
1314 forNode(node).setType(SpecInt32);
1315 break;
1316 case Array::Uint32Array:
1317 if (node->shouldSpeculateInt32())
1318 forNode(node).setType(SpecInt32);
1319 else if (enableInt52() && node->shouldSpeculateMachineInt())
1320 forNode(node).setType(SpecInt52);
1321 else
1322 forNode(node).setType(SpecInt52AsDouble);
1323 break;
1324 case Array::Float32Array:
1325 forNode(node).setType(SpecFullDouble);
1326 break;
1327 case Array::Float64Array:
1328 forNode(node).setType(SpecFullDouble);
1329 break;
1330 default:
1331 RELEASE_ASSERT_NOT_REACHED();
1332 break;
1333 }
1334 break;
1335 }
1336
1337 case PutByValDirect:
1338 case PutByVal:
1339 case PutByValAlias: {
81345200
A
1340 switch (node->arrayMode().modeForPut().type()) {
1341 case Array::ForceExit:
1342 m_state.setIsValid(false);
1343 break;
1344 case Array::Generic:
1345 clobberWorld(node->origin.semantic, clobberLimit);
1346 break;
1347 case Array::Int32:
1348 if (node->arrayMode().isOutOfBounds())
1349 clobberWorld(node->origin.semantic, clobberLimit);
1350 break;
1351 case Array::Double:
1352 if (node->arrayMode().isOutOfBounds())
1353 clobberWorld(node->origin.semantic, clobberLimit);
1354 break;
1355 case Array::Contiguous:
1356 case Array::ArrayStorage:
1357 if (node->arrayMode().isOutOfBounds())
1358 clobberWorld(node->origin.semantic, clobberLimit);
1359 break;
1360 case Array::SlowPutArrayStorage:
1361 if (node->arrayMode().mayStoreToHole())
1362 clobberWorld(node->origin.semantic, clobberLimit);
1363 break;
1364 default:
1365 break;
1366 }
1367 break;
1368 }
1369
1370 case ArrayPush:
81345200
A
1371 clobberWorld(node->origin.semantic, clobberLimit);
1372 forNode(node).setType(SpecBytecodeNumber);
1373 break;
1374
1375 case ArrayPop:
81345200
A
1376 clobberWorld(node->origin.semantic, clobberLimit);
1377 forNode(node).makeHeapTop();
1378 break;
ed1e77d3
A
1379
1380 case GetMyArgumentByVal: {
1381 JSValue index = forNode(node->child2()).m_value;
1382 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame;
1383
1384 if (index && index.isInt32()) {
1385 // This pretends to return TOP for accesses that are actually proven out-of-bounds because
1386 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
1387 // paths as unreachable, and it's almost certainly not worth the effort.
1388
1389 if (inlineCallFrame) {
1390 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
1391 forNode(node) = m_state.variables().operand(
1392 virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
1393 m_state.setFoundConstants(true);
1394 break;
1395 }
1396 } else {
1397 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
1398 forNode(node) = m_state.variables().argument(index.asInt32() + 1);
1399 m_state.setFoundConstants(true);
1400 break;
1401 }
1402 }
1403 }
1404
1405 if (inlineCallFrame) {
1406 // We have a bound on the types even though it's random access. Take advantage of this.
1407
1408 AbstractValue result;
1409 for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
1410 result.merge(
1411 m_state.variables().operand(
1412 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
1413 }
1414
1415 if (result.value())
1416 m_state.setFoundConstants(true);
1417 forNode(node) = result;
1418 break;
1419 }
1420
1421 forNode(node).makeHeapTop();
1422 break;
1423 }
81345200
A
1424
1425 case RegExpExec:
1426 forNode(node).makeHeapTop();
1427 break;
1428
1429 case RegExpTest:
1430 forNode(node).setType(SpecBoolean);
1431 break;
1432
1433 case Jump:
1434 break;
1435
1436 case Branch: {
1437 Node* child = node->child1().node();
1438 BooleanResult result = booleanResult(node, forNode(child));
1439 if (result == DefinitelyTrue) {
1440 m_state.setBranchDirection(TakeTrue);
1441 break;
1442 }
1443 if (result == DefinitelyFalse) {
1444 m_state.setBranchDirection(TakeFalse);
1445 break;
1446 }
1447 // FIXME: The above handles the trivial cases of sparse conditional
1448 // constant propagation, but we can do better:
1449 // We can specialize the source variable's value on each direction of
1450 // the branch.
81345200
A
1451 m_state.setBranchDirection(TakeBoth);
1452 break;
1453 }
1454
1455 case Switch: {
1456 // Nothing to do for now.
1457 // FIXME: Do sparse conditional things.
1458 break;
1459 }
1460
1461 case Return:
1462 m_state.setIsValid(false);
1463 break;
1464
1465 case Throw:
1466 case ThrowReferenceError:
1467 m_state.setIsValid(false);
81345200
A
1468 break;
1469
1470 case ToPrimitive: {
1471 JSValue childConst = forNode(node->child1()).value();
1472 if (childConst && childConst.isNumber()) {
1473 setConstant(node, childConst);
1474 break;
1475 }
1476
1477 ASSERT(node->child1().useKind() == UntypedUse);
1478
1479 if (!forNode(node->child1()).m_type) {
1480 m_state.setIsValid(false);
1481 break;
1482 }
1483
ed1e77d3 1484 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
81345200
A
1485 m_state.setFoundConstants(true);
1486 forNode(node) = forNode(node->child1());
1487 break;
1488 }
1489
1490 clobberWorld(node->origin.semantic, clobberLimit);
1491
ed1e77d3 1492 forNode(node).setType(m_graph, (SpecHeapTop & ~SpecCell) | SpecString | SpecSymbol);
81345200
A
1493 break;
1494 }
1495
ed1e77d3
A
1496 case ToString:
1497 case CallStringConstructor: {
81345200
A
1498 switch (node->child1().useKind()) {
1499 case StringObjectUse:
1500 // This also filters that the StringObject has the primordial StringObject
1501 // structure.
1502 filter(
1503 node->child1(),
1504 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
81345200
A
1505 break;
1506 case StringOrStringObjectUse:
81345200
A
1507 break;
1508 case CellUse:
1509 case UntypedUse:
1510 clobberWorld(node->origin.semantic, clobberLimit);
1511 break;
1512 default:
1513 RELEASE_ASSERT_NOT_REACHED();
1514 break;
1515 }
1516 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1517 break;
1518 }
1519
1520 case NewStringObject: {
1521 ASSERT(node->structure()->classInfo() == StringObject::info());
1522 forNode(node).set(m_graph, node->structure());
1523 break;
1524 }
1525
1526 case NewArray:
81345200
A
1527 forNode(node).set(
1528 m_graph,
1529 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
81345200
A
1530 break;
1531
1532 case NewArrayBuffer:
81345200
A
1533 forNode(node).set(
1534 m_graph,
1535 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
81345200
A
1536 break;
1537
1538 case NewArrayWithSize:
ed1e77d3 1539 forNode(node).setType(m_graph, SpecArray);
81345200
A
1540 break;
1541
1542 case NewTypedArray:
1543 switch (node->child1().useKind()) {
1544 case Int32Use:
1545 break;
1546 case UntypedUse:
1547 clobberWorld(node->origin.semantic, clobberLimit);
1548 break;
1549 default:
1550 RELEASE_ASSERT_NOT_REACHED();
1551 break;
1552 }
1553 forNode(node).set(
1554 m_graph,
1555 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
1556 node->typedArrayType()));
81345200
A
1557 break;
1558
1559 case NewRegexp:
1560 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
81345200
A
1561 break;
1562
1563 case ToThis: {
1564 AbstractValue& source = forNode(node->child1());
1565 AbstractValue& destination = forNode(node);
1566
1567 if (m_graph.executableFor(node->origin.semantic)->isStrictMode())
1568 destination.makeHeapTop();
1569 else {
1570 destination = source;
1571 destination.merge(SpecObject);
1572 }
1573 break;
1574 }
1575
1576 case CreateThis: {
ed1e77d3
A
1577 // FIXME: We can fold this to NewObject if the incoming callee is a constant.
1578 forNode(node).setType(m_graph, SpecFinalObject);
81345200
A
1579 break;
1580 }
1581
81345200
A
1582 case NewObject:
1583 ASSERT(node->structure());
1584 forNode(node).set(m_graph, node->structure());
81345200
A
1585 break;
1586
ed1e77d3
A
1587 case PhantomNewObject:
1588 case PhantomNewFunction:
1589 case PhantomCreateActivation:
1590 case PhantomDirectArguments:
1591 case PhantomClonedArguments:
1592 case BottomValue:
1593 m_state.setDidClobber(true); // Prevent constant folding.
1594 // This claims to return bottom.
1595 break;
1596
1597 case PutHint:
1598 break;
1599
1600 case MaterializeNewObject: {
1601 StructureSet set;
1602
1603 m_phiChildren->forAllTransitiveIncomingValues(
1604 m_graph.varArgChild(node, 0).node(),
1605 [&] (Node* incoming) {
1606 set.add(incoming->castConstant<Structure*>());
1607 });
1608
1609 forNode(node).set(m_graph, set);
1610 break;
1611 }
1612
81345200 1613 case CreateActivation:
ed1e77d3 1614 case MaterializeCreateActivation:
81345200
A
1615 forNode(node).set(
1616 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
81345200
A
1617 break;
1618
ed1e77d3
A
1619 case CreateDirectArguments:
1620 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
81345200
A
1621 break;
1622
ed1e77d3
A
1623 case CreateScopedArguments:
1624 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
81345200
A
1625 break;
1626
ed1e77d3
A
1627 case CreateClonedArguments:
1628 forNode(node).setType(m_graph, SpecObjectOther);
81345200
A
1629 break;
1630
ed1e77d3
A
1631 case NewFunction:
1632 forNode(node).set(
1633 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
81345200
A
1634 break;
1635
ed1e77d3
A
1636 case GetCallee:
1637 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
1638 InferredValue* singleton = executable->singletonFunction();
1639 if (JSValue value = singleton->inferredValue()) {
1640 m_graph.watchpoints().addLazily(singleton);
1641 JSFunction* function = jsCast<JSFunction*>(value);
1642 setConstant(node, *m_graph.freeze(function));
1643 break;
1644 }
1645 }
1646 forNode(node).setType(m_graph, SpecFunction);
81345200
A
1647 break;
1648
ed1e77d3
A
1649 case GetArgumentCount:
1650 forNode(node).setType(SpecInt32);
1651 break;
81345200 1652
ed1e77d3
A
1653 case GetGetter: {
1654 JSValue base = forNode(node->child1()).m_value;
1655 if (base) {
1656 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
1657 if (!getterSetter->isGetterNull()) {
1658 setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
1659 break;
1660 }
81345200 1661 }
ed1e77d3
A
1662
1663 forNode(node).setType(m_graph, SpecObject);
81345200
A
1664 break;
1665 }
81345200 1666
ed1e77d3
A
1667 case GetSetter: {
1668 JSValue base = forNode(node->child1()).m_value;
1669 if (base) {
1670 GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
1671 if (!getterSetter->isSetterNull()) {
1672 setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
1673 break;
1674 }
1675 }
1676
1677 forNode(node).setType(m_graph, SpecObject);
81345200 1678 break;
ed1e77d3 1679 }
81345200 1680
ed1e77d3
A
1681 case GetScope:
1682 if (JSValue base = forNode(node->child1()).m_value) {
1683 if (JSFunction* function = jsDynamicCast<JSFunction*>(base)) {
1684 setConstant(node, *m_graph.freeze(function->scope()));
1685 break;
1686 }
1687 }
1688 forNode(node).setType(m_graph, SpecObjectOther);
81345200
A
1689 break;
1690
1691 case SkipScope: {
1692 JSValue child = forNode(node->child1()).value();
1693 if (child) {
ed1e77d3 1694 setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
81345200
A
1695 break;
1696 }
ed1e77d3 1697 forNode(node).setType(m_graph, SpecObjectOther);
81345200
A
1698 break;
1699 }
1700
81345200 1701 case GetClosureVar:
ed1e77d3
A
1702 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
1703 setConstant(node, *m_graph.freeze(value));
1704 break;
1705 }
81345200
A
1706 forNode(node).makeHeapTop();
1707 break;
1708
1709 case PutClosureVar:
ed1e77d3
A
1710 break;
1711
1712 case GetFromArguments:
1713 forNode(node).makeHeapTop();
1714 break;
1715
1716 case PutToArguments:
81345200
A
1717 break;
1718
1719 case GetById:
ed1e77d3 1720 case GetByIdFlush: {
81345200
A
1721 if (!node->prediction()) {
1722 m_state.setIsValid(false);
1723 break;
1724 }
ed1e77d3
A
1725
1726 AbstractValue& value = forNode(node->child1());
1727 if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1728 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1729 GetByIdStatus status = GetByIdStatus::computeFor(
1730 value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1731 if (status.isSimple()) {
1732 // Figure out what the result is going to be - is it TOP, a constant, or maybe
1733 // something more subtle?
1734 AbstractValue result;
1735 for (unsigned i = status.numVariants(); i--;) {
1736 DFG_ASSERT(m_graph, node, !status[i].alternateBase());
1737 JSValue constantResult =
1738 m_graph.tryGetConstantProperty(value, status[i].offset());
1739 if (!constantResult) {
1740 result.makeHeapTop();
1741 break;
1742 }
81345200 1743
ed1e77d3
A
1744 AbstractValue thisResult;
1745 thisResult.set(
1746 m_graph, *m_graph.freeze(constantResult),
1747 m_state.structureClobberState());
1748 result.merge(thisResult);
81345200 1749 }
ed1e77d3
A
1750 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1751 m_state.setFoundConstants(true);
1752 forNode(node) = result;
1753 break;
81345200
A
1754 }
1755 }
ed1e77d3 1756
81345200
A
1757 clobberWorld(node->origin.semantic, clobberLimit);
1758 forNode(node).makeHeapTop();
1759 break;
ed1e77d3 1760 }
81345200 1761
ed1e77d3
A
1762 case GetArrayLength: {
1763 JSArrayBufferView* view = m_graph.tryGetFoldableView(
1764 forNode(node->child1()).m_value, node->arrayMode());
1765 if (view) {
1766 setConstant(node, jsNumber(view->length()));
1767 break;
1768 }
81345200
A
1769 forNode(node).setType(SpecInt32);
1770 break;
81345200 1771 }
ed1e77d3 1772
81345200 1773 case CheckStructure: {
81345200
A
1774 AbstractValue& value = forNode(node->child1());
1775 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1776
1777 StructureSet& set = node->structureSet();
ed1e77d3
A
1778
1779 // It's interesting that we could have proven that the object has a larger structure set
1780 // that includes the set we're testing. In that case we could make the structure check
1781 // more efficient. We currently don't.
1782
1783 if (value.m_structure.isSubsetOf(set)) {
81345200 1784 m_state.setFoundConstants(true);
81345200
A
1785 break;
1786 }
1787
1788 filter(value, set);
1789 break;
1790 }
1791
ed1e77d3
A
1792 case CheckStructureImmediate: {
1793 // FIXME: This currently can only reason about one structure at a time.
1794 // https://bugs.webkit.org/show_bug.cgi?id=136988
1795
81345200 1796 AbstractValue& value = forNode(node->child1());
ed1e77d3
A
1797 StructureSet& set = node->structureSet();
1798
1799 if (value.value()) {
1800 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
1801 if (set.contains(structure)) {
1802 m_state.setFoundConstants(true);
1803 break;
1804 }
1805 }
1806 m_state.setIsValid(false);
1807 break;
1808 }
1809
1810 if (m_phiChildren) {
1811 bool allGood = true;
1812 m_phiChildren->forAllTransitiveIncomingValues(
1813 node,
1814 [&] (Node* incoming) {
1815 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
1816 if (set.contains(structure))
1817 return;
1818 }
1819 allGood = false;
1820 });
1821 if (allGood) {
1822 m_state.setFoundConstants(true);
1823 break;
1824 }
1825 }
1826
1827 if (Structure* structure = set.onlyStructure()) {
1828 filterByValue(node->child1(), *m_graph.freeze(structure));
1829 break;
1830 }
1831
1832 // Aw shucks, we can't do anything!
81345200
A
1833 break;
1834 }
ed1e77d3 1835
81345200 1836 case PutStructure:
ed1e77d3
A
1837 if (!forNode(node->child1()).m_structure.isClear()) {
1838 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
1839 m_state.setFoundConstants(true);
1840 else {
1841 observeTransition(
1842 clobberLimit, node->transition()->previous, node->transition()->next);
1843 forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
1844 }
81345200
A
1845 }
1846 break;
1847 case GetButterfly:
1848 case AllocatePropertyStorage:
1849 case ReallocatePropertyStorage:
1850 forNode(node).clear(); // The result is not a JS value.
1851 break;
1852 case CheckArray: {
1853 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1854 m_state.setFoundConstants(true);
1855 break;
1856 }
81345200
A
1857 switch (node->arrayMode().type()) {
1858 case Array::String:
1859 filter(node->child1(), SpecString);
1860 break;
1861 case Array::Int32:
1862 case Array::Double:
1863 case Array::Contiguous:
1864 case Array::ArrayStorage:
1865 case Array::SlowPutArrayStorage:
1866 break;
ed1e77d3
A
1867 case Array::DirectArguments:
1868 filter(node->child1(), SpecDirectArguments);
1869 break;
1870 case Array::ScopedArguments:
1871 filter(node->child1(), SpecScopedArguments);
81345200
A
1872 break;
1873 case Array::Int8Array:
1874 filter(node->child1(), SpecInt8Array);
1875 break;
1876 case Array::Int16Array:
1877 filter(node->child1(), SpecInt16Array);
1878 break;
1879 case Array::Int32Array:
1880 filter(node->child1(), SpecInt32Array);
1881 break;
1882 case Array::Uint8Array:
1883 filter(node->child1(), SpecUint8Array);
1884 break;
1885 case Array::Uint8ClampedArray:
1886 filter(node->child1(), SpecUint8ClampedArray);
1887 break;
1888 case Array::Uint16Array:
1889 filter(node->child1(), SpecUint16Array);
1890 break;
1891 case Array::Uint32Array:
1892 filter(node->child1(), SpecUint32Array);
1893 break;
1894 case Array::Float32Array:
1895 filter(node->child1(), SpecFloat32Array);
1896 break;
1897 case Array::Float64Array:
1898 filter(node->child1(), SpecFloat64Array);
1899 break;
1900 default:
1901 RELEASE_ASSERT_NOT_REACHED();
1902 break;
1903 }
1904 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
81345200
A
1905 break;
1906 }
1907 case Arrayify: {
1908 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1909 m_state.setFoundConstants(true);
1910 break;
1911 }
ed1e77d3 1912 ASSERT(node->arrayMode().conversion() == Array::Convert);
81345200
A
1913 clobberStructures(clobberLimit);
1914 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
81345200
A
1915 break;
1916 }
1917 case ArrayifyToStructure: {
1918 AbstractValue& value = forNode(node->child1());
ed1e77d3 1919 if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
81345200 1920 m_state.setFoundConstants(true);
81345200 1921 clobberStructures(clobberLimit);
ed1e77d3
A
1922
1923 // We have a bunch of options of how to express the abstract set at this point. Let set S
1924 // be the set of structures that the value had before clobbering and assume that all of
1925 // them are watchable. The new value should be the least expressible upper bound of the
1926 // intersection of "values that currently have structure = node->structure()" and "values
1927 // that have structure in S plus any structure transition-reachable from S". Assume that
1928 // node->structure() is not in S but it is transition-reachable from S. Then we would
1929 // like to say that the result is "values that have structure = node->structure() until
1930 // we invalidate", but there is no way to express this using the AbstractValue syntax. So
1931 // we must choose between:
1932 //
1933 // 1) "values that currently have structure = node->structure()". This is a valid
1934 // superset of the value that we really want, and it's specific enough to satisfy the
1935 // preconditions of the array access that this is guarding. It's also specific enough
1936 // to allow relevant optimizations in the case that we didn't have a contradiction
1937 // like in this example. Notice that in the abscence of any contradiction, this result
1938 // is precise rather than being a conservative LUB.
1939 //
1940 // 2) "values that currently hava structure in S plus any structure transition-reachable
1941 // from S". This is also a valid superset of the value that we really want, but it's
1942 // not specific enough to satisfy the preconditions of the array access that this is
1943 // guarding - so playing such shenanigans would preclude us from having assertions on
1944 // the typing preconditions of any array accesses. This would also not be a desirable
1945 // answer in the absence of a contradiction.
1946 //
1947 // Note that it's tempting to simply say that the resulting value is BOTTOM because of
1948 // the contradiction. That would be wrong, since we haven't hit an invalidation point,
1949 // yet.
1950 value.set(m_graph, node->structure());
1951 break;
1952 }
1953 case GetIndexedPropertyStorage: {
1954 JSArrayBufferView* view = m_graph.tryGetFoldableView(
1955 forNode(node->child1()).m_value, node->arrayMode());
1956 if (view)
1957 m_state.setFoundConstants(true);
1958 forNode(node).clear();
81345200
A
1959 break;
1960 }
81345200
A
1961 case ConstantStoragePointer: {
1962 forNode(node).clear();
1963 break;
1964 }
1965
1966 case GetTypedArrayByteOffset: {
ed1e77d3
A
1967 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
1968 if (view) {
1969 setConstant(node, jsNumber(view->byteOffset()));
1970 break;
1971 }
81345200
A
1972 forNode(node).setType(SpecInt32);
1973 break;
1974 }
1975
1976 case GetByOffset: {
ed1e77d3
A
1977 StorageAccessData& data = node->storageAccessData();
1978 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
1979 if (result) {
1980 setConstant(node, *m_graph.freeze(result));
1981 break;
1982 }
1983
81345200
A
1984 forNode(node).makeHeapTop();
1985 break;
1986 }
1987
ed1e77d3
A
1988 case GetGetterSetterByOffset: {
1989 StorageAccessData& data = node->storageAccessData();
1990 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
1991 if (result && jsDynamicCast<GetterSetter*>(result)) {
1992 setConstant(node, *m_graph.freeze(result));
1993 break;
1994 }
1995
1996 forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
1997 break;
1998 }
1999
81345200 2000 case MultiGetByOffset: {
ed1e77d3
A
2001 // This code will filter the base value in a manner that is possibly different (either more
2002 // or less precise) than the way it would be filtered if this was strength-reduced to a
2003 // CheckStructure. This is fine. It's legal for different passes over the code to prove
2004 // different things about the code, so long as all of them are sound. That even includes
2005 // one guy proving that code should never execute (due to a contradiction) and another guy
2006 // not finding that contradiction. If someone ever proved that there would be a
2007 // contradiction then there must always be a contradiction even if subsequent passes don't
2008 // realize it. This is the case here.
2009
2010 // Ordinarily you have to be careful with calling setFoundConstants()
2011 // because of the effect on compile times, but this node is FTL-only.
2012 m_state.setFoundConstants(true);
2013
2014 AbstractValue base = forNode(node->child1());
2015 StructureSet baseSet;
2016 AbstractValue result;
2017 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
2018 GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
2019 StructureSet set = variant.structureSet();
2020 set.filter(base);
2021 if (set.isEmpty())
2022 continue;
2023 baseSet.merge(set);
2024
2025 JSValue baseForLoad;
2026 if (variant.alternateBase())
2027 baseForLoad = variant.alternateBase();
2028 else
2029 baseForLoad = base.m_value;
2030 JSValue constantResult =
2031 m_graph.tryGetConstantProperty(
2032 baseForLoad, variant.baseStructure(), variant.offset());
2033 if (!constantResult) {
2034 result.makeHeapTop();
2035 continue;
81345200 2036 }
ed1e77d3
A
2037 AbstractValue thisResult;
2038 thisResult.set(
2039 m_graph,
2040 *m_graph.freeze(constantResult),
2041 m_state.structureClobberState());
2042 result.merge(thisResult);
81345200
A
2043 }
2044
ed1e77d3
A
2045 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2046 m_state.setIsValid(false);
81345200 2047
ed1e77d3 2048 forNode(node) = result;
81345200
A
2049 break;
2050 }
2051
2052 case PutByOffset: {
2053 break;
2054 }
2055
2056 case MultiPutByOffset: {
ed1e77d3
A
2057 StructureSet newSet;
2058 TransitionVector transitions;
81345200 2059
ed1e77d3
A
2060 // Ordinarily you have to be careful with calling setFoundConstants()
2061 // because of the effect on compile times, but this node is FTL-only.
2062 m_state.setFoundConstants(true);
2063
2064 AbstractValue base = forNode(node->child1());
81345200 2065
81345200
A
2066 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2067 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
ed1e77d3
A
2068 StructureSet thisSet = variant.oldStructure();
2069 thisSet.filter(base);
2070 if (thisSet.isEmpty())
81345200 2071 continue;
ed1e77d3
A
2072 if (variant.kind() == PutByIdVariant::Transition) {
2073 if (thisSet.onlyStructure() != variant.newStructure()) {
2074 transitions.append(
2075 Transition(variant.oldStructureForTransition(), variant.newStructure()));
2076 } // else this is really a replace.
2077 newSet.add(variant.newStructure());
2078 } else {
2079 ASSERT(variant.kind() == PutByIdVariant::Replace);
2080 newSet.merge(thisSet);
81345200 2081 }
81345200
A
2082 }
2083
ed1e77d3
A
2084 observeTransitions(clobberLimit, transitions);
2085 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2086 m_state.setIsValid(false);
2087 break;
2088 }
2089
2090 case GetExecutable: {
2091 JSValue value = forNode(node->child1()).value();
2092 if (value) {
2093 JSFunction* function = jsDynamicCast<JSFunction*>(value);
2094 if (function) {
2095 setConstant(node, *m_graph.freeze(function->executable()));
2096 break;
2097 }
2098 }
2099 forNode(node).setType(m_graph, SpecCellOther);
81345200
A
2100 break;
2101 }
2102
ed1e77d3 2103 case CheckCell: {
81345200 2104 JSValue value = forNode(node->child1()).value();
ed1e77d3 2105 if (value == node->cellOperand()->value()) {
81345200
A
2106 m_state.setFoundConstants(true);
2107 ASSERT(value);
2108 break;
2109 }
ed1e77d3 2110 filterByValue(node->child1(), *node->cellOperand());
81345200
A
2111 break;
2112 }
ed1e77d3
A
2113
2114 case CheckNotEmpty: {
2115 AbstractValue& value = forNode(node->child1());
2116 if (!(value.m_type & SpecEmpty)) {
2117 m_state.setFoundConstants(true);
2118 break;
2119 }
81345200 2120
ed1e77d3
A
2121 filter(value, ~SpecEmpty);
2122 break;
2123 }
2124
81345200
A
2125 case CheckInBounds: {
2126 JSValue left = forNode(node->child1()).value();
2127 JSValue right = forNode(node->child2()).value();
2128 if (left && right && left.isInt32() && right.isInt32()
2129 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
2130 m_state.setFoundConstants(true);
2131 break;
2132 }
81345200
A
2133 break;
2134 }
2135
2136 case PutById:
2137 case PutByIdFlush:
ed1e77d3
A
2138 case PutByIdDirect: {
2139 AbstractValue& value = forNode(node->child1());
2140 if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
81345200 2141 PutByIdStatus status = PutByIdStatus::computeFor(
81345200 2142 m_graph.globalObjectFor(node->origin.semantic),
ed1e77d3 2143 value.m_structure.set(),
81345200
A
2144 m_graph.identifiers()[node->identifierNumber()],
2145 node->op() == PutByIdDirect);
ed1e77d3
A
2146
2147 if (status.isSimple()) {
2148 StructureSet newSet;
2149 TransitionVector transitions;
2150
2151 for (unsigned i = status.numVariants(); i--;) {
2152 const PutByIdVariant& variant = status[i];
2153 if (variant.kind() == PutByIdVariant::Transition) {
2154 transitions.append(
2155 Transition(
2156 variant.oldStructureForTransition(), variant.newStructure()));
2157 m_graph.registerStructure(variant.newStructure());
2158 newSet.add(variant.newStructure());
2159 } else {
2160 ASSERT(variant.kind() == PutByIdVariant::Replace);
2161 newSet.merge(variant.oldStructure());
2162 }
81345200 2163 }
ed1e77d3
A
2164
2165 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
81345200 2166 m_state.setFoundConstants(true);
ed1e77d3
A
2167
2168 observeTransitions(clobberLimit, transitions);
2169 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2170 m_state.setIsValid(false);
2171 break;
81345200
A
2172 }
2173 }
ed1e77d3 2174
81345200
A
2175 clobberWorld(node->origin.semantic, clobberLimit);
2176 break;
ed1e77d3 2177 }
81345200 2178
ed1e77d3 2179 case In: {
81345200
A
2180 // FIXME: We can determine when the property definitely exists based on abstract
2181 // value information.
2182 clobberWorld(node->origin.semantic, clobberLimit);
2183 forNode(node).setType(SpecBoolean);
2184 break;
ed1e77d3 2185 }
81345200 2186
ed1e77d3
A
2187 case GetEnumerableLength: {
2188 forNode(node).setType(SpecInt32);
2189 break;
2190 }
2191 case HasGenericProperty: {
2192 forNode(node).setType(SpecBoolean);
2193 break;
2194 }
2195 case HasStructureProperty: {
2196 forNode(node).setType(SpecBoolean);
2197 break;
2198 }
2199 case HasIndexedProperty: {
2200 ArrayMode mode = node->arrayMode();
2201 switch (mode.type()) {
2202 case Array::Int32:
2203 case Array::Double:
2204 case Array::Contiguous:
2205 case Array::ArrayStorage: {
2206 break;
2207 }
2208 default: {
2209 clobberWorld(node->origin.semantic, clobberLimit);
2210 break;
2211 }
2212 }
2213 forNode(node).setType(SpecBoolean);
2214 break;
2215 }
2216 case GetDirectPname: {
2217 clobberWorld(node->origin.semantic, clobberLimit);
2218 forNode(node).makeHeapTop();
2219 break;
2220 }
2221 case GetPropertyEnumerator: {
2222 forNode(node).setType(m_graph, SpecCell);
2223 break;
2224 }
2225 case GetEnumeratorStructurePname: {
2226 forNode(node).setType(m_graph, SpecString | SpecOther);
2227 break;
2228 }
2229 case GetEnumeratorGenericPname: {
2230 forNode(node).setType(m_graph, SpecString | SpecOther);
2231 break;
2232 }
2233 case ToIndexString: {
2234 forNode(node).setType(m_graph, SpecString);
2235 break;
2236 }
2237
81345200
A
2238 case GetGlobalVar:
2239 forNode(node).makeHeapTop();
2240 break;
2241
81345200 2242 case VarInjectionWatchpoint:
81345200
A
2243 case PutGlobalVar:
2244 case NotifyWrite:
2245 break;
2246
2247 case CheckHasInstance:
81345200
A
2248 // Sadly, we don't propagate the fact that we've done CheckHasInstance
2249 break;
2250
2251 case InstanceOf:
81345200
A
2252 // Again, sadly, we don't propagate the fact that we've done InstanceOf
2253 forNode(node).setType(SpecBoolean);
2254 break;
2255
2256 case Phi:
2257 RELEASE_ASSERT(m_graph.m_form == SSA);
ed1e77d3
A
2258 // The state of this node would have already been decided, but it may have become a
2259 // constant, in which case we'd like to know.
2260 if (forNode(node).m_value)
2261 m_state.setFoundConstants(true);
81345200
A
2262 break;
2263
2264 case Upsilon: {
2265 m_state.createValueForNode(node->phi());
ed1e77d3 2266 forNode(node->phi()) = forNode(node->child1());
81345200
A
2267 break;
2268 }
2269
2270 case Flush:
2271 case PhantomLocal:
2272 break;
2273
2274 case Call:
2275 case Construct:
ed1e77d3
A
2276 case NativeCall:
2277 case NativeConstruct:
2278 case CallVarargs:
2279 case CallForwardVarargs:
2280 case ConstructVarargs:
2281 case ConstructForwardVarargs:
81345200
A
2282 clobberWorld(node->origin.semantic, clobberLimit);
2283 forNode(node).makeHeapTop();
2284 break;
2285
2286 case ForceOSRExit:
ed1e77d3 2287 case CheckBadCell:
81345200
A
2288 m_state.setIsValid(false);
2289 break;
2290
2291 case InvalidationPoint:
ed1e77d3
A
2292 forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
2293 m_state.setStructureClobberState(StructuresAreWatched);
81345200
A
2294 break;
2295
2296 case CheckWatchdogTimer:
81345200
A
2297 break;
2298
2299 case Breakpoint:
2300 case ProfileWillCall:
2301 case ProfileDidCall:
ed1e77d3
A
2302 case ProfileType:
2303 case ProfileControlFlow:
81345200 2304 case Phantom:
81345200
A
2305 case CountExecution:
2306 case CheckTierUpInLoop:
2307 case CheckTierUpAtReturn:
2308 break;
2309
ed1e77d3
A
2310 case Check: {
2311 // Simplify out checks that don't actually do checking.
2312 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
2313 Edge edge = node->children.child(i);
2314 if (!edge)
2315 break;
2316 if (edge.isProved() || edge.willNotHaveCheck()) {
2317 m_state.setFoundConstants(true);
2318 break;
2319 }
2320 }
81345200
A
2321 break;
2322 }
2323
ed1e77d3
A
2324 case StoreBarrier: {
2325 filter(node->child1(), SpecCell);
81345200
A
2326 break;
2327 }
2328
2329 case CheckTierUpAndOSREnter:
ed1e77d3 2330 case CheckTierUpWithNestedTriggerAndOSREnter:
81345200 2331 case LoopHint:
ed1e77d3 2332 case ZombieHint:
81345200
A
2333 break;
2334
81345200
A
2335 case Unreachable:
2336 case LastNodeType:
2337 case ArithIMul:
2338 case FiatInt52:
ed1e77d3 2339 DFG_CRASH(m_graph, node, "Unexpected node type");
81345200
A
2340 break;
2341 }
2342
2343 return m_state.isValid();
2344}
2345
2346template<typename AbstractStateType>
2347bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
2348{
2349 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
2350}
2351
2352template<typename AbstractStateType>
2353bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
2354{
2355 Node* node = m_state.block()->at(indexInBlock);
81345200 2356
ed1e77d3 2357 startExecuting();
81345200
A
2358 executeEdges(node);
2359 return executeEffects(indexInBlock, node);
2360}
2361
2362template<typename AbstractStateType>
2363bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
2364{
ed1e77d3 2365 startExecuting();
81345200
A
2366 executeEdges(node);
2367 return executeEffects(UINT_MAX, node);
2368}
2369
2370template<typename AbstractStateType>
2371void AbstractInterpreter<AbstractStateType>::clobberWorld(
ed1e77d3 2372 const CodeOrigin&, unsigned clobberLimit)
81345200 2373{
81345200
A
2374 clobberStructures(clobberLimit);
2375}
2376
2377template<typename AbstractStateType>
ed1e77d3
A
2378template<typename Functor>
2379void AbstractInterpreter<AbstractStateType>::forAllValues(
2380 unsigned clobberLimit, Functor& functor)
81345200 2381{
ed1e77d3 2382 SamplingRegion samplingRegion("DFG AI For All Values");
81345200
A
2383 if (clobberLimit >= m_state.block()->size())
2384 clobberLimit = m_state.block()->size();
2385 else
2386 clobberLimit++;
2387 ASSERT(clobberLimit <= m_state.block()->size());
2388 for (size_t i = clobberLimit; i--;)
ed1e77d3 2389 functor(forNode(m_state.block()->at(i)));
81345200
A
2390 if (m_graph.m_form == SSA) {
2391 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2392 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2393 for (; iter != end; ++iter)
ed1e77d3 2394 functor(forNode(*iter));
81345200
A
2395 }
2396 for (size_t i = m_state.variables().numberOfArguments(); i--;)
ed1e77d3 2397 functor(m_state.variables().argument(i));
81345200 2398 for (size_t i = m_state.variables().numberOfLocals(); i--;)
ed1e77d3
A
2399 functor(m_state.variables().local(i));
2400}
2401
2402template<typename AbstractStateType>
2403void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
2404{
2405 SamplingRegion samplingRegion("DFG AI Clobber Structures");
2406 forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
2407 setDidClobber();
2408}
2409
2410template<typename AbstractStateType>
2411void AbstractInterpreter<AbstractStateType>::observeTransition(
2412 unsigned clobberLimit, Structure* from, Structure* to)
2413{
2414 AbstractValue::TransitionObserver transitionObserver(from, to);
2415 forAllValues(clobberLimit, transitionObserver);
2416
2417 ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
2418}
2419
2420template<typename AbstractStateType>
2421void AbstractInterpreter<AbstractStateType>::observeTransitions(
2422 unsigned clobberLimit, const TransitionVector& vector)
2423{
2424 AbstractValue::TransitionsObserver transitionsObserver(vector);
2425 forAllValues(clobberLimit, transitionsObserver);
2426
2427 if (!ASSERT_DISABLED) {
2428 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
2429 for (unsigned i = vector.size(); i--;)
2430 ASSERT(!vector[i].previous->dfgShouldWatch());
2431 }
2432}
2433
2434template<typename AbstractStateType>
2435void AbstractInterpreter<AbstractStateType>::setDidClobber()
2436{
81345200 2437 m_state.setDidClobber(true);
ed1e77d3
A
2438 m_state.setStructureClobberState(StructuresAreClobbered);
2439}
2440
2441template<typename AbstractStateType>
2442void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
2443{
2444 const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
81345200
A
2445}
2446
2447template<typename AbstractStateType>
2448void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
2449{
2450 CommaPrinter comma(" ");
ed1e77d3 2451 HashSet<Node*> seen;
81345200
A
2452 if (m_graph.m_form == SSA) {
2453 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2454 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2455 for (; iter != end; ++iter) {
2456 Node* node = *iter;
ed1e77d3 2457 seen.add(node);
81345200
A
2458 AbstractValue& value = forNode(node);
2459 if (value.isClear())
2460 continue;
2461 out.print(comma, node, ":", value);
2462 }
2463 }
2464 for (size_t i = 0; i < m_state.block()->size(); ++i) {
2465 Node* node = m_state.block()->at(i);
ed1e77d3 2466 seen.add(node);
81345200
A
2467 AbstractValue& value = forNode(node);
2468 if (value.isClear())
2469 continue;
2470 out.print(comma, node, ":", value);
2471 }
ed1e77d3
A
2472 if (m_graph.m_form == SSA) {
2473 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtTail.begin();
2474 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtTail.end();
2475 for (; iter != end; ++iter) {
2476 Node* node = *iter;
2477 if (seen.contains(node))
2478 continue;
2479 AbstractValue& value = forNode(node);
2480 if (value.isClear())
2481 continue;
2482 out.print(comma, node, ":", value);
2483 }
2484 }
81345200
A
2485}
2486
2487template<typename AbstractStateType>
2488FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2489 AbstractValue& value, const StructureSet& set)
2490{
2491 if (value.filter(m_graph, set) == FiltrationOK)
2492 return FiltrationOK;
2493 m_state.setIsValid(false);
2494 return Contradiction;
2495}
2496
2497template<typename AbstractStateType>
2498FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
2499 AbstractValue& value, ArrayModes arrayModes)
2500{
2501 if (value.filterArrayModes(arrayModes) == FiltrationOK)
2502 return FiltrationOK;
2503 m_state.setIsValid(false);
2504 return Contradiction;
2505}
2506
2507template<typename AbstractStateType>
2508FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2509 AbstractValue& value, SpeculatedType type)
2510{
2511 if (value.filter(type) == FiltrationOK)
2512 return FiltrationOK;
2513 m_state.setIsValid(false);
2514 return Contradiction;
2515}
2516
2517template<typename AbstractStateType>
2518FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
ed1e77d3 2519 AbstractValue& abstractValue, FrozenValue concreteValue)
81345200
A
2520{
2521 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
2522 return FiltrationOK;
2523 m_state.setIsValid(false);
2524 return Contradiction;
2525}
2526
2527} } // namespace JSC::DFG
2528
2529#endif // ENABLE(DFG_JIT)
2530
2531#endif // DFGAbstractInterpreterInlines_h
2532