2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGAbstractState.h"
31 #include "CodeBlock.h"
32 #include "DFGBasicBlock.h"
34 namespace JSC
{ namespace DFG
{
36 #define CFA_PROFILING 0
39 #define PROFILE(flag) SamplingFlags::ScopedFlag scopedFlag(flag)
41 #define PROFILE(flag) do { } while (false)
45 #define FLAG_FOR_BLOCK_INITIALIZATION 17
46 #define FLAG_FOR_BLOCK_END 18
47 #define FLAG_FOR_EXECUTION 19
48 #define FLAG_FOR_MERGE_TO_SUCCESSORS 20
49 #define FLAG_FOR_STRUCTURE_CLOBBERING 21
51 AbstractState::AbstractState(Graph
& graph
)
52 : m_codeBlock(graph
.m_codeBlock
)
54 , m_variables(m_codeBlock
->numParameters(), graph
.m_localVars
)
57 m_nodes
.resize(graph
.size());
60 AbstractState::~AbstractState() { }
62 void AbstractState::beginBasicBlock(BasicBlock
* basicBlock
)
64 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION
);
68 ASSERT(basicBlock
->variablesAtHead
.numberOfLocals() == basicBlock
->valuesAtHead
.numberOfLocals());
69 ASSERT(basicBlock
->variablesAtTail
.numberOfLocals() == basicBlock
->valuesAtTail
.numberOfLocals());
70 ASSERT(basicBlock
->variablesAtHead
.numberOfLocals() == basicBlock
->variablesAtTail
.numberOfLocals());
72 for (size_t i
= 0; i
< basicBlock
->size(); i
++)
73 m_nodes
[basicBlock
->at(i
)].clear();
75 m_variables
= basicBlock
->valuesAtHead
;
76 m_haveStructures
= false;
77 for (size_t i
= 0; i
< m_variables
.numberOfArguments(); ++i
) {
78 if (m_variables
.argument(i
).m_structure
.isNeitherClearNorTop()) {
79 m_haveStructures
= true;
83 for (size_t i
= 0; i
< m_variables
.numberOfLocals(); ++i
) {
84 if (m_variables
.local(i
).m_structure
.isNeitherClearNorTop()) {
85 m_haveStructures
= true;
90 basicBlock
->cfaShouldRevisit
= false;
91 basicBlock
->cfaHasVisited
= true;
96 void AbstractState::initialize(Graph
& graph
)
98 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION
);
99 BasicBlock
* root
= graph
.m_blocks
[0].get();
100 root
->cfaShouldRevisit
= true;
101 for (size_t i
= 0; i
< root
->valuesAtHead
.numberOfArguments(); ++i
) {
102 Node
& node
= graph
[root
->variablesAtHead
.argument(i
)];
103 ASSERT(node
.op() == SetArgument
);
104 if (!node
.shouldGenerate()) {
105 // The argument is dead. We don't do any checks for such arguments, and so
106 // for the purpose of the analysis, they contain no value.
107 root
->valuesAtHead
.argument(i
).clear();
111 if (graph
.argumentIsCaptured(i
)) {
112 root
->valuesAtHead
.argument(i
).makeTop();
116 PredictedType prediction
= node
.variableAccessData()->prediction();
117 if (isInt32Prediction(prediction
))
118 root
->valuesAtHead
.argument(i
).set(PredictInt32
);
119 else if (isArrayPrediction(prediction
))
120 root
->valuesAtHead
.argument(i
).set(PredictArray
);
121 else if (isBooleanPrediction(prediction
))
122 root
->valuesAtHead
.argument(i
).set(PredictBoolean
);
123 else if (isInt8ArrayPrediction(prediction
))
124 root
->valuesAtHead
.argument(i
).set(PredictInt8Array
);
125 else if (isInt16ArrayPrediction(prediction
))
126 root
->valuesAtHead
.argument(i
).set(PredictInt16Array
);
127 else if (isInt32ArrayPrediction(prediction
))
128 root
->valuesAtHead
.argument(i
).set(PredictInt32Array
);
129 else if (isUint8ArrayPrediction(prediction
))
130 root
->valuesAtHead
.argument(i
).set(PredictUint8Array
);
131 else if (isUint8ClampedArrayPrediction(prediction
))
132 root
->valuesAtHead
.argument(i
).set(PredictUint8ClampedArray
);
133 else if (isUint16ArrayPrediction(prediction
))
134 root
->valuesAtHead
.argument(i
).set(PredictUint16Array
);
135 else if (isUint32ArrayPrediction(prediction
))
136 root
->valuesAtHead
.argument(i
).set(PredictUint32Array
);
137 else if (isFloat32ArrayPrediction(prediction
))
138 root
->valuesAtHead
.argument(i
).set(PredictFloat32Array
);
139 else if (isFloat64ArrayPrediction(prediction
))
140 root
->valuesAtHead
.argument(i
).set(PredictFloat64Array
);
142 root
->valuesAtHead
.argument(i
).makeTop();
144 for (size_t i
= 0; i
< root
->valuesAtHead
.numberOfLocals(); ++i
) {
145 if (!graph
.localIsCaptured(i
))
147 root
->valuesAtHead
.local(i
).makeTop();
151 bool AbstractState::endBasicBlock(MergeMode mergeMode
)
153 PROFILE(FLAG_FOR_BLOCK_END
);
156 BasicBlock
* block
= m_block
; // Save the block for successor merging.
163 bool changed
= false;
165 if (mergeMode
!= DontMerge
|| !ASSERT_DISABLED
) {
166 for (size_t argument
= 0; argument
< block
->variablesAtTail
.numberOfArguments(); ++argument
) {
167 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
168 dataLog(" Merging state for argument %zu.\n", argument
);
170 AbstractValue
& destination
= block
->valuesAtTail
.argument(argument
);
171 if (m_graph
.argumentIsCaptured(argument
)) {
172 if (!destination
.isTop()) {
173 destination
.makeTop();
177 changed
|= mergeStateAtTail(destination
, m_variables
.argument(argument
), block
->variablesAtTail
.argument(argument
));
180 for (size_t local
= 0; local
< block
->variablesAtTail
.numberOfLocals(); ++local
) {
181 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
182 dataLog(" Merging state for local %zu.\n", local
);
184 AbstractValue
& destination
= block
->valuesAtTail
.local(local
);
185 if (m_graph
.localIsCaptured(local
)) {
186 if (!destination
.isTop()) {
187 destination
.makeTop();
191 changed
|= mergeStateAtTail(destination
, m_variables
.local(local
), block
->variablesAtTail
.local(local
));
195 ASSERT(mergeMode
!= DontMerge
|| !changed
);
199 if (mergeMode
!= MergeToSuccessors
)
202 return mergeToSuccessors(m_graph
, block
);
205 void AbstractState::reset()
211 bool AbstractState::execute(unsigned indexInBlock
)
213 PROFILE(FLAG_FOR_EXECUTION
);
217 NodeIndex nodeIndex
= m_block
->at(indexInBlock
);
218 Node
& node
= m_graph
[nodeIndex
];
220 if (!node
.shouldGenerate())
225 case WeakJSConstant
: {
226 JSValue value
= m_graph
.valueOfJSConstant(nodeIndex
);
227 // Have to be careful here! It's tempting to call set(value), but
228 // that would be wrong, since that would constitute a proof that this
229 // value will always have the same structure. The whole point of a value
230 // having a structure is that it may change in the future - for example
231 // between when we compile the code and when we run it.
232 forNode(nodeIndex
).set(predictionFromValue(value
));
237 if (m_graph
.isCaptured(node
.local()))
238 forNode(nodeIndex
).makeTop();
240 forNode(nodeIndex
) = m_variables
.operand(node
.local());
245 if (m_graph
.isCaptured(node
.local()))
248 if (node
.variableAccessData()->shouldUseDoubleFormat()) {
249 forNode(node
.child1()).filter(PredictNumber
);
250 m_variables
.operand(node
.local()).set(PredictDouble
);
254 PredictedType predictedType
= node
.variableAccessData()->argumentAwarePrediction();
255 if (isInt32Prediction(predictedType
))
256 forNode(node
.child1()).filter(PredictInt32
);
257 else if (isArrayPrediction(predictedType
))
258 forNode(node
.child1()).filter(PredictArray
);
259 else if (isBooleanPrediction(predictedType
))
260 forNode(node
.child1()).filter(PredictBoolean
);
262 m_variables
.operand(node
.local()) = forNode(node
.child1());
267 // Assert that the state of arguments has been set.
268 ASSERT(!m_block
->valuesAtHead
.operand(node
.local()).isClear());
277 forNode(node
.child1()).filter(PredictInt32
);
278 forNode(node
.child2()).filter(PredictInt32
);
279 forNode(nodeIndex
).set(PredictInt32
);
283 if (!node
.canSpeculateInteger())
284 forNode(nodeIndex
).set(PredictDouble
);
286 forNode(nodeIndex
).set(PredictInt32
);
290 forNode(node
.child1()).filter(PredictNumber
);
291 forNode(nodeIndex
).set(PredictInt32
);
295 if (m_graph
[node
.child1()].shouldSpeculateInteger())
296 forNode(node
.child1()).filter(PredictInt32
);
297 else if (m_graph
[node
.child1()].shouldSpeculateNumber())
298 forNode(node
.child1()).filter(PredictNumber
);
299 else if (m_graph
[node
.child1()].shouldSpeculateBoolean())
300 forNode(node
.child1()).filter(PredictBoolean
);
302 forNode(nodeIndex
).set(PredictInt32
);
306 forNode(node
.child1()).filter(PredictNumber
);
307 forNode(nodeIndex
).set(PredictDouble
);
311 forNode(node
.child1()).filter(PredictNumber
);
316 if (m_graph
.addShouldSpeculateInteger(node
)) {
317 forNode(node
.child1()).filter(PredictInt32
);
318 forNode(node
.child2()).filter(PredictInt32
);
319 forNode(nodeIndex
).set(PredictInt32
);
322 if (Node::shouldSpeculateNumber(m_graph
[node
.child1()], m_graph
[node
.child2()])) {
323 forNode(node
.child1()).filter(PredictNumber
);
324 forNode(node
.child2()).filter(PredictNumber
);
325 forNode(nodeIndex
).set(PredictDouble
);
328 if (node
.op() == ValueAdd
) {
329 clobberStructures(indexInBlock
);
330 forNode(nodeIndex
).set(PredictString
| PredictInt32
| PredictNumber
);
333 // We don't handle this yet. :-(
339 if (m_graph
.addShouldSpeculateInteger(node
)) {
340 forNode(node
.child1()).filter(PredictInt32
);
341 forNode(node
.child2()).filter(PredictInt32
);
342 forNode(nodeIndex
).set(PredictInt32
);
345 forNode(node
.child1()).filter(PredictNumber
);
346 forNode(node
.child2()).filter(PredictNumber
);
347 forNode(nodeIndex
).set(PredictDouble
);
352 if (m_graph
.negateShouldSpeculateInteger(node
)) {
353 forNode(node
.child1()).filter(PredictInt32
);
354 forNode(nodeIndex
).set(PredictInt32
);
357 forNode(node
.child1()).filter(PredictNumber
);
358 forNode(nodeIndex
).set(PredictDouble
);
367 if (Node::shouldSpeculateInteger(m_graph
[node
.child1()], m_graph
[node
.child2()]) && node
.canSpeculateInteger()) {
368 forNode(node
.child1()).filter(PredictInt32
);
369 forNode(node
.child2()).filter(PredictInt32
);
370 forNode(nodeIndex
).set(PredictInt32
);
373 forNode(node
.child1()).filter(PredictNumber
);
374 forNode(node
.child2()).filter(PredictNumber
);
375 forNode(nodeIndex
).set(PredictDouble
);
380 if (m_graph
[node
.child1()].shouldSpeculateInteger() && node
.canSpeculateInteger()) {
381 forNode(node
.child1()).filter(PredictInt32
);
382 forNode(nodeIndex
).set(PredictInt32
);
385 forNode(node
.child1()).filter(PredictNumber
);
386 forNode(nodeIndex
).set(PredictDouble
);
390 forNode(node
.child1()).filter(PredictNumber
);
391 forNode(nodeIndex
).set(PredictDouble
);
395 Node
& child
= m_graph
[node
.child1()];
396 if (isBooleanPrediction(child
.prediction()))
397 forNode(node
.child1()).filter(PredictBoolean
);
398 else if (child
.shouldSpeculateFinalObjectOrOther())
399 forNode(node
.child1()).filter(PredictFinalObject
| PredictOther
);
400 else if (child
.shouldSpeculateArrayOrOther())
401 forNode(node
.child1()).filter(PredictArray
| PredictOther
);
402 else if (child
.shouldSpeculateInteger())
403 forNode(node
.child1()).filter(PredictInt32
);
404 else if (child
.shouldSpeculateNumber())
405 forNode(node
.child1()).filter(PredictNumber
);
407 clobberStructures(indexInBlock
);
408 forNode(nodeIndex
).set(PredictBoolean
);
418 forNode(nodeIndex
).set(PredictBoolean
);
425 case CompareGreaterEq
:
427 forNode(nodeIndex
).set(PredictBoolean
);
429 Node
& left
= m_graph
[node
.child1()];
430 Node
& right
= m_graph
[node
.child2()];
431 PredictedType filter
;
432 if (Node::shouldSpeculateInteger(left
, right
))
433 filter
= PredictInt32
;
434 else if (Node::shouldSpeculateNumber(left
, right
))
435 filter
= PredictNumber
;
436 else if (node
.op() == CompareEq
) {
437 if ((m_graph
.isConstant(node
.child1().index())
438 && m_graph
.valueOfJSConstant(node
.child1().index()).isNull())
439 || (m_graph
.isConstant(node
.child2().index())
440 && m_graph
.valueOfJSConstant(node
.child2().index()).isNull())) {
441 // We know that this won't clobber the world. But that's all we know.
445 if (Node::shouldSpeculateFinalObject(left
, right
))
446 filter
= PredictFinalObject
;
447 else if (Node::shouldSpeculateArray(left
, right
))
448 filter
= PredictArray
;
449 else if (left
.shouldSpeculateFinalObject() && right
.shouldSpeculateFinalObjectOrOther()) {
450 forNode(node
.child1()).filter(PredictFinalObject
);
451 forNode(node
.child2()).filter(PredictFinalObject
| PredictOther
);
453 } else if (right
.shouldSpeculateFinalObject() && left
.shouldSpeculateFinalObjectOrOther()) {
454 forNode(node
.child1()).filter(PredictFinalObject
| PredictOther
);
455 forNode(node
.child2()).filter(PredictFinalObject
);
457 } else if (left
.shouldSpeculateArray() && right
.shouldSpeculateArrayOrOther()) {
458 forNode(node
.child1()).filter(PredictFinalObject
);
459 forNode(node
.child2()).filter(PredictFinalObject
| PredictOther
);
461 } else if (right
.shouldSpeculateArray() && left
.shouldSpeculateArrayOrOther()) {
462 forNode(node
.child1()).filter(PredictFinalObject
| PredictOther
);
463 forNode(node
.child2()).filter(PredictFinalObject
);
467 clobberStructures(indexInBlock
);
471 clobberStructures(indexInBlock
);
473 forNode(node
.child1()).filter(filter
);
474 forNode(node
.child2()).filter(filter
);
478 case CompareStrictEq
:
479 forNode(nodeIndex
).set(PredictBoolean
);
482 case StringCharCodeAt
:
483 forNode(node
.child1()).filter(PredictString
);
484 forNode(node
.child2()).filter(PredictInt32
);
485 forNode(nodeIndex
).set(PredictInt32
);
489 forNode(node
.child1()).filter(PredictString
);
490 forNode(node
.child2()).filter(PredictInt32
);
491 forNode(nodeIndex
).set(PredictString
);
495 if (!node
.prediction() || !m_graph
[node
.child1()].prediction() || !m_graph
[node
.child2()].prediction()) {
499 if (!isActionableArrayPrediction(m_graph
[node
.child1()].prediction()) || !m_graph
[node
.child2()].shouldSpeculateInteger()) {
500 clobberStructures(indexInBlock
);
501 forNode(nodeIndex
).makeTop();
504 if (m_graph
[node
.child1()].prediction() == PredictString
) {
505 forNode(node
.child1()).filter(PredictString
);
506 forNode(node
.child2()).filter(PredictInt32
);
507 forNode(nodeIndex
).set(PredictString
);
511 if (m_graph
[node
.child1()].shouldSpeculateInt8Array()) {
512 forNode(node
.child1()).filter(PredictInt8Array
);
513 forNode(node
.child2()).filter(PredictInt32
);
514 forNode(nodeIndex
).set(PredictInt32
);
517 if (m_graph
[node
.child1()].shouldSpeculateInt16Array()) {
518 forNode(node
.child1()).filter(PredictInt16Array
);
519 forNode(node
.child2()).filter(PredictInt32
);
520 forNode(nodeIndex
).set(PredictInt32
);
523 if (m_graph
[node
.child1()].shouldSpeculateInt32Array()) {
524 forNode(node
.child1()).filter(PredictInt32Array
);
525 forNode(node
.child2()).filter(PredictInt32
);
526 forNode(nodeIndex
).set(PredictInt32
);
529 if (m_graph
[node
.child1()].shouldSpeculateUint8Array()) {
530 forNode(node
.child1()).filter(PredictUint8Array
);
531 forNode(node
.child2()).filter(PredictInt32
);
532 forNode(nodeIndex
).set(PredictInt32
);
535 if (m_graph
[node
.child1()].shouldSpeculateUint8ClampedArray()) {
536 forNode(node
.child1()).filter(PredictUint8ClampedArray
);
537 forNode(node
.child2()).filter(PredictInt32
);
538 forNode(nodeIndex
).set(PredictInt32
);
541 if (m_graph
[node
.child1()].shouldSpeculateUint16Array()) {
542 forNode(node
.child1()).filter(PredictUint16Array
);
543 forNode(node
.child2()).filter(PredictInt32
);
544 forNode(nodeIndex
).set(PredictInt32
);
547 if (m_graph
[node
.child1()].shouldSpeculateUint32Array()) {
548 forNode(node
.child1()).filter(PredictUint32Array
);
549 forNode(node
.child2()).filter(PredictInt32
);
550 if (node
.shouldSpeculateInteger())
551 forNode(nodeIndex
).set(PredictInt32
);
553 forNode(nodeIndex
).set(PredictDouble
);
556 if (m_graph
[node
.child1()].shouldSpeculateFloat32Array()) {
557 forNode(node
.child1()).filter(PredictFloat32Array
);
558 forNode(node
.child2()).filter(PredictInt32
);
559 forNode(nodeIndex
).set(PredictDouble
);
562 if (m_graph
[node
.child1()].shouldSpeculateFloat64Array()) {
563 forNode(node
.child1()).filter(PredictFloat64Array
);
564 forNode(node
.child2()).filter(PredictInt32
);
565 forNode(nodeIndex
).set(PredictDouble
);
568 ASSERT(m_graph
[node
.child1()].shouldSpeculateArray());
569 forNode(node
.child1()).filter(PredictArray
);
570 forNode(node
.child2()).filter(PredictInt32
);
571 forNode(nodeIndex
).makeTop();
576 case PutByValAlias
: {
577 if (!m_graph
[node
.child1()].prediction() || !m_graph
[node
.child2()].prediction()) {
581 if (!m_graph
[node
.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph
[node
.child1()].prediction())) {
582 ASSERT(node
.op() == PutByVal
);
583 clobberStructures(indexInBlock
);
584 forNode(nodeIndex
).makeTop();
588 if (m_graph
[node
.child1()].shouldSpeculateInt8Array()) {
589 forNode(node
.child1()).filter(PredictInt8Array
);
590 forNode(node
.child2()).filter(PredictInt32
);
591 if (m_graph
[node
.child3()].shouldSpeculateInteger())
592 forNode(node
.child3()).filter(PredictInt32
);
594 forNode(node
.child3()).filter(PredictNumber
);
597 if (m_graph
[node
.child1()].shouldSpeculateInt16Array()) {
598 forNode(node
.child1()).filter(PredictInt16Array
);
599 forNode(node
.child2()).filter(PredictInt32
);
600 if (m_graph
[node
.child3()].shouldSpeculateInteger())
601 forNode(node
.child3()).filter(PredictInt32
);
603 forNode(node
.child3()).filter(PredictNumber
);
606 if (m_graph
[node
.child1()].shouldSpeculateInt32Array()) {
607 forNode(node
.child1()).filter(PredictInt32Array
);
608 forNode(node
.child2()).filter(PredictInt32
);
609 if (m_graph
[node
.child3()].shouldSpeculateInteger())
610 forNode(node
.child3()).filter(PredictInt32
);
612 forNode(node
.child3()).filter(PredictNumber
);
615 if (m_graph
[node
.child1()].shouldSpeculateUint8Array()) {
616 forNode(node
.child1()).filter(PredictUint8Array
);
617 forNode(node
.child2()).filter(PredictInt32
);
618 if (m_graph
[node
.child3()].shouldSpeculateInteger())
619 forNode(node
.child3()).filter(PredictInt32
);
621 forNode(node
.child3()).filter(PredictNumber
);
624 if (m_graph
[node
.child1()].shouldSpeculateUint8ClampedArray()) {
625 forNode(node
.child1()).filter(PredictUint8ClampedArray
);
626 forNode(node
.child2()).filter(PredictInt32
);
627 if (m_graph
[node
.child3()].shouldSpeculateInteger())
628 forNode(node
.child3()).filter(PredictInt32
);
630 forNode(node
.child3()).filter(PredictNumber
);
633 if (m_graph
[node
.child1()].shouldSpeculateUint16Array()) {
634 forNode(node
.child1()).filter(PredictUint16Array
);
635 forNode(node
.child2()).filter(PredictInt32
);
636 if (m_graph
[node
.child3()].shouldSpeculateInteger())
637 forNode(node
.child3()).filter(PredictInt32
);
639 forNode(node
.child3()).filter(PredictNumber
);
642 if (m_graph
[node
.child1()].shouldSpeculateUint32Array()) {
643 forNode(node
.child1()).filter(PredictUint32Array
);
644 forNode(node
.child2()).filter(PredictInt32
);
645 if (m_graph
[node
.child3()].shouldSpeculateInteger())
646 forNode(node
.child3()).filter(PredictInt32
);
648 forNode(node
.child3()).filter(PredictNumber
);
651 if (m_graph
[node
.child1()].shouldSpeculateFloat32Array()) {
652 forNode(node
.child1()).filter(PredictFloat32Array
);
653 forNode(node
.child2()).filter(PredictInt32
);
654 forNode(node
.child3()).filter(PredictNumber
);
657 if (m_graph
[node
.child1()].shouldSpeculateFloat64Array()) {
658 forNode(node
.child1()).filter(PredictFloat64Array
);
659 forNode(node
.child2()).filter(PredictInt32
);
660 forNode(node
.child3()).filter(PredictNumber
);
663 ASSERT(m_graph
[node
.child1()].shouldSpeculateArray());
664 forNode(node
.child1()).filter(PredictArray
);
665 forNode(node
.child2()).filter(PredictInt32
);
670 forNode(node
.child1()).filter(PredictArray
);
671 forNode(nodeIndex
).set(PredictNumber
);
675 forNode(node
.child1()).filter(PredictArray
);
676 forNode(nodeIndex
).makeTop();
681 forNode(node
.child1()).filter(PredictCell
);
682 forNode(node
.child2()).filter(PredictCell
);
683 forNode(nodeIndex
).makeTop();
690 // There is probably profit to be found in doing sparse conditional constant
691 // propagation, and to take it one step further, where a variable's value
692 // is specialized on each direction of a branch. For now, we don't do this.
693 Node
& child
= m_graph
[node
.child1()];
694 if (child
.shouldSpeculateBoolean())
695 forNode(node
.child1()).filter(PredictBoolean
);
696 else if (child
.shouldSpeculateFinalObjectOrOther())
697 forNode(node
.child1()).filter(PredictFinalObject
| PredictOther
);
698 else if (child
.shouldSpeculateArrayOrOther())
699 forNode(node
.child1()).filter(PredictArray
| PredictOther
);
700 else if (child
.shouldSpeculateInteger())
701 forNode(node
.child1()).filter(PredictInt32
);
702 else if (child
.shouldSpeculateNumber())
703 forNode(node
.child1()).filter(PredictNumber
);
709 case ThrowReferenceError
:
714 Node
& child
= m_graph
[node
.child1()];
715 if (child
.shouldSpeculateInteger()) {
716 forNode(node
.child1()).filter(PredictInt32
);
717 forNode(nodeIndex
).set(PredictInt32
);
721 AbstractValue
& source
= forNode(node
.child1());
722 AbstractValue
& destination
= forNode(nodeIndex
);
724 PredictedType type
= source
.m_type
;
725 if (type
& ~(PredictNumber
| PredictString
| PredictBoolean
)) {
726 type
&= (PredictNumber
| PredictString
| PredictBoolean
);
727 type
|= PredictString
;
729 destination
.set(type
);
734 forNode(nodeIndex
).set(PredictString
);
739 forNode(nodeIndex
).set(m_codeBlock
->globalObject()->arrayStructure());
740 m_haveStructures
= true;
744 forNode(nodeIndex
).set(m_codeBlock
->globalObject()->regExpStructure());
745 m_haveStructures
= true;
749 Node
& child
= m_graph
[node
.child1()];
750 AbstractValue
& source
= forNode(node
.child1());
751 AbstractValue
& destination
= forNode(nodeIndex
);
753 if (isObjectPrediction(source
.m_type
)) {
754 // This is the simple case. We already know that the source is an
755 // object, so there's nothing to do. I don't think this case will
756 // be hit, but then again, you never know.
757 destination
= source
;
761 if (isOtherPrediction(child
.prediction())) {
762 source
.filter(PredictOther
);
763 destination
.set(PredictObjectOther
);
767 if (isObjectPrediction(child
.prediction())) {
768 source
.filter(PredictObjectMask
);
769 destination
= source
;
773 destination
= source
;
774 destination
.merge(PredictObjectOther
);
779 Node
& child
= m_graph
[node
.child1()];
780 AbstractValue
& source
= forNode(node
.child1());
781 AbstractValue
& destination
= forNode(nodeIndex
);
783 if (child
.shouldSpeculateFinalObject())
784 source
.filter(PredictFinalObject
);
786 destination
.set(PredictFinalObject
);
791 forNode(nodeIndex
).set(m_codeBlock
->globalObjectFor(node
.codeOrigin
)->emptyObjectStructure());
792 m_haveStructures
= true;
795 case CreateActivation
:
796 forNode(nodeIndex
).set(m_graph
.m_globalData
.activationStructure
.get());
797 m_haveStructures
= true;
800 case TearOffActivation
:
801 // Does nothing that is user-visible.
805 case NewFunctionExpression
:
806 case NewFunctionNoCheck
:
807 forNode(nodeIndex
).set(m_codeBlock
->globalObjectFor(node
.codeOrigin
)->functionStructure());
811 forNode(nodeIndex
).set(PredictFunction
);
815 forNode(nodeIndex
).set(PredictCellOther
);
819 forNode(nodeIndex
).makeTop();
823 clobberStructures(indexInBlock
);
828 if (!node
.prediction()) {
832 if (isCellPrediction(m_graph
[node
.child1()].prediction()))
833 forNode(node
.child1()).filter(PredictCell
);
834 clobberStructures(indexInBlock
);
835 forNode(nodeIndex
).makeTop();
839 forNode(node
.child1()).filter(PredictArray
);
840 forNode(nodeIndex
).set(PredictInt32
);
843 case GetStringLength
:
844 forNode(node
.child1()).filter(PredictString
);
845 forNode(nodeIndex
).set(PredictInt32
);
848 case GetInt8ArrayLength
:
849 forNode(node
.child1()).filter(PredictInt8Array
);
850 forNode(nodeIndex
).set(PredictInt32
);
852 case GetInt16ArrayLength
:
853 forNode(node
.child1()).filter(PredictInt16Array
);
854 forNode(nodeIndex
).set(PredictInt32
);
856 case GetInt32ArrayLength
:
857 forNode(node
.child1()).filter(PredictInt32Array
);
858 forNode(nodeIndex
).set(PredictInt32
);
860 case GetUint8ArrayLength
:
861 forNode(node
.child1()).filter(PredictUint8Array
);
862 forNode(nodeIndex
).set(PredictInt32
);
864 case GetUint8ClampedArrayLength
:
865 forNode(node
.child1()).filter(PredictUint8ClampedArray
);
866 forNode(nodeIndex
).set(PredictInt32
);
868 case GetUint16ArrayLength
:
869 forNode(node
.child1()).filter(PredictUint16Array
);
870 forNode(nodeIndex
).set(PredictInt32
);
872 case GetUint32ArrayLength
:
873 forNode(node
.child1()).filter(PredictUint32Array
);
874 forNode(nodeIndex
).set(PredictInt32
);
876 case GetFloat32ArrayLength
:
877 forNode(node
.child1()).filter(PredictFloat32Array
);
878 forNode(nodeIndex
).set(PredictInt32
);
880 case GetFloat64ArrayLength
:
881 forNode(node
.child1()).filter(PredictFloat64Array
);
882 forNode(nodeIndex
).set(PredictInt32
);
886 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
887 forNode(node
.child1()).filter(node
.structureSet());
888 m_haveStructures
= true;
892 clobberStructures(indexInBlock
);
893 forNode(node
.child1()).set(node
.structureTransitionData().newStructure
);
894 m_haveStructures
= true;
896 case GetPropertyStorage
:
897 forNode(node
.child1()).filter(PredictCell
);
898 forNode(nodeIndex
).clear(); // The result is not a JS value.
900 case GetIndexedPropertyStorage
: {
901 PredictedType basePrediction
= m_graph
[node
.child2()].prediction();
902 if (!(basePrediction
& PredictInt32
) && basePrediction
) {
903 forNode(nodeIndex
).clear();
906 if (m_graph
[node
.child1()].prediction() == PredictString
) {
907 forNode(node
.child1()).filter(PredictString
);
908 forNode(nodeIndex
).clear();
912 if (m_graph
[node
.child1()].shouldSpeculateInt8Array()) {
913 forNode(node
.child1()).filter(PredictInt8Array
);
914 forNode(nodeIndex
).clear();
917 if (m_graph
[node
.child1()].shouldSpeculateInt16Array()) {
918 forNode(node
.child1()).filter(PredictInt16Array
);
919 forNode(nodeIndex
).clear();
922 if (m_graph
[node
.child1()].shouldSpeculateInt32Array()) {
923 forNode(node
.child1()).filter(PredictInt32Array
);
924 forNode(nodeIndex
).clear();
927 if (m_graph
[node
.child1()].shouldSpeculateUint8Array()) {
928 forNode(node
.child1()).filter(PredictUint8Array
);
929 forNode(nodeIndex
).clear();
932 if (m_graph
[node
.child1()].shouldSpeculateUint8ClampedArray()) {
933 forNode(node
.child1()).filter(PredictUint8ClampedArray
);
934 forNode(nodeIndex
).clear();
937 if (m_graph
[node
.child1()].shouldSpeculateUint16Array()) {
938 forNode(node
.child1()).filter(PredictUint16Array
);
939 forNode(nodeIndex
).set(PredictOther
);
942 if (m_graph
[node
.child1()].shouldSpeculateUint32Array()) {
943 forNode(node
.child1()).filter(PredictUint32Array
);
944 forNode(nodeIndex
).clear();
947 if (m_graph
[node
.child1()].shouldSpeculateFloat32Array()) {
948 forNode(node
.child1()).filter(PredictFloat32Array
);
949 forNode(nodeIndex
).clear();
952 if (m_graph
[node
.child1()].shouldSpeculateFloat64Array()) {
953 forNode(node
.child1()).filter(PredictFloat64Array
);
954 forNode(nodeIndex
).clear();
957 forNode(node
.child1()).filter(PredictArray
);
958 forNode(nodeIndex
).clear();
962 forNode(node
.child1()).filter(PredictCell
);
963 forNode(nodeIndex
).makeTop();
967 forNode(node
.child1()).filter(PredictCell
);
971 forNode(node
.child1()).filter(PredictFunction
);
972 // FIXME: Should be able to propagate the fact that we know what the function is.
977 forNode(node
.child1()).filter(PredictCell
);
978 clobberStructures(indexInBlock
);
982 forNode(nodeIndex
).makeTop();
988 case CheckHasInstance
:
989 forNode(node
.child1()).filter(PredictCell
);
990 // Sadly, we don't propagate the fact that we've done CheckHasInstance
994 // Again, sadly, we don't propagate the fact that we've done InstanceOf
995 if (!(m_graph
[node
.child1()].prediction() & ~PredictCell
) && !(forNode(node
.child1()).m_type
& ~PredictCell
))
996 forNode(node
.child1()).filter(PredictCell
);
997 forNode(node
.child3()).filter(PredictCell
);
998 forNode(nodeIndex
).set(PredictBoolean
);
1012 case ResolveBaseStrictPut
:
1014 clobberStructures(indexInBlock
);
1015 forNode(nodeIndex
).makeTop();
1028 ASSERT_NOT_REACHED();
1035 inline void AbstractState::clobberStructures(unsigned indexInBlock
)
1037 PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING
);
1038 if (!m_haveStructures
)
1040 for (size_t i
= indexInBlock
+ 1; i
--;)
1041 forNode(m_block
->at(i
)).clobberStructures();
1042 for (size_t i
= 0; i
< m_variables
.numberOfArguments(); ++i
)
1043 m_variables
.argument(i
).clobberStructures();
1044 for (size_t i
= 0; i
< m_variables
.numberOfLocals(); ++i
)
1045 m_variables
.local(i
).clobberStructures();
1046 m_haveStructures
= false;
1049 inline bool AbstractState::mergeStateAtTail(AbstractValue
& destination
, AbstractValue
& inVariable
, NodeIndex nodeIndex
)
1051 if (nodeIndex
== NoNode
)
1054 AbstractValue source
;
1056 Node
& node
= m_graph
[nodeIndex
];
1057 if (!node
.refCount())
1060 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1061 dataLog(" It's live, node @%u.\n", nodeIndex
);
1064 switch (node
.op()) {
1068 // The block transfers the value from head to tail.
1069 source
= inVariable
;
1070 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1071 dataLog(" Transfering from head to tail.\n");
1076 // The block refines the value with additional speculations.
1077 source
= forNode(nodeIndex
);
1078 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1079 dataLog(" Refining.\n");
1084 // The block sets the variable, and potentially refines it, both
1085 // before and after setting it.
1086 if (node
.variableAccessData()->shouldUseDoubleFormat())
1087 source
.set(PredictDouble
);
1089 source
= forNode(node
.child1());
1090 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1091 dataLog(" Setting.\n");
1096 ASSERT_NOT_REACHED();
1100 if (destination
== source
) {
1101 // Abstract execution did not change the output value of the variable, for this
1102 // basic block, on this iteration.
1103 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1104 dataLog(" Not changed!\n");
1109 // Abstract execution reached a new conclusion about the speculations reached about
1110 // this variable after execution of this basic block. Update the state, and return
1111 // true to indicate that the fixpoint must go on!
1112 destination
= source
;
1113 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
1114 dataLog(" Changed!\n");
1119 inline bool AbstractState::merge(BasicBlock
* from
, BasicBlock
* to
)
1121 ASSERT(from
->variablesAtTail
.numberOfArguments() == to
->variablesAtHead
.numberOfArguments());
1122 ASSERT(from
->variablesAtTail
.numberOfLocals() == to
->variablesAtHead
.numberOfLocals());
1124 bool changed
= false;
1126 for (size_t argument
= 0; argument
< from
->variablesAtTail
.numberOfArguments(); ++argument
) {
1127 AbstractValue
& destination
= to
->valuesAtHead
.argument(argument
);
1128 if (m_graph
.argumentIsCaptured(argument
)) {
1129 if (destination
.isTop())
1131 destination
.makeTop();
1135 changed
|= mergeVariableBetweenBlocks(destination
, from
->valuesAtTail
.argument(argument
), to
->variablesAtHead
.argument(argument
), from
->variablesAtTail
.argument(argument
));
1138 for (size_t local
= 0; local
< from
->variablesAtTail
.numberOfLocals(); ++local
) {
1139 AbstractValue
& destination
= to
->valuesAtHead
.local(local
);
1140 if (m_graph
.localIsCaptured(local
)) {
1141 if (destination
.isTop())
1143 destination
.makeTop();
1147 changed
|= mergeVariableBetweenBlocks(destination
, from
->valuesAtTail
.local(local
), to
->variablesAtHead
.local(local
), from
->variablesAtTail
.local(local
));
1150 if (!to
->cfaHasVisited
)
1153 to
->cfaShouldRevisit
|= changed
;
1158 inline bool AbstractState::mergeToSuccessors(Graph
& graph
, BasicBlock
* basicBlock
)
1160 PROFILE(FLAG_FOR_MERGE_TO_SUCCESSORS
);
1162 Node
& terminal
= graph
[basicBlock
->last()];
1164 ASSERT(terminal
.isTerminal());
1166 switch (terminal
.op()) {
1168 return merge(basicBlock
, graph
.m_blocks
[terminal
.takenBlockIndex()].get());
1171 return merge(basicBlock
, graph
.m_blocks
[terminal
.takenBlockIndex()].get())
1172 | merge(basicBlock
, graph
.m_blocks
[terminal
.notTakenBlockIndex()].get());
1176 case ThrowReferenceError
:
1180 ASSERT_NOT_REACHED();
1185 inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue
& destination
, AbstractValue
& source
, NodeIndex destinationNodeIndex
, NodeIndex sourceNodeIndex
)
1187 if (destinationNodeIndex
== NoNode
)
1190 ASSERT_UNUSED(sourceNodeIndex
, sourceNodeIndex
!= NoNode
);
1192 // FIXME: We could do some sparse conditional propagation here!
1194 return destination
.merge(source
);
1198 void AbstractState::dump(FILE* out
)
1201 for (size_t i
= 0; i
< m_block
->size(); ++i
) {
1202 NodeIndex index
= m_block
->at(i
);
1203 AbstractValue
& value
= m_nodes
[index
];
1204 if (value
.isClear())
1210 fprintf(out
, "@%lu:", static_cast<unsigned long>(index
));
1216 } } // namespace JSC::DFG
1218 #endif // ENABLE(DFG_JIT)