]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGAbstractInterpreterInlines.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGAbstractInterpreterInlines.h
CommitLineData
81345200
A
1/*
2 * Copyright (C) 2013, 2014 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#ifndef DFGAbstractInterpreterInlines_h
27#define DFGAbstractInterpreterInlines_h
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGAbstractInterpreter.h"
32#include "GetByIdStatus.h"
33#include "Operations.h"
34#include "PutByIdStatus.h"
35#include "StringObject.h"
36
37namespace JSC { namespace DFG {
38
39template<typename AbstractStateType>
40AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
41 : m_codeBlock(graph.m_codeBlock)
42 , m_graph(graph)
43 , m_state(state)
44{
45}
46
47template<typename AbstractStateType>
48AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
49{
50}
51
52template<typename AbstractStateType>
53typename AbstractInterpreter<AbstractStateType>::BooleanResult
54AbstractInterpreter<AbstractStateType>::booleanResult(
55 Node* node, AbstractValue& value)
56{
57 JSValue childConst = value.value();
58 if (childConst) {
59 if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)->globalExec()))
60 return DefinitelyTrue;
61 return DefinitelyFalse;
62 }
63
64 // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
65 if (isCellSpeculation(value.m_type)
66 && value.m_currentKnownStructure.hasSingleton()) {
67 Structure* structure = value.m_currentKnownStructure.singleton();
68 if (!structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
69 && structure->typeInfo().type() != StringType)
70 return DefinitelyTrue;
71 }
72
73 return UnknownBooleanResult;
74}
75
76template<typename AbstractStateType>
77bool AbstractInterpreter<AbstractStateType>::startExecuting(Node* node)
78{
79 ASSERT(m_state.block());
80 ASSERT(m_state.isValid());
81
82 m_state.setDidClobber(false);
83
84 node->setCanExit(false);
85
86 return node->shouldGenerate();
87}
88
89template<typename AbstractStateType>
90bool AbstractInterpreter<AbstractStateType>::startExecuting(unsigned indexInBlock)
91{
92 return startExecuting(m_state.block()->at(indexInBlock));
93}
94
95template<typename AbstractStateType>
96void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
97{
98 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse);
99}
100
101template<typename AbstractStateType>
102void AbstractInterpreter<AbstractStateType>::executeEdges(unsigned indexInBlock)
103{
104 executeEdges(m_state.block()->at(indexInBlock));
105}
106
107template<typename AbstractStateType>
108void AbstractInterpreter<AbstractStateType>::verifyEdge(Node*, Edge edge)
109{
110 RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
111}
112
113template<typename AbstractStateType>
114void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
115{
116 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
117}
118
119template<typename AbstractStateType>
120bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
121{
122 if (!ASSERT_DISABLED)
123 verifyEdges(node);
124
125 m_state.createValueForNode(node);
126
127 switch (node->op()) {
128 case JSConstant:
129 case DoubleConstant:
130 case Int52Constant:
131 case WeakJSConstant:
132 case PhantomArguments: {
133 setBuiltInConstant(node, m_graph.valueOfJSConstant(node));
134 break;
135 }
136
137 case Identity: {
138 forNode(node) = forNode(node->child1());
139 break;
140 }
141
142 case GetArgument: {
143 ASSERT(m_graph.m_form == SSA);
144 VariableAccessData* variable = node->variableAccessData();
145 AbstractValue& value = m_state.variables().operand(variable->local().offset());
146 ASSERT(value.isHeapTop());
147 FiltrationResult result =
148 value.filter(typeFilterFor(useKindFor(variable->flushFormat())));
149 ASSERT_UNUSED(result, result == FiltrationOK);
150 forNode(node) = value;
151 break;
152 }
153
154 case ExtractOSREntryLocal: {
155 if (!(node->unlinkedLocal().isArgument())
156 && m_graph.m_lazyVars.get(node->unlinkedLocal().toLocal())) {
157 // This is kind of pessimistic - we could know in some cases that the
158 // DFG code at the point of the OSR had already initialized the lazy
159 // variable. But maybe this is fine, since we're inserting OSR
160 // entrypoints very early in the pipeline - so any lazy initializations
161 // ought to be hoisted out anyway.
162 forNode(node).makeBytecodeTop();
163 } else
164 forNode(node).makeHeapTop();
165 break;
166 }
167
168 case GetLocal: {
169 VariableAccessData* variableAccessData = node->variableAccessData();
170 AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
171 if (!variableAccessData->isCaptured()) {
172 if (value.isClear())
173 node->setCanExit(true);
174 }
175 if (value.value())
176 m_state.setFoundConstants(true);
177 forNode(node) = value;
178 break;
179 }
180
181 case GetLocalUnlinked: {
182 AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
183 if (value.value())
184 m_state.setFoundConstants(true);
185 forNode(node) = value;
186 break;
187 }
188
189 case SetLocal: {
190 m_state.variables().operand(node->local().offset()) = forNode(node->child1());
191 break;
192 }
193
194 case MovHint: {
195 // Don't need to do anything. A MovHint only informs us about what would have happened
196 // in bytecode, but this code is just concerned with what is actually happening during
197 // DFG execution.
198 break;
199 }
200
201 case SetArgument:
202 // Assert that the state of arguments has been set.
203 ASSERT(!m_state.block()->valuesAtHead.operand(node->local()).isClear());
204 break;
205
206 case BitAnd:
207 case BitOr:
208 case BitXor:
209 case BitRShift:
210 case BitLShift:
211 case BitURShift: {
212 JSValue left = forNode(node->child1()).value();
213 JSValue right = forNode(node->child2()).value();
214 if (left && right && left.isInt32() && right.isInt32()) {
215 int32_t a = left.asInt32();
216 int32_t b = right.asInt32();
217 switch (node->op()) {
218 case BitAnd:
219 setConstant(node, JSValue(a & b));
220 break;
221 case BitOr:
222 setConstant(node, JSValue(a | b));
223 break;
224 case BitXor:
225 setConstant(node, JSValue(a ^ b));
226 break;
227 case BitRShift:
228 setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
229 break;
230 case BitLShift:
231 setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
232 break;
233 case BitURShift:
234 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
235 break;
236 default:
237 RELEASE_ASSERT_NOT_REACHED();
238 break;
239 }
240 break;
241 }
242 forNode(node).setType(SpecInt32);
243 break;
244 }
245
246 case UInt32ToNumber: {
247 JSValue child = forNode(node->child1()).value();
248 if (doesOverflow(node->arithMode())) {
249 if (child && child.isInt32()) {
250 uint32_t value = child.asInt32();
251 setConstant(node, jsNumber(value));
252 break;
253 }
254 forNode(node).setType(SpecInt52AsDouble);
255 break;
256 }
257 if (child && child.isInt32()) {
258 int32_t value = child.asInt32();
259 if (value >= 0) {
260 setConstant(node, jsNumber(value));
261 break;
262 }
263 }
264 forNode(node).setType(SpecInt32);
265 node->setCanExit(true);
266 break;
267 }
268
269 case BooleanToNumber: {
270 JSValue concreteValue = forNode(node->child1()).value();
271 if (concreteValue) {
272 if (concreteValue.isBoolean())
273 setConstant(node, jsNumber(concreteValue.asBoolean()));
274 else
275 setConstant(node, concreteValue);
276 break;
277 }
278 AbstractValue& value = forNode(node);
279 value = forNode(node->child1());
280 if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
281 m_state.setFoundConstants(true);
282 if (value.m_type & SpecBoolean) {
283 value.merge(SpecInt32);
284 value.filter(~SpecBoolean);
285 }
286 break;
287 }
288
289 case DoubleAsInt32: {
290 JSValue child = forNode(node->child1()).value();
291 if (child && child.isNumber()) {
292 double asDouble = child.asNumber();
293 int32_t asInt = JSC::toInt32(asDouble);
294 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
295 setConstant(node, JSValue(asInt));
296 break;
297 }
298 }
299 node->setCanExit(true);
300 forNode(node).setType(SpecInt32);
301 break;
302 }
303
304 case ValueToInt32: {
305 JSValue child = forNode(node->child1()).value();
306 if (child) {
307 if (child.isNumber()) {
308 if (child.isInt32())
309 setConstant(node, child);
310 else
311 setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
312 break;
313 }
314 if (child.isBoolean()) {
315 setConstant(node, jsNumber(child.asBoolean()));
316 break;
317 }
318 if (child.isUndefinedOrNull()) {
319 setConstant(node, jsNumber(0));
320 break;
321 }
322 }
323
324 forNode(node).setType(SpecInt32);
325 break;
326 }
327
328 case DoubleRep: {
329 JSValue child = forNode(node->child1()).value();
330 if (child && child.isNumber()) {
331 setConstant(node, jsDoubleNumber(child.asNumber()));
332 break;
333 }
334 forNode(node).setType(forNode(node->child1()).m_type);
335 forNode(node).fixTypeForRepresentation(node);
336 break;
337 }
338
339 case Int52Rep: {
340 JSValue child = forNode(node->child1()).value();
341 if (child && child.isMachineInt()) {
342 setConstant(node, child);
343 break;
344 }
345
346 forNode(node).setType(SpecInt32);
347 break;
348 }
349
350 case ValueRep: {
351 JSValue value = forNode(node->child1()).value();
352 if (value) {
353 setConstant(node, value);
354 break;
355 }
356
357 forNode(node).setType(forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
358 forNode(node).fixTypeForRepresentation(node);
359 break;
360 }
361
362 case ValueAdd: {
363 ASSERT(node->binaryUseKind() == UntypedUse);
364 clobberWorld(node->origin.semantic, clobberLimit);
365 forNode(node).setType(SpecString | SpecBytecodeNumber);
366 break;
367 }
368
369 case ArithAdd: {
370 JSValue left = forNode(node->child1()).value();
371 JSValue right = forNode(node->child2()).value();
372 switch (node->binaryUseKind()) {
373 case Int32Use:
374 if (left && right && left.isInt32() && right.isInt32()) {
375 if (!shouldCheckOverflow(node->arithMode())) {
376 setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
377 break;
378 }
379 JSValue result = jsNumber(left.asNumber() + right.asNumber());
380 if (result.isInt32()) {
381 setConstant(node, result);
382 break;
383 }
384 }
385 forNode(node).setType(SpecInt32);
386 if (shouldCheckOverflow(node->arithMode()))
387 node->setCanExit(true);
388 break;
389 case Int52RepUse:
390 if (left && right && left.isMachineInt() && right.isMachineInt()) {
391 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt());
392 if (result.isMachineInt()) {
393 setConstant(node, result);
394 break;
395 }
396 }
397 forNode(node).setType(SpecMachineInt);
398 if (!forNode(node->child1()).isType(SpecInt32)
399 || !forNode(node->child2()).isType(SpecInt32))
400 node->setCanExit(true);
401 break;
402 case DoubleRepUse:
403 if (left && right && left.isNumber() && right.isNumber()) {
404 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
405 break;
406 }
407 forNode(node).setType(
408 typeOfDoubleSum(
409 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
410 break;
411 default:
412 RELEASE_ASSERT_NOT_REACHED();
413 break;
414 }
415 break;
416 }
417
418 case MakeRope: {
419 node->setCanExit(true);
420 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
421 break;
422 }
423
424 case ArithSub: {
425 JSValue left = forNode(node->child1()).value();
426 JSValue right = forNode(node->child2()).value();
427 switch (node->binaryUseKind()) {
428 case Int32Use:
429 if (left && right && left.isInt32() && right.isInt32()) {
430 if (!shouldCheckOverflow(node->arithMode())) {
431 setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
432 break;
433 }
434 JSValue result = jsNumber(left.asNumber() - right.asNumber());
435 if (result.isInt32()) {
436 setConstant(node, result);
437 break;
438 }
439 }
440 forNode(node).setType(SpecInt32);
441 if (shouldCheckOverflow(node->arithMode()))
442 node->setCanExit(true);
443 break;
444 case Int52RepUse:
445 if (left && right && left.isMachineInt() && right.isMachineInt()) {
446 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt());
447 if (result.isMachineInt() || !shouldCheckOverflow(node->arithMode())) {
448 setConstant(node, result);
449 break;
450 }
451 }
452 forNode(node).setType(SpecMachineInt);
453 if (!forNode(node->child1()).isType(SpecInt32)
454 || !forNode(node->child2()).isType(SpecInt32))
455 node->setCanExit(true);
456 break;
457 case DoubleRepUse:
458 if (left && right && left.isNumber() && right.isNumber()) {
459 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
460 break;
461 }
462 forNode(node).setType(
463 typeOfDoubleDifference(
464 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
465 break;
466 default:
467 RELEASE_ASSERT_NOT_REACHED();
468 break;
469 }
470 break;
471 }
472
473 case ArithNegate: {
474 JSValue child = forNode(node->child1()).value();
475 switch (node->child1().useKind()) {
476 case Int32Use:
477 if (child && child.isInt32()) {
478 if (!shouldCheckOverflow(node->arithMode())) {
479 setConstant(node, jsNumber(-child.asInt32()));
480 break;
481 }
482 double doubleResult;
483 if (shouldCheckNegativeZero(node->arithMode()))
484 doubleResult = -child.asNumber();
485 else
486 doubleResult = 0 - child.asNumber();
487 JSValue valueResult = jsNumber(doubleResult);
488 if (valueResult.isInt32()) {
489 setConstant(node, valueResult);
490 break;
491 }
492 }
493 forNode(node).setType(SpecInt32);
494 if (shouldCheckOverflow(node->arithMode()))
495 node->setCanExit(true);
496 break;
497 case Int52RepUse:
498 if (child && child.isMachineInt()) {
499 double doubleResult;
500 if (shouldCheckNegativeZero(node->arithMode()))
501 doubleResult = -child.asNumber();
502 else
503 doubleResult = 0 - child.asNumber();
504 JSValue valueResult = jsNumber(doubleResult);
505 if (valueResult.isMachineInt()) {
506 setConstant(node, valueResult);
507 break;
508 }
509 }
510 forNode(node).setType(SpecMachineInt);
511 if (m_state.forNode(node->child1()).couldBeType(SpecInt52))
512 node->setCanExit(true);
513 if (shouldCheckNegativeZero(node->arithMode()))
514 node->setCanExit(true);
515 break;
516 case DoubleRepUse:
517 if (child && child.isNumber()) {
518 setConstant(node, jsDoubleNumber(-child.asNumber()));
519 break;
520 }
521 forNode(node).setType(
522 typeOfDoubleNegation(
523 forNode(node->child1()).m_type));
524 break;
525 default:
526 RELEASE_ASSERT_NOT_REACHED();
527 break;
528 }
529 break;
530 }
531
532 case ArithMul: {
533 JSValue left = forNode(node->child1()).value();
534 JSValue right = forNode(node->child2()).value();
535 switch (node->binaryUseKind()) {
536 case Int32Use:
537 if (left && right && left.isInt32() && right.isInt32()) {
538 if (!shouldCheckOverflow(node->arithMode())) {
539 setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
540 break;
541 }
542 double doubleResult = left.asNumber() * right.asNumber();
543 if (!shouldCheckNegativeZero(node->arithMode()))
544 doubleResult += 0; // Sanitizes zero.
545 JSValue valueResult = jsNumber(doubleResult);
546 if (valueResult.isInt32()) {
547 setConstant(node, valueResult);
548 break;
549 }
550 }
551 forNode(node).setType(SpecInt32);
552 if (shouldCheckOverflow(node->arithMode()))
553 node->setCanExit(true);
554 break;
555 case Int52RepUse:
556 if (left && right && left.isMachineInt() && right.isMachineInt()) {
557 double doubleResult = left.asNumber() * right.asNumber();
558 if (!shouldCheckNegativeZero(node->arithMode()))
559 doubleResult += 0;
560 JSValue valueResult = jsNumber(doubleResult);
561 if (valueResult.isMachineInt()) {
562 setConstant(node, valueResult);
563 break;
564 }
565 }
566 forNode(node).setType(SpecMachineInt);
567 node->setCanExit(true);
568 break;
569 case DoubleRepUse:
570 if (left && right && left.isNumber() && right.isNumber()) {
571 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
572 break;
573 }
574 forNode(node).setType(
575 typeOfDoubleProduct(
576 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
577 break;
578 default:
579 RELEASE_ASSERT_NOT_REACHED();
580 break;
581 }
582 break;
583 }
584
585 case ArithDiv: {
586 JSValue left = forNode(node->child1()).value();
587 JSValue right = forNode(node->child2()).value();
588 switch (node->binaryUseKind()) {
589 case Int32Use:
590 if (left && right && left.isInt32() && right.isInt32()) {
591 double doubleResult = left.asNumber() / right.asNumber();
592 if (!shouldCheckOverflow(node->arithMode()))
593 doubleResult = toInt32(doubleResult);
594 else if (!shouldCheckNegativeZero(node->arithMode()))
595 doubleResult += 0; // Sanitizes zero.
596 JSValue valueResult = jsNumber(doubleResult);
597 if (valueResult.isInt32()) {
598 setConstant(node, valueResult);
599 break;
600 }
601 }
602 forNode(node).setType(SpecInt32);
603 node->setCanExit(true);
604 break;
605 case DoubleRepUse:
606 if (left && right && left.isNumber() && right.isNumber()) {
607 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
608 break;
609 }
610 forNode(node).setType(
611 typeOfDoubleQuotient(
612 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
613 break;
614 default:
615 RELEASE_ASSERT_NOT_REACHED();
616 break;
617 }
618 break;
619 }
620
621 case ArithMod: {
622 JSValue left = forNode(node->child1()).value();
623 JSValue right = forNode(node->child2()).value();
624 switch (node->binaryUseKind()) {
625 case Int32Use:
626 if (left && right && left.isInt32() && right.isInt32()) {
627 double doubleResult = fmod(left.asNumber(), right.asNumber());
628 if (!shouldCheckOverflow(node->arithMode()))
629 doubleResult = toInt32(doubleResult);
630 else if (!shouldCheckNegativeZero(node->arithMode()))
631 doubleResult += 0; // Sanitizes zero.
632 JSValue valueResult = jsNumber(doubleResult);
633 if (valueResult.isInt32()) {
634 setConstant(node, valueResult);
635 break;
636 }
637 }
638 forNode(node).setType(SpecInt32);
639 node->setCanExit(true);
640 break;
641 case DoubleRepUse:
642 if (left && right && left.isNumber() && right.isNumber()) {
643 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
644 break;
645 }
646 forNode(node).setType(
647 typeOfDoubleBinaryOp(
648 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
649 break;
650 default:
651 RELEASE_ASSERT_NOT_REACHED();
652 break;
653 }
654 break;
655 }
656
657 case ArithMin: {
658 JSValue left = forNode(node->child1()).value();
659 JSValue right = forNode(node->child2()).value();
660 switch (node->binaryUseKind()) {
661 case Int32Use:
662 if (left && right && left.isInt32() && right.isInt32()) {
663 setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
664 break;
665 }
666 forNode(node).setType(SpecInt32);
667 node->setCanExit(true);
668 break;
669 case DoubleRepUse:
670 if (left && right && left.isNumber() && right.isNumber()) {
671 double a = left.asNumber();
672 double b = right.asNumber();
673 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
674 break;
675 }
676 forNode(node).setType(
677 typeOfDoubleMinMax(
678 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
679 break;
680 default:
681 RELEASE_ASSERT_NOT_REACHED();
682 break;
683 }
684 break;
685 }
686
687 case ArithMax: {
688 JSValue left = forNode(node->child1()).value();
689 JSValue right = forNode(node->child2()).value();
690 switch (node->binaryUseKind()) {
691 case Int32Use:
692 if (left && right && left.isInt32() && right.isInt32()) {
693 setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
694 break;
695 }
696 forNode(node).setType(SpecInt32);
697 node->setCanExit(true);
698 break;
699 case DoubleRepUse:
700 if (left && right && left.isNumber() && right.isNumber()) {
701 double a = left.asNumber();
702 double b = right.asNumber();
703 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
704 break;
705 }
706 forNode(node).setType(
707 typeOfDoubleMinMax(
708 forNode(node->child1()).m_type, forNode(node->child2()).m_type));
709 break;
710 default:
711 RELEASE_ASSERT_NOT_REACHED();
712 break;
713 }
714 break;
715 }
716
717 case ArithAbs: {
718 JSValue child = forNode(node->child1()).value();
719 switch (node->child1().useKind()) {
720 case Int32Use:
721 if (child && child.isInt32()) {
722 JSValue result = jsNumber(fabs(child.asNumber()));
723 if (result.isInt32()) {
724 setConstant(node, result);
725 break;
726 }
727 }
728 forNode(node).setType(SpecInt32);
729 node->setCanExit(true);
730 break;
731 case DoubleRepUse:
732 if (child && child.isNumber()) {
733 setConstant(node, jsDoubleNumber(child.asNumber()));
734 break;
735 }
736 forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
737 break;
738 default:
739 RELEASE_ASSERT_NOT_REACHED();
740 break;
741 }
742 break;
743 }
744
745 case ArithSqrt: {
746 JSValue child = forNode(node->child1()).value();
747 if (child && child.isNumber()) {
748 setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
749 break;
750 }
751 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
752 break;
753 }
754
755 case ArithFRound: {
756 JSValue child = forNode(node->child1()).value();
757 if (child && child.isNumber()) {
758 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
759 break;
760 }
761 forNode(node).setType(typeOfDoubleFRound(forNode(node->child1()).m_type));
762 break;
763 }
764
765 case ArithSin: {
766 JSValue child = forNode(node->child1()).value();
767 if (child && child.isNumber()) {
768 setConstant(node, jsDoubleNumber(sin(child.asNumber())));
769 break;
770 }
771 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
772 break;
773 }
774
775 case ArithCos: {
776 JSValue child = forNode(node->child1()).value();
777 if (child && child.isNumber()) {
778 setConstant(node, jsDoubleNumber(cos(child.asNumber())));
779 break;
780 }
781 forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
782 break;
783 }
784
785 case LogicalNot: {
786 switch (booleanResult(node, forNode(node->child1()))) {
787 case DefinitelyTrue:
788 setConstant(node, jsBoolean(false));
789 break;
790 case DefinitelyFalse:
791 setConstant(node, jsBoolean(true));
792 break;
793 default:
794 switch (node->child1().useKind()) {
795 case BooleanUse:
796 case Int32Use:
797 case DoubleRepUse:
798 case UntypedUse:
799 case StringUse:
800 break;
801 case ObjectOrOtherUse:
802 node->setCanExit(true);
803 break;
804 default:
805 RELEASE_ASSERT_NOT_REACHED();
806 break;
807 }
808 forNode(node).setType(SpecBoolean);
809 break;
810 }
811 break;
812 }
813
814 case IsUndefined:
815 case IsBoolean:
816 case IsNumber:
817 case IsString:
818 case IsObject:
819 case IsFunction: {
820 node->setCanExit(
821 node->op() == IsUndefined
822 && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic));
823 JSValue child = forNode(node->child1()).value();
824 if (child) {
825 bool constantWasSet = true;
826 switch (node->op()) {
827 case IsUndefined:
828 setConstant(node, jsBoolean(
829 child.isCell()
830 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
831 : child.isUndefined()));
832 break;
833 case IsBoolean:
834 setConstant(node, jsBoolean(child.isBoolean()));
835 break;
836 case IsNumber:
837 setConstant(node, jsBoolean(child.isNumber()));
838 break;
839 case IsString:
840 setConstant(node, jsBoolean(isJSString(child)));
841 break;
842 case IsObject:
843 if (child.isNull() || !child.isObject()) {
844 setConstant(node, jsBoolean(child.isNull()));
845 break;
846 }
847 constantWasSet = false;
848 break;
849 default:
850 constantWasSet = false;
851 break;
852 }
853 if (constantWasSet)
854 break;
855 }
856
857 forNode(node).setType(SpecBoolean);
858 break;
859 }
860
861 case TypeOf: {
862 VM* vm = m_codeBlock->vm();
863 JSValue child = forNode(node->child1()).value();
864 AbstractValue& abstractChild = forNode(node->child1());
865 if (child) {
866 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
867 setConstant(node, typeString);
868 break;
869 }
870
871 if (isFullNumberSpeculation(abstractChild.m_type)) {
872 setConstant(node, vm->smallStrings.numberString());
873 break;
874 }
875
876 if (isStringSpeculation(abstractChild.m_type)) {
877 setConstant(node, vm->smallStrings.stringString());
878 break;
879 }
880
881 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
882 setConstant(node, vm->smallStrings.objectString());
883 break;
884 }
885
886 if (isFunctionSpeculation(abstractChild.m_type)) {
887 setConstant(node, vm->smallStrings.functionString());
888 break;
889 }
890
891 if (isBooleanSpeculation(abstractChild.m_type)) {
892 setConstant(node, vm->smallStrings.booleanString());
893 break;
894 }
895
896 switch (node->child1().useKind()) {
897 case StringUse:
898 case CellUse:
899 node->setCanExit(true);
900 break;
901 case UntypedUse:
902 break;
903 default:
904 RELEASE_ASSERT_NOT_REACHED();
905 break;
906 }
907 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
908 break;
909 }
910
911 case CompareLess:
912 case CompareLessEq:
913 case CompareGreater:
914 case CompareGreaterEq:
915 case CompareEq:
916 case CompareEqConstant: {
917 JSValue leftConst = forNode(node->child1()).value();
918 JSValue rightConst = forNode(node->child2()).value();
919 if (leftConst && rightConst) {
920 if (leftConst.isNumber() && rightConst.isNumber()) {
921 double a = leftConst.asNumber();
922 double b = rightConst.asNumber();
923 switch (node->op()) {
924 case CompareLess:
925 setConstant(node, jsBoolean(a < b));
926 break;
927 case CompareLessEq:
928 setConstant(node, jsBoolean(a <= b));
929 break;
930 case CompareGreater:
931 setConstant(node, jsBoolean(a > b));
932 break;
933 case CompareGreaterEq:
934 setConstant(node, jsBoolean(a >= b));
935 break;
936 case CompareEq:
937 setConstant(node, jsBoolean(a == b));
938 break;
939 default:
940 RELEASE_ASSERT_NOT_REACHED();
941 break;
942 }
943 break;
944 }
945
946 if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) {
947 const StringImpl* a = asString(leftConst)->tryGetValueImpl();
948 const StringImpl* b = asString(rightConst)->tryGetValueImpl();
949 if (a && b) {
950 setConstant(node, jsBoolean(WTF::equal(a, b)));
951 break;
952 }
953 }
954 }
955
956 if (node->op() == CompareEqConstant || node->op() == CompareEq) {
957 SpeculatedType leftType = forNode(node->child1()).m_type;
958 SpeculatedType rightType = forNode(node->child2()).m_type;
959 if (!valuesCouldBeEqual(leftType, rightType)) {
960 setConstant(node, jsBoolean(false));
961 break;
962 }
963 }
964
965 forNode(node).setType(SpecBoolean);
966
967 // This is overly conservative. But the only thing this prevents is store elimination,
968 // and how likely is it, really, that you'll have redundant stores across a comparison
969 // operation? Comparison operations are typically at the end of basic blocks, so
970 // unless we have global store elimination (super unlikely given how unprofitable that
971 // optimization is to begin with), you aren't going to be wanting to store eliminate
972 // across an equality op.
973 node->setCanExit(true);
974 break;
975 }
976
977 case CompareStrictEq: {
978 Node* leftNode = node->child1().node();
979 Node* rightNode = node->child2().node();
980 JSValue left = forNode(leftNode).value();
981 JSValue right = forNode(rightNode).value();
982 if (left && right) {
983 if (left.isString() && right.isString()) {
984 // We need this case because JSValue::strictEqual is otherwise too racy for
985 // string comparisons.
986 const StringImpl* a = asString(left)->tryGetValueImpl();
987 const StringImpl* b = asString(right)->tryGetValueImpl();
988 if (a && b) {
989 setConstant(node, jsBoolean(WTF::equal(a, b)));
990 break;
991 }
992 } else {
993 setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
994 break;
995 }
996 }
997
998 SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
999 SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
1000 if (!(leftLUB & rightLUB)) {
1001 setConstant(node, jsBoolean(false));
1002 break;
1003 }
1004
1005 forNode(node).setType(SpecBoolean);
1006 node->setCanExit(true); // This is overly conservative.
1007 break;
1008 }
1009
1010 case StringCharCodeAt:
1011 node->setCanExit(true);
1012 forNode(node).setType(SpecInt32);
1013 break;
1014
1015 case StringFromCharCode:
1016 forNode(node).setType(SpecString);
1017 break;
1018
1019 case StringCharAt:
1020 node->setCanExit(true);
1021 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1022 break;
1023
1024 case GetByVal: {
1025 node->setCanExit(true);
1026 switch (node->arrayMode().type()) {
1027 case Array::SelectUsingPredictions:
1028 case Array::Unprofiled:
1029 case Array::Undecided:
1030 RELEASE_ASSERT_NOT_REACHED();
1031 break;
1032 case Array::ForceExit:
1033 m_state.setIsValid(false);
1034 break;
1035 case Array::Generic:
1036 clobberWorld(node->origin.semantic, clobberLimit);
1037 forNode(node).makeHeapTop();
1038 break;
1039 case Array::String:
1040 if (node->arrayMode().isOutOfBounds()) {
1041 // If the watchpoint was still valid we could totally set this to be
1042 // SpecString | SpecOther. Except that we'd have to be careful. If we
1043 // tested the watchpoint state here then it could change by the time
1044 // we got to the backend. So to do this right, we'd have to get the
1045 // fixup phase to check the watchpoint state and then bake into the
1046 // GetByVal operation the fact that we're using a watchpoint, using
1047 // something like Array::SaneChain (except not quite, because that
1048 // implies an in-bounds access). None of this feels like it's worth it,
1049 // so we're going with TOP for now. The same thing applies to
1050 // clobbering the world.
1051 clobberWorld(node->origin.semantic, clobberLimit);
1052 forNode(node).makeHeapTop();
1053 } else
1054 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1055 break;
1056 case Array::Arguments:
1057 forNode(node).makeHeapTop();
1058 break;
1059 case Array::Int32:
1060 if (node->arrayMode().isOutOfBounds()) {
1061 clobberWorld(node->origin.semantic, clobberLimit);
1062 forNode(node).makeHeapTop();
1063 } else
1064 forNode(node).setType(SpecInt32);
1065 break;
1066 case Array::Double:
1067 if (node->arrayMode().isOutOfBounds()) {
1068 clobberWorld(node->origin.semantic, clobberLimit);
1069 forNode(node).makeHeapTop();
1070 } else if (node->arrayMode().isSaneChain())
1071 forNode(node).setType(SpecBytecodeDouble);
1072 else
1073 forNode(node).setType(SpecDoubleReal);
1074 break;
1075 case Array::Contiguous:
1076 case Array::ArrayStorage:
1077 case Array::SlowPutArrayStorage:
1078 if (node->arrayMode().isOutOfBounds())
1079 clobberWorld(node->origin.semantic, clobberLimit);
1080 forNode(node).makeHeapTop();
1081 break;
1082 case Array::Int8Array:
1083 forNode(node).setType(SpecInt32);
1084 break;
1085 case Array::Int16Array:
1086 forNode(node).setType(SpecInt32);
1087 break;
1088 case Array::Int32Array:
1089 forNode(node).setType(SpecInt32);
1090 break;
1091 case Array::Uint8Array:
1092 forNode(node).setType(SpecInt32);
1093 break;
1094 case Array::Uint8ClampedArray:
1095 forNode(node).setType(SpecInt32);
1096 break;
1097 case Array::Uint16Array:
1098 forNode(node).setType(SpecInt32);
1099 break;
1100 case Array::Uint32Array:
1101 if (node->shouldSpeculateInt32())
1102 forNode(node).setType(SpecInt32);
1103 else if (enableInt52() && node->shouldSpeculateMachineInt())
1104 forNode(node).setType(SpecInt52);
1105 else
1106 forNode(node).setType(SpecInt52AsDouble);
1107 break;
1108 case Array::Float32Array:
1109 forNode(node).setType(SpecFullDouble);
1110 break;
1111 case Array::Float64Array:
1112 forNode(node).setType(SpecFullDouble);
1113 break;
1114 default:
1115 RELEASE_ASSERT_NOT_REACHED();
1116 break;
1117 }
1118 break;
1119 }
1120
1121 case PutByValDirect:
1122 case PutByVal:
1123 case PutByValAlias: {
1124 node->setCanExit(true);
1125 switch (node->arrayMode().modeForPut().type()) {
1126 case Array::ForceExit:
1127 m_state.setIsValid(false);
1128 break;
1129 case Array::Generic:
1130 clobberWorld(node->origin.semantic, clobberLimit);
1131 break;
1132 case Array::Int32:
1133 if (node->arrayMode().isOutOfBounds())
1134 clobberWorld(node->origin.semantic, clobberLimit);
1135 break;
1136 case Array::Double:
1137 if (node->arrayMode().isOutOfBounds())
1138 clobberWorld(node->origin.semantic, clobberLimit);
1139 break;
1140 case Array::Contiguous:
1141 case Array::ArrayStorage:
1142 if (node->arrayMode().isOutOfBounds())
1143 clobberWorld(node->origin.semantic, clobberLimit);
1144 break;
1145 case Array::SlowPutArrayStorage:
1146 if (node->arrayMode().mayStoreToHole())
1147 clobberWorld(node->origin.semantic, clobberLimit);
1148 break;
1149 default:
1150 break;
1151 }
1152 break;
1153 }
1154
1155 case ArrayPush:
1156 node->setCanExit(true);
1157 clobberWorld(node->origin.semantic, clobberLimit);
1158 forNode(node).setType(SpecBytecodeNumber);
1159 break;
1160
1161 case ArrayPop:
1162 node->setCanExit(true);
1163 clobberWorld(node->origin.semantic, clobberLimit);
1164 forNode(node).makeHeapTop();
1165 break;
1166
1167 case RegExpExec:
1168 forNode(node).makeHeapTop();
1169 break;
1170
1171 case RegExpTest:
1172 forNode(node).setType(SpecBoolean);
1173 break;
1174
1175 case Jump:
1176 break;
1177
1178 case Branch: {
1179 Node* child = node->child1().node();
1180 BooleanResult result = booleanResult(node, forNode(child));
1181 if (result == DefinitelyTrue) {
1182 m_state.setBranchDirection(TakeTrue);
1183 break;
1184 }
1185 if (result == DefinitelyFalse) {
1186 m_state.setBranchDirection(TakeFalse);
1187 break;
1188 }
1189 // FIXME: The above handles the trivial cases of sparse conditional
1190 // constant propagation, but we can do better:
1191 // We can specialize the source variable's value on each direction of
1192 // the branch.
1193 node->setCanExit(true); // This is overly conservative.
1194 m_state.setBranchDirection(TakeBoth);
1195 break;
1196 }
1197
1198 case Switch: {
1199 // Nothing to do for now.
1200 // FIXME: Do sparse conditional things.
1201 break;
1202 }
1203
1204 case Return:
1205 m_state.setIsValid(false);
1206 break;
1207
1208 case Throw:
1209 case ThrowReferenceError:
1210 m_state.setIsValid(false);
1211 node->setCanExit(true);
1212 break;
1213
1214 case ToPrimitive: {
1215 JSValue childConst = forNode(node->child1()).value();
1216 if (childConst && childConst.isNumber()) {
1217 setConstant(node, childConst);
1218 break;
1219 }
1220
1221 ASSERT(node->child1().useKind() == UntypedUse);
1222
1223 if (!forNode(node->child1()).m_type) {
1224 m_state.setIsValid(false);
1225 break;
1226 }
1227
1228 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString))) {
1229 m_state.setFoundConstants(true);
1230 forNode(node) = forNode(node->child1());
1231 break;
1232 }
1233
1234 clobberWorld(node->origin.semantic, clobberLimit);
1235
1236 forNode(node).setType((SpecHeapTop & ~SpecCell) | SpecString);
1237 break;
1238 }
1239
1240 case ToString: {
1241 switch (node->child1().useKind()) {
1242 case StringObjectUse:
1243 // This also filters that the StringObject has the primordial StringObject
1244 // structure.
1245 filter(
1246 node->child1(),
1247 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
1248 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1249 break;
1250 case StringOrStringObjectUse:
1251 node->setCanExit(true); // We could be more precise but it's likely not worth it.
1252 break;
1253 case CellUse:
1254 case UntypedUse:
1255 clobberWorld(node->origin.semantic, clobberLimit);
1256 break;
1257 default:
1258 RELEASE_ASSERT_NOT_REACHED();
1259 break;
1260 }
1261 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
1262 break;
1263 }
1264
1265 case NewStringObject: {
1266 ASSERT(node->structure()->classInfo() == StringObject::info());
1267 forNode(node).set(m_graph, node->structure());
1268 break;
1269 }
1270
1271 case NewArray:
1272 node->setCanExit(true);
1273 forNode(node).set(
1274 m_graph,
1275 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1276 m_state.setHaveStructures(true);
1277 break;
1278
1279 case NewArrayBuffer:
1280 node->setCanExit(true);
1281 forNode(node).set(
1282 m_graph,
1283 m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
1284 m_state.setHaveStructures(true);
1285 break;
1286
1287 case NewArrayWithSize:
1288 node->setCanExit(true);
1289 forNode(node).setType(SpecArray);
1290 m_state.setHaveStructures(true);
1291 break;
1292
1293 case NewTypedArray:
1294 switch (node->child1().useKind()) {
1295 case Int32Use:
1296 break;
1297 case UntypedUse:
1298 clobberWorld(node->origin.semantic, clobberLimit);
1299 break;
1300 default:
1301 RELEASE_ASSERT_NOT_REACHED();
1302 break;
1303 }
1304 forNode(node).set(
1305 m_graph,
1306 m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
1307 node->typedArrayType()));
1308 m_state.setHaveStructures(true);
1309 break;
1310
1311 case NewRegexp:
1312 forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
1313 m_state.setHaveStructures(true);
1314 break;
1315
1316 case ToThis: {
1317 AbstractValue& source = forNode(node->child1());
1318 AbstractValue& destination = forNode(node);
1319
1320 if (m_graph.executableFor(node->origin.semantic)->isStrictMode())
1321 destination.makeHeapTop();
1322 else {
1323 destination = source;
1324 destination.merge(SpecObject);
1325 }
1326 break;
1327 }
1328
1329 case CreateThis: {
1330 forNode(node).setType(SpecFinalObject);
1331 break;
1332 }
1333
1334 case AllocationProfileWatchpoint:
1335 node->setCanExit(true);
1336 break;
1337
1338 case NewObject:
1339 ASSERT(node->structure());
1340 forNode(node).set(m_graph, node->structure());
1341 m_state.setHaveStructures(true);
1342 break;
1343
1344 case CreateActivation:
1345 forNode(node).set(
1346 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
1347 m_state.setHaveStructures(true);
1348 break;
1349
1350 case FunctionReentryWatchpoint:
1351 case TypedArrayWatchpoint:
1352 break;
1353
1354 case CreateArguments:
1355 forNode(node) = forNode(node->child1());
1356 forNode(node).filter(~SpecEmpty);
1357 forNode(node).merge(SpecArguments);
1358 break;
1359
1360 case TearOffActivation:
1361 case TearOffArguments:
1362 // Does nothing that is user-visible.
1363 break;
1364
1365 case CheckArgumentsNotCreated:
1366 if (isEmptySpeculation(
1367 m_state.variables().operand(
1368 m_graph.argumentsRegisterFor(node->origin.semantic).offset()).m_type))
1369 m_state.setFoundConstants(true);
1370 else
1371 node->setCanExit(true);
1372 break;
1373
1374 case GetMyArgumentsLength:
1375 // We know that this executable does not escape its arguments, so we can optimize
1376 // the arguments a bit. Note that this is not sufficient to force constant folding
1377 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
1378 // We perform further optimizations on this later on.
1379 if (node->origin.semantic.inlineCallFrame) {
1380 forNode(node).set(
1381 m_graph, jsNumber(node->origin.semantic.inlineCallFrame->arguments.size() - 1));
1382 } else
1383 forNode(node).setType(SpecInt32);
1384 node->setCanExit(
1385 !isEmptySpeculation(
1386 m_state.variables().operand(
1387 m_graph.argumentsRegisterFor(node->origin.semantic)).m_type));
1388 break;
1389
1390 case GetMyArgumentsLengthSafe:
1391 // This potentially clobbers all structures if the arguments object had a getter
1392 // installed on the length property.
1393 clobberWorld(node->origin.semantic, clobberLimit);
1394 // We currently make no guarantee about what this returns because it does not
1395 // speculate that the length property is actually a length.
1396 forNode(node).makeHeapTop();
1397 break;
1398
1399 case GetMyArgumentByVal:
1400 node->setCanExit(true);
1401 // We know that this executable does not escape its arguments, so we can optimize
1402 // the arguments a bit. Note that this ends up being further optimized by the
1403 // ArgumentsSimplificationPhase.
1404 forNode(node).makeHeapTop();
1405 break;
1406
1407 case GetMyArgumentByValSafe:
1408 node->setCanExit(true);
1409 // This potentially clobbers all structures if the property we're accessing has
1410 // a getter. We don't speculate against this.
1411 clobberWorld(node->origin.semantic, clobberLimit);
1412 // And the result is unknown.
1413 forNode(node).makeHeapTop();
1414 break;
1415
1416 case NewFunction: {
1417 AbstractValue& value = forNode(node);
1418 value = forNode(node->child1());
1419
1420 if (!(value.m_type & SpecEmpty)) {
1421 m_state.setFoundConstants(true);
1422 break;
1423 }
1424
1425 value.setType((value.m_type & ~SpecEmpty) | SpecFunction);
1426 break;
1427 }
1428
1429 case NewFunctionExpression:
1430 case NewFunctionNoCheck:
1431 forNode(node).set(
1432 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
1433 m_state.setHaveStructures(true);
1434 break;
1435
1436 case GetCallee:
1437 forNode(node).setType(SpecFunction);
1438 break;
1439
1440 case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
1441 case GetMyScope:
1442 case SkipTopScope:
1443 forNode(node).setType(SpecObjectOther);
1444 break;
1445
1446 case SkipScope: {
1447 JSValue child = forNode(node->child1()).value();
1448 if (child) {
1449 setConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()));
1450 break;
1451 }
1452 forNode(node).setType(SpecObjectOther);
1453 break;
1454 }
1455
1456 case GetClosureRegisters:
1457 forNode(node).clear(); // The result is not a JS value.
1458 break;
1459
1460 case GetClosureVar:
1461 forNode(node).makeHeapTop();
1462 break;
1463
1464 case PutClosureVar:
1465 clobberCapturedVars(node->origin.semantic);
1466 break;
1467
1468 case GetById:
1469 case GetByIdFlush:
1470 node->setCanExit(true);
1471 if (!node->prediction()) {
1472 m_state.setIsValid(false);
1473 break;
1474 }
1475 if (isCellSpeculation(node->child1()->prediction())) {
1476 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
1477 GetByIdStatus status = GetByIdStatus::computeFor(
1478 m_graph.m_vm, structure,
1479 m_graph.identifiers()[node->identifierNumber()]);
1480 if (status.isSimple() && status.numVariants() == 1) {
1481 // Assert things that we can't handle and that the computeFor() method
1482 // above won't be able to return.
1483 ASSERT(status[0].structureSet().size() == 1);
1484 ASSERT(!status[0].chain());
1485
1486 if (status[0].specificValue())
1487 setConstant(node, status[0].specificValue());
1488 else
1489 forNode(node).makeHeapTop();
1490 filter(node->child1(), status[0].structureSet());
1491
1492 m_state.setFoundConstants(true);
1493 m_state.setHaveStructures(true);
1494 break;
1495 }
1496 }
1497 }
1498 clobberWorld(node->origin.semantic, clobberLimit);
1499 forNode(node).makeHeapTop();
1500 break;
1501
1502 case GetArrayLength:
1503 node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
1504 forNode(node).setType(SpecInt32);
1505 break;
1506
1507 case CheckExecutable: {
1508 // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
1509 // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
1510 // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
1511 // https://bugs.webkit.org/show_bug.cgi?id=106201
1512 node->setCanExit(true);
1513 break;
1514 }
1515
1516 case CheckStructure: {
1517 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
1518 AbstractValue& value = forNode(node->child1());
1519 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1520
1521 StructureSet& set = node->structureSet();
1522
1523 if (value.m_currentKnownStructure.isSubsetOf(set)) {
1524 m_state.setFoundConstants(true);
1525 break;
1526 }
1527
1528 node->setCanExit(true);
1529 m_state.setHaveStructures(true);
1530
1531 // If this structure check is attempting to prove knowledge already held in
1532 // the futurePossibleStructure set then the constant folding phase should
1533 // turn this into a watchpoint instead.
1534 if (value.m_futurePossibleStructure.isSubsetOf(set)
1535 && value.m_futurePossibleStructure.hasSingleton()) {
1536 m_state.setFoundConstants(true);
1537 filter(value, value.m_futurePossibleStructure.singleton());
1538 break;
1539 }
1540
1541 filter(value, set);
1542 break;
1543 }
1544
1545 case StructureTransitionWatchpoint: {
1546 AbstractValue& value = forNode(node->child1());
1547
1548 filter(value, node->structure());
1549 m_state.setHaveStructures(true);
1550 node->setCanExit(true);
1551 break;
1552 }
1553
1554 case PutStructure:
1555 case PhantomPutStructure:
1556 if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
1557 clobberStructures(clobberLimit);
1558 forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure);
1559 m_state.setHaveStructures(true);
1560 }
1561 break;
1562 case GetButterfly:
1563 case AllocatePropertyStorage:
1564 case ReallocatePropertyStorage:
1565 forNode(node).clear(); // The result is not a JS value.
1566 break;
1567 case CheckArray: {
1568 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1569 m_state.setFoundConstants(true);
1570 break;
1571 }
1572 node->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
1573 switch (node->arrayMode().type()) {
1574 case Array::String:
1575 filter(node->child1(), SpecString);
1576 break;
1577 case Array::Int32:
1578 case Array::Double:
1579 case Array::Contiguous:
1580 case Array::ArrayStorage:
1581 case Array::SlowPutArrayStorage:
1582 break;
1583 case Array::Arguments:
1584 filter(node->child1(), SpecArguments);
1585 break;
1586 case Array::Int8Array:
1587 filter(node->child1(), SpecInt8Array);
1588 break;
1589 case Array::Int16Array:
1590 filter(node->child1(), SpecInt16Array);
1591 break;
1592 case Array::Int32Array:
1593 filter(node->child1(), SpecInt32Array);
1594 break;
1595 case Array::Uint8Array:
1596 filter(node->child1(), SpecUint8Array);
1597 break;
1598 case Array::Uint8ClampedArray:
1599 filter(node->child1(), SpecUint8ClampedArray);
1600 break;
1601 case Array::Uint16Array:
1602 filter(node->child1(), SpecUint16Array);
1603 break;
1604 case Array::Uint32Array:
1605 filter(node->child1(), SpecUint32Array);
1606 break;
1607 case Array::Float32Array:
1608 filter(node->child1(), SpecFloat32Array);
1609 break;
1610 case Array::Float64Array:
1611 filter(node->child1(), SpecFloat64Array);
1612 break;
1613 default:
1614 RELEASE_ASSERT_NOT_REACHED();
1615 break;
1616 }
1617 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1618 m_state.setHaveStructures(true);
1619 break;
1620 }
1621 case Arrayify: {
1622 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
1623 m_state.setFoundConstants(true);
1624 break;
1625 }
1626 ASSERT(node->arrayMode().conversion() == Array::Convert
1627 || node->arrayMode().conversion() == Array::RageConvert);
1628 node->setCanExit(true);
1629 clobberStructures(clobberLimit);
1630 filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
1631 m_state.setHaveStructures(true);
1632 break;
1633 }
1634 case ArrayifyToStructure: {
1635 AbstractValue& value = forNode(node->child1());
1636 StructureSet set = node->structure();
1637 if (value.m_futurePossibleStructure.isSubsetOf(set)
1638 || value.m_currentKnownStructure.isSubsetOf(set))
1639 m_state.setFoundConstants(true);
1640 node->setCanExit(true);
1641 clobberStructures(clobberLimit);
1642 filter(value, set);
1643 m_state.setHaveStructures(true);
1644 break;
1645 }
1646 case GetIndexedPropertyStorage:
1647 case ConstantStoragePointer: {
1648 forNode(node).clear();
1649 break;
1650 }
1651
1652 case GetTypedArrayByteOffset: {
1653 forNode(node).setType(SpecInt32);
1654 break;
1655 }
1656
1657 case GetByOffset: {
1658 forNode(node).makeHeapTop();
1659 break;
1660 }
1661
1662 case MultiGetByOffset: {
1663 AbstractValue& value = forNode(node->child1());
1664 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1665
1666 if (Structure* structure = value.bestProvenStructure()) {
1667 bool done = false;
1668 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
1669 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
1670 if (!variant.structureSet().contains(structure))
1671 continue;
1672
1673 if (variant.chain())
1674 break;
1675
1676 filter(value, structure);
1677 forNode(node).makeHeapTop();
1678 m_state.setFoundConstants(true);
1679 done = true;
1680 break;
1681 }
1682 if (done)
1683 break;
1684 }
1685
1686 StructureSet set;
1687 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
1688 set.addAll(node->multiGetByOffsetData().variants[i].structureSet());
1689
1690 filter(node->child1(), set);
1691 forNode(node).makeHeapTop();
1692 break;
1693 }
1694
1695 case PutByOffset: {
1696 break;
1697 }
1698
1699 case MultiPutByOffset: {
1700 AbstractValue& value = forNode(node->child1());
1701 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1702
1703 if (Structure* structure = value.bestProvenStructure()) {
1704 bool done = false;
1705 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1706 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1707 if (variant.oldStructure() != structure)
1708 continue;
1709
1710 if (variant.kind() == PutByIdVariant::Replace) {
1711 filter(node->child1(), structure);
1712 m_state.setFoundConstants(true);
1713 m_state.setHaveStructures(true);
1714 done = true;
1715 break;
1716 }
1717
1718 ASSERT(variant.kind() == PutByIdVariant::Transition);
1719 clobberStructures(clobberLimit);
1720 forNode(node->child1()).set(m_graph, variant.newStructure());
1721 m_state.setFoundConstants(true);
1722 m_state.setHaveStructures(true);
1723 done = true;
1724 break;
1725 }
1726 if (done)
1727 break;
1728 }
1729
1730 clobberStructures(clobberLimit);
1731
1732 StructureSet newSet;
1733 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1734 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1735 if (variant.kind() == PutByIdVariant::Replace) {
1736 if (value.m_currentKnownStructure.contains(variant.structure()))
1737 newSet.addAll(variant.structure());
1738 continue;
1739 }
1740 ASSERT(variant.kind() == PutByIdVariant::Transition);
1741 if (value.m_currentKnownStructure.contains(variant.oldStructure()))
1742 newSet.addAll(variant.newStructure());
1743 }
1744
1745 // Use filter(value, set) as a way of setting the structure set. This works because
1746 // we would have already made the set be TOP before this. Filtering top is another
1747 // way of setting.
1748 filter(node->child1(), newSet);
1749 break;
1750 }
1751
1752 case CheckFunction: {
1753 JSValue value = forNode(node->child1()).value();
1754 if (value == node->function()) {
1755 m_state.setFoundConstants(true);
1756 ASSERT(value);
1757 break;
1758 }
1759
1760 node->setCanExit(true); // Lies! We can do better.
1761 filterByValue(node->child1(), node->function());
1762 break;
1763 }
1764
1765 case CheckInBounds: {
1766 JSValue left = forNode(node->child1()).value();
1767 JSValue right = forNode(node->child2()).value();
1768 if (left && right && left.isInt32() && right.isInt32()
1769 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
1770 m_state.setFoundConstants(true);
1771 break;
1772 }
1773
1774 node->setCanExit(true);
1775 break;
1776 }
1777
1778 case PutById:
1779 case PutByIdFlush:
1780 case PutByIdDirect:
1781 node->setCanExit(true);
1782 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
1783 PutByIdStatus status = PutByIdStatus::computeFor(
1784 m_graph.m_vm,
1785 m_graph.globalObjectFor(node->origin.semantic),
1786 structure,
1787 m_graph.identifiers()[node->identifierNumber()],
1788 node->op() == PutByIdDirect);
1789 if (status.isSimple() && status.numVariants() == 1) {
1790 if (status[0].kind() == PutByIdVariant::Replace) {
1791 filter(node->child1(), structure);
1792 m_state.setFoundConstants(true);
1793 m_state.setHaveStructures(true);
1794 break;
1795 }
1796 if (status[0].kind() == PutByIdVariant::Transition) {
1797 clobberStructures(clobberLimit);
1798 forNode(node->child1()).set(m_graph, status[0].newStructure());
1799 m_state.setHaveStructures(true);
1800 m_state.setFoundConstants(true);
1801 break;
1802 }
1803 }
1804 }
1805 clobberWorld(node->origin.semantic, clobberLimit);
1806 break;
1807
1808 case In:
1809 // FIXME: We can determine when the property definitely exists based on abstract
1810 // value information.
1811 clobberWorld(node->origin.semantic, clobberLimit);
1812 forNode(node).setType(SpecBoolean);
1813 break;
1814
1815 case GetGlobalVar:
1816 forNode(node).makeHeapTop();
1817 break;
1818
1819 case VariableWatchpoint:
1820 case VarInjectionWatchpoint:
1821 node->setCanExit(true);
1822 break;
1823
1824 case PutGlobalVar:
1825 case NotifyWrite:
1826 break;
1827
1828 case CheckHasInstance:
1829 node->setCanExit(true);
1830 // Sadly, we don't propagate the fact that we've done CheckHasInstance
1831 break;
1832
1833 case InstanceOf:
1834 node->setCanExit(true);
1835 // Again, sadly, we don't propagate the fact that we've done InstanceOf
1836 forNode(node).setType(SpecBoolean);
1837 break;
1838
1839 case Phi:
1840 RELEASE_ASSERT(m_graph.m_form == SSA);
1841 // The state of this node would have already been decided.
1842 break;
1843
1844 case Upsilon: {
1845 m_state.createValueForNode(node->phi());
1846 AbstractValue& value = forNode(node->child1());
1847 forNode(node) = value;
1848 forNode(node->phi()) = value;
1849 break;
1850 }
1851
1852 case Flush:
1853 case PhantomLocal:
1854 break;
1855
1856 case Call:
1857 case Construct:
1858 node->setCanExit(true);
1859 clobberWorld(node->origin.semantic, clobberLimit);
1860 forNode(node).makeHeapTop();
1861 break;
1862
1863 case ForceOSRExit:
1864 node->setCanExit(true);
1865 m_state.setIsValid(false);
1866 break;
1867
1868 case InvalidationPoint:
1869 node->setCanExit(true);
1870 break;
1871
1872 case CheckWatchdogTimer:
1873 node->setCanExit(true);
1874 break;
1875
1876 case Breakpoint:
1877 case ProfileWillCall:
1878 case ProfileDidCall:
1879 case Phantom:
1880 case HardPhantom:
1881 case Check:
1882 case CountExecution:
1883 case CheckTierUpInLoop:
1884 case CheckTierUpAtReturn:
1885 break;
1886
1887 case StoreBarrier: {
1888 filter(node->child1(), SpecCell);
1889 break;
1890 }
1891
1892 case StoreBarrierWithNullCheck: {
1893 break;
1894 }
1895
1896 case CheckTierUpAndOSREnter:
1897 case LoopHint:
1898 // We pretend that it can exit because it may want to get all state.
1899 node->setCanExit(true);
1900 break;
1901
1902 case ZombieHint:
1903 case Unreachable:
1904 case LastNodeType:
1905 case ArithIMul:
1906 case FiatInt52:
1907 RELEASE_ASSERT_NOT_REACHED();
1908 break;
1909 }
1910
1911 return m_state.isValid();
1912}
1913
1914template<typename AbstractStateType>
1915bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
1916{
1917 return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
1918}
1919
1920template<typename AbstractStateType>
1921bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
1922{
1923 Node* node = m_state.block()->at(indexInBlock);
1924 if (!startExecuting(node))
1925 return true;
1926
1927 executeEdges(node);
1928 return executeEffects(indexInBlock, node);
1929}
1930
1931template<typename AbstractStateType>
1932bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
1933{
1934 if (!startExecuting(node))
1935 return true;
1936
1937 executeEdges(node);
1938 return executeEffects(UINT_MAX, node);
1939}
1940
1941template<typename AbstractStateType>
1942void AbstractInterpreter<AbstractStateType>::clobberWorld(
1943 const CodeOrigin& codeOrigin, unsigned clobberLimit)
1944{
1945 clobberCapturedVars(codeOrigin);
1946 clobberStructures(clobberLimit);
1947}
1948
1949template<typename AbstractStateType>
1950void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigin& codeOrigin)
1951{
1952 if (codeOrigin.inlineCallFrame) {
1953 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;
1954 for (size_t i = capturedVars.size(); i--;) {
1955 if (!capturedVars.quickGet(i))
1956 continue;
1957 m_state.variables().local(i).makeHeapTop();
1958 }
1959 } else {
1960 for (size_t i = m_codeBlock->m_numVars; i--;) {
1961 if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))
1962 m_state.variables().local(i).makeHeapTop();
1963 }
1964 }
1965
1966 for (size_t i = m_state.variables().numberOfArguments(); i--;) {
1967 if (m_codeBlock->isCaptured(virtualRegisterForArgument(i)))
1968 m_state.variables().argument(i).makeHeapTop();
1969 }
1970}
1971
1972template<typename AbstractStateType>
1973void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
1974{
1975 if (!m_state.haveStructures())
1976 return;
1977 if (clobberLimit >= m_state.block()->size())
1978 clobberLimit = m_state.block()->size();
1979 else
1980 clobberLimit++;
1981 ASSERT(clobberLimit <= m_state.block()->size());
1982 for (size_t i = clobberLimit; i--;)
1983 forNode(m_state.block()->at(i)).clobberStructures();
1984 if (m_graph.m_form == SSA) {
1985 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
1986 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
1987 for (; iter != end; ++iter)
1988 forNode(*iter).clobberStructures();
1989 }
1990 for (size_t i = m_state.variables().numberOfArguments(); i--;)
1991 m_state.variables().argument(i).clobberStructures();
1992 for (size_t i = m_state.variables().numberOfLocals(); i--;)
1993 m_state.variables().local(i).clobberStructures();
1994 m_state.setHaveStructures(true);
1995 m_state.setDidClobber(true);
1996}
1997
1998template<typename AbstractStateType>
1999void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
2000{
2001 CommaPrinter comma(" ");
2002 if (m_graph.m_form == SSA) {
2003 HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
2004 HashSet<Node*>::iterator end = m_state.block()->ssa->liveAtHead.end();
2005 for (; iter != end; ++iter) {
2006 Node* node = *iter;
2007 AbstractValue& value = forNode(node);
2008 if (value.isClear())
2009 continue;
2010 out.print(comma, node, ":", value);
2011 }
2012 }
2013 for (size_t i = 0; i < m_state.block()->size(); ++i) {
2014 Node* node = m_state.block()->at(i);
2015 AbstractValue& value = forNode(node);
2016 if (value.isClear())
2017 continue;
2018 out.print(comma, node, ":", value);
2019 }
2020}
2021
2022template<typename AbstractStateType>
2023FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2024 AbstractValue& value, const StructureSet& set)
2025{
2026 if (value.filter(m_graph, set) == FiltrationOK)
2027 return FiltrationOK;
2028 m_state.setIsValid(false);
2029 return Contradiction;
2030}
2031
2032template<typename AbstractStateType>
2033FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
2034 AbstractValue& value, ArrayModes arrayModes)
2035{
2036 if (value.filterArrayModes(arrayModes) == FiltrationOK)
2037 return FiltrationOK;
2038 m_state.setIsValid(false);
2039 return Contradiction;
2040}
2041
2042template<typename AbstractStateType>
2043FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2044 AbstractValue& value, SpeculatedType type)
2045{
2046 if (value.filter(type) == FiltrationOK)
2047 return FiltrationOK;
2048 m_state.setIsValid(false);
2049 return Contradiction;
2050}
2051
2052template<typename AbstractStateType>
2053FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
2054 AbstractValue& abstractValue, JSValue concreteValue)
2055{
2056 if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
2057 return FiltrationOK;
2058 m_state.setIsValid(false);
2059 return Contradiction;
2060}
2061
2062} } // namespace JSC::DFG
2063
2064#endif // ENABLE(DFG_JIT)
2065
2066#endif // DFGAbstractInterpreterInlines_h
2067