blob: 329db611e852fbe136a8b46b401dabf4c4254150 [file] [log] [blame]
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +00001/*
2 * Copyright (C) 2011 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#include "config.h"
27#include "DFGAbstractState.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "CodeBlock.h"
32#include "DFGBasicBlock.h"
33
34namespace JSC { namespace DFG {
35
36#define CFA_PROFILING 0
37
38#if CFA_PROFILING
39#define PROFILE(flag) SamplingFlags::ScopedFlag scopedFlag(flag)
40#else
41#define PROFILE(flag) do { } while (false)
42#endif
43
44// Profiling flags
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
50
51AbstractState::AbstractState(CodeBlock* codeBlock, Graph& graph)
52 : m_codeBlock(codeBlock)
53 , m_graph(graph)
54 , m_variables(codeBlock->m_numParameters, graph.m_localVars)
55 , m_block(0)
56{
57 size_t maxBlockSize = 0;
58 for (size_t i = 0; i < graph.m_blocks.size(); ++i) {
59 BasicBlock* block = graph.m_blocks[i].get();
60 if (block->end - block->begin > maxBlockSize)
61 maxBlockSize = block->end - block->begin;
62 }
63 m_nodes.resize(maxBlockSize);
64}
65
66AbstractState::~AbstractState() { }
67
68void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
69{
70 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
71
72 ASSERT(!m_block);
73
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000074 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
75 ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
76 ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
77
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +000078 for (size_t i = 0; i < basicBlock->end - basicBlock->begin; ++i)
79 m_nodes[i].clear();
80 m_variables = basicBlock->valuesAtHead;
81 m_haveStructures = false;
82 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
83 if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
84 m_haveStructures = true;
85 break;
86 }
87 }
88 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
89 if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
90 m_haveStructures = true;
91 break;
92 }
93 }
94
95 basicBlock->cfaShouldRevisit = false;
96 basicBlock->cfaHasVisited = true;
97 m_block = basicBlock;
98 m_isValid = true;
99}
100
101void AbstractState::initialize(Graph& graph)
102{
103 PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
104 BasicBlock* root = graph.m_blocks[0].get();
105 root->cfaShouldRevisit = true;
106 for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
107 PredictedType prediction = graph[root->variablesAtHead.argument(i)].variableAccessData()->prediction();
108 if (isInt32Prediction(prediction))
109 root->valuesAtHead.argument(i).set(PredictInt32);
110 else if (isArrayPrediction(prediction))
111 root->valuesAtHead.argument(i).set(PredictArray);
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000112 else if (isByteArrayPrediction(prediction))
113 root->valuesAtHead.argument(i).set(PredictByteArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000114 else if (isBooleanPrediction(prediction))
115 root->valuesAtHead.argument(i).set(PredictBoolean);
116 else
117 root->valuesAtHead.argument(i).makeTop();
118 }
119}
120
121bool AbstractState::endBasicBlock(MergeMode mergeMode)
122{
123 PROFILE(FLAG_FOR_BLOCK_END);
124 ASSERT(m_block);
125
126 BasicBlock* block = m_block; // Save the block for successor merging.
127
128 if (!m_isValid) {
129 reset();
130 return false;
131 }
132
133 bool changed = false;
134
135 if (mergeMode != DontMerge || !ASSERT_DISABLED) {
136 for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument)
137 changed |= mergeStateAtTail(block->valuesAtTail.argument(argument), m_variables.argument(argument), block->variablesAtTail.argument(argument));
138
139 for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local)
140 changed |= mergeStateAtTail(block->valuesAtTail.local(local), m_variables.local(local), block->variablesAtTail.local(local));
141 }
142
143 ASSERT(mergeMode != DontMerge || !changed);
144
145 reset();
146
147 if (mergeMode != MergeToSuccessors)
148 return changed;
149
150 return mergeToSuccessors(m_graph, block);
151}
152
153void AbstractState::reset()
154{
155 m_block = 0;
156 m_isValid = false;
157}
158
159bool AbstractState::execute(NodeIndex nodeIndex)
160{
161 PROFILE(FLAG_FOR_EXECUTION);
162 ASSERT(m_block);
163 ASSERT(m_isValid);
164
165 Node& node = m_graph[nodeIndex];
166
167 if (!node.shouldGenerate())
168 return true;
169
170 switch (node.op) {
171 case JSConstant: {
172 JSValue value = m_graph.valueOfJSConstant(m_codeBlock, nodeIndex);
173 if (value.isCell())
174 m_haveStructures = true;
175 forNode(nodeIndex).set(value);
176 break;
177 }
178
179 case GetLocal: {
180 forNode(nodeIndex) = m_variables.operand(node.local());
181 break;
182 }
183
184 case SetLocal: {
185 PredictedType predictedType = node.variableAccessData()->prediction();
186 if (isInt32Prediction(predictedType))
187 forNode(node.child1()).filter(PredictInt32);
188 else if (isArrayPrediction(predictedType))
189 forNode(node.child1()).filter(PredictArray);
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000190 else if (isByteArrayPrediction(predictedType))
191 forNode(node.child1()).filter(PredictByteArray);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000192 else if (isBooleanPrediction(predictedType))
193 forNode(node.child1()).filter(PredictBoolean);
194
195 m_variables.operand(node.local()) = forNode(node.child1());
196 break;
197 }
198
199 case SetArgument:
200 // Assert that the state of arguments has been set.
201 ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
202 break;
203
204 case BitAnd:
205 case BitOr:
206 case BitXor:
207 case BitRShift:
208 case BitLShift:
209 case BitURShift:
210 forNode(node.child1()).filter(PredictInt32);
211 forNode(node.child2()).filter(PredictInt32);
212 forNode(nodeIndex).set(PredictInt32);
213 break;
214
215 case UInt32ToNumber:
216 if (!node.canSpeculateInteger())
217 forNode(nodeIndex).set(PredictDouble);
218 else
219 forNode(nodeIndex).set(PredictInt32);
220 break;
221
222 case ValueToInt32:
oliver@apple.com6b748682011-10-13 22:23:47 +0000223 if (!m_graph[node.child1()].shouldNotSpeculateInteger()) {
224 if (m_graph[node.child1()].shouldSpeculateDouble())
225 forNode(node.child1()).filter(PredictNumber);
226 else
227 forNode(node.child1()).filter(PredictInt32);
228 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000229 forNode(nodeIndex).set(PredictInt32);
230 break;
231
232 case ValueToNumber:
233 if (m_graph[node.child1()].shouldNotSpeculateInteger()) {
234 forNode(node.child1()).filter(PredictNumber);
235 forNode(nodeIndex).set(PredictDouble);
236 break;
237 }
238
239 forNode(node.child1()).filter(PredictInt32);
240 forNode(nodeIndex).set(PredictInt32);
241 break;
242
243 case ValueToDouble:
244 forNode(node.child1()).filter(PredictNumber);
245 forNode(nodeIndex).set(PredictDouble);
246 break;
247
248 case ValueAdd:
249 case ArithAdd: {
250 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) {
251 forNode(node.child1()).filter(PredictInt32);
252 forNode(node.child2()).filter(PredictInt32);
253 forNode(nodeIndex).set(PredictInt32);
254 break;
255 }
256 if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
257 forNode(node.child1()).filter(PredictNumber);
258 forNode(node.child2()).filter(PredictNumber);
259 forNode(nodeIndex).set(PredictDouble);
260 break;
261 }
262 ASSERT(node.op == ValueAdd);
263 clobberStructures(nodeIndex);
264 forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber);
265 break;
266 }
267
268 case ArithSub:
269 case ArithMul:
270 case ArithDiv:
271 case ArithMin:
272 case ArithMax: {
273 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) {
274 forNode(node.child1()).filter(PredictInt32);
275 forNode(node.child2()).filter(PredictInt32);
276 forNode(nodeIndex).set(PredictInt32);
277 break;
278 }
279 forNode(node.child1()).filter(PredictNumber);
280 forNode(node.child2()).filter(PredictNumber);
281 forNode(nodeIndex).set(PredictDouble);
282 break;
283 }
284
285 case ArithMod: {
286 if (m_graph[node.child1()].shouldNotSpeculateInteger() || m_graph[node.child2()].shouldNotSpeculateInteger() || !node.canSpeculateInteger()) {
287 forNode(node.child1()).filter(PredictNumber);
288 forNode(node.child2()).filter(PredictNumber);
289 forNode(nodeIndex).set(PredictDouble);
290 break;
291 }
292 forNode(node.child1()).filter(PredictInt32);
293 forNode(node.child2()).filter(PredictInt32);
294 forNode(nodeIndex).set(PredictInt32);
295 break;
296 }
297
298 case ArithAbs:
299 if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) {
300 forNode(node.child1()).filter(PredictInt32);
301 forNode(nodeIndex).set(PredictInt32);
302 break;
303 }
304 forNode(node.child1()).filter(PredictNumber);
305 forNode(nodeIndex).set(PredictDouble);
306 break;
307
308 case ArithSqrt:
309 forNode(node.child1()).filter(PredictNumber);
310 forNode(nodeIndex).set(PredictDouble);
311 break;
312
313 case LogicalNot: {
314 Node& child = m_graph[node.child1()];
315 if (isBooleanPrediction(child.prediction()) || !child.prediction())
316 forNode(node.child1()).filter(PredictBoolean);
317 else if (child.shouldSpeculateFinalObjectOrOther())
318 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
319 else if (child.shouldSpeculateArrayOrOther())
320 forNode(node.child1()).filter(PredictArray | PredictOther);
321 else if (child.shouldSpeculateInteger())
322 forNode(node.child1()).filter(PredictInt32);
323 else if (child.shouldSpeculateNumber())
324 forNode(node.child1()).filter(PredictNumber);
325 else
326 clobberStructures(nodeIndex);
327 forNode(nodeIndex).set(PredictBoolean);
328 break;
329 }
330
331 case CompareLess:
332 case CompareLessEq:
333 case CompareGreater:
334 case CompareGreaterEq:
335 case CompareEq: {
336 Node& left = m_graph[node.child1()];
337 Node& right = m_graph[node.child2()];
338 PredictedType filter;
339 if (Node::shouldSpeculateInteger(left, right))
340 filter = PredictInt32;
341 else if (Node::shouldSpeculateNumber(left, right))
342 filter = PredictNumber;
343 else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(left, right))
344 filter = PredictFinalObject;
345 else if (node.op == CompareEq && Node::shouldSpeculateArray(left, right))
346 filter = PredictArray;
347 else {
348 filter = PredictTop;
349 clobberStructures(nodeIndex);
350 }
351 forNode(node.child1()).filter(filter);
352 forNode(node.child2()).filter(filter);
353 forNode(nodeIndex).set(PredictBoolean);
354 break;
355 }
356
357 case CompareStrictEq:
358 forNode(nodeIndex).set(PredictBoolean);
359 break;
360
361 case StringCharCodeAt:
362 forNode(node.child1()).filter(PredictString);
363 forNode(node.child2()).filter(PredictInt32);
364 forNode(nodeIndex).set(PredictInt32);
365 break;
366
367 case StringCharAt:
368 forNode(node.child1()).filter(PredictString);
369 forNode(node.child2()).filter(PredictInt32);
370 forNode(nodeIndex).set(PredictString);
371 break;
372
373 case GetByVal: {
374 PredictedType indexPrediction = m_graph[node.child2()].prediction();
375 if (!(indexPrediction & PredictInt32) && indexPrediction) {
376 clobberStructures(nodeIndex);
377 forNode(nodeIndex).makeTop();
378 break;
379 }
380 if (m_graph[node.child1()].prediction() == PredictString) {
381 forNode(node.child1()).filter(PredictString);
382 forNode(node.child2()).filter(PredictInt32);
383 forNode(nodeIndex).set(PredictString);
384 break;
385 }
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000386 if (m_graph[node.child1()].shouldSpeculateByteArray()) {
387 forNode(node.child1()).filter(PredictByteArray);
388 forNode(node.child2()).filter(PredictInt32);
389 forNode(nodeIndex).set(PredictInt32);
390 break;
391 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000392 forNode(node.child1()).filter(PredictArray);
393 forNode(node.child2()).filter(PredictInt32);
394 forNode(nodeIndex).makeTop();
395 break;
396 }
397
398 case PutByVal:
399 case PutByValAlias: {
400 PredictedType indexPrediction = m_graph[node.child2()].prediction();
401 if (!(indexPrediction & PredictInt32) && indexPrediction) {
402 clobberStructures(nodeIndex);
403 forNode(nodeIndex).makeTop();
404 break;
405 }
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000406 if (m_graph[node.child1()].shouldSpeculateByteArray()) {
407 forNode(node.child1()).filter(PredictByteArray);
408 forNode(node.child2()).filter(PredictInt32);
409 forNode(node.child3()).filter(PredictNumber);
410 break;
411 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000412 forNode(node.child1()).filter(PredictArray);
413 forNode(node.child2()).filter(PredictInt32);
414 break;
415 }
416
417 case ArrayPush:
418 forNode(node.child1()).filter(PredictArray);
419 forNode(nodeIndex).set(PredictNumber);
420 break;
421
422 case ArrayPop:
423 forNode(node.child1()).filter(PredictArray);
424 forNode(nodeIndex).makeTop();
425 break;
426
427 case Jump:
428 break;
429
430 case Branch: {
431 // There is probably profit to be found in doing sparse conditional constant
432 // propagation, and to take it one step further, where a variable's value
433 // is specialized on each direction of a branch. For now, we don't do this.
434 Node& child = m_graph[node.child1()];
435 if (isBooleanPrediction(child.prediction()) || !child.prediction())
436 forNode(node.child1()).filter(PredictBoolean);
437 else if (child.shouldSpeculateFinalObjectOrOther())
438 forNode(node.child1()).filter(PredictFinalObject | PredictOther);
439 else if (child.shouldSpeculateArrayOrOther())
440 forNode(node.child1()).filter(PredictArray | PredictOther);
441 else if (child.shouldSpeculateInteger())
442 forNode(node.child1()).filter(PredictInt32);
443 else if (child.shouldSpeculateNumber())
444 forNode(node.child1()).filter(PredictNumber);
445 break;
446 }
447
448 case Return:
449 case Throw:
450 case ThrowReferenceError:
451 m_isValid = false;
452 break;
453
454 case ToPrimitive: {
455 Node& child = m_graph[node.child1()];
456 if (child.shouldSpeculateInteger()) {
457 forNode(node.child1()).filter(PredictInt32);
458 forNode(nodeIndex).set(PredictInt32);
459 break;
460 }
461
462 AbstractValue& source = forNode(node.child1());
463 AbstractValue& destination = forNode(nodeIndex);
464
465 PredictedType type = source.m_type;
466 if (type & ~(PredictNumber | PredictString | PredictBoolean)) {
467 type &= (PredictNumber | PredictString | PredictBoolean);
468 type |= PredictString;
469 }
470 destination.set(type);
471 break;
472 }
473
474 case StrCat:
475 forNode(nodeIndex).set(PredictString);
476 break;
477
478 case NewArray:
479 case NewArrayBuffer:
480 forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
481 m_haveStructures = true;
482 break;
483
484 case NewRegexp:
485 forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
486 m_haveStructures = true;
487 break;
488
489 case ConvertThis: {
490 Node& child = m_graph[node.child1()];
491 AbstractValue& source = forNode(node.child1());
492 AbstractValue& destination = forNode(nodeIndex);
493
494 if (isObjectPrediction(source.m_type)) {
495 // This is the simple case. We already know that the source is an
496 // object, so there's nothing to do. I don't think this case will
497 // be hit, but then again, you never know.
498 destination = source;
499 break;
500 }
501
502 if (isOtherPrediction(child.prediction())) {
503 source.filter(PredictOther);
504 destination.set(PredictObjectOther);
505 break;
506 }
507
508 if (isObjectPrediction(child.prediction())) {
509 source.filter(PredictObjectMask);
510 destination = source;
511 break;
512 }
513
514 destination = source;
515 destination.merge(PredictObjectOther);
516 break;
517 }
518
519 case CreateThis: {
520 Node& child = m_graph[node.child1()];
521 AbstractValue& source = forNode(node.child1());
522 AbstractValue& destination = forNode(nodeIndex);
523
524 if (child.shouldSpeculateFinalObject())
525 source.filter(PredictFinalObject);
526
527 destination.set(PredictFinalObject);
528 break;
529 }
530
531 case NewObject:
532 forNode(nodeIndex).set(m_codeBlock->globalObject()->emptyObjectStructure());
533 m_haveStructures = true;
534 break;
535
536 case GetCallee:
537 forNode(nodeIndex).set(PredictObjectOther);
538 break;
539
540 case GetScopeChain:
541 forNode(nodeIndex).set(PredictCellOther);
542 break;
543
544 case GetScopedVar:
545 forNode(nodeIndex).makeTop();
546 break;
547
548 case PutScopedVar:
549 clobberStructures(nodeIndex);
550 break;
551
552 case GetById:
553 case GetMethod:
fpizlo@apple.com49bfe572011-10-31 23:50:57 +0000554 if (!node.prediction()) {
555 m_isValid = false;
556 break;
557 }
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000558 forNode(node.child1()).filter(PredictCell);
559 clobberStructures(nodeIndex);
560 forNode(nodeIndex).makeTop();
561 break;
562
563 case GetArrayLength:
564 forNode(node.child1()).filter(PredictArray);
565 forNode(nodeIndex).set(PredictInt32);
566 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000567
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000568 case GetStringLength:
569 forNode(node.child1()).filter(PredictString);
570 forNode(nodeIndex).set(PredictInt32);
571 break;
oliver@apple.comf4596ca2011-10-19 21:25:10 +0000572
573 case GetByteArrayLength:
574 forNode(node.child1()).filter(PredictByteArray);
575 forNode(nodeIndex).set(PredictInt32);
576 break;
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000577
578 case CheckStructure:
579 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
580 forNode(node.child1()).filter(node.structureSet());
581 m_haveStructures = true;
582 break;
583
584 case PutStructure:
585 clobberStructures(nodeIndex);
586 forNode(node.child1()).set(node.structureTransitionData().newStructure);
587 m_haveStructures = true;
588 break;
589
590 case GetPropertyStorage:
591 forNode(node.child1()).filter(PredictCell);
592 forNode(nodeIndex).clear(); // The result is not a JS value.
593 break;
594
595 case GetByOffset:
596 forNode(node.child1()).filter(PredictCell);
597 forNode(nodeIndex).makeTop();
598 break;
599
600 case PutByOffset:
601 forNode(node.child1()).filter(PredictCell);
602 break;
603
604 case CheckMethod:
605 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
606 forNode(node.child1()).filter(m_graph.m_methodCheckData[node.methodCheckDataIndex()].structure);
fpizlo@apple.comd9fbf2f2011-10-24 03:58:03 +0000607 forNode(nodeIndex).set(PredictObjectOther);
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000608 m_haveStructures = true;
609 break;
610
611 case CheckFunction:
612 forNode(node.child1()).filter(PredictObjectOther);
613 // FIXME: Should be able to propagate the fact that we know what the function is.
614 break;
615
616 case PutById:
617 case PutByIdDirect:
618 forNode(node.child1()).filter(PredictCell);
619 clobberStructures(nodeIndex);
620 break;
621
622 case GetGlobalVar:
623 forNode(nodeIndex).makeTop();
624 break;
625
626 case PutGlobalVar:
627 break;
628
629 case CheckHasInstance:
630 forNode(node.child1()).filter(PredictCell);
631 // Sadly, we don't propagate the fact that we've done CheckHasInstance
632 break;
633
634 case InstanceOf:
635 // Again, sadly, we don't propagate the fact that we've done InstanceOf
636 forNode(node.child1()).filter(PredictCell);
637 forNode(node.child2()).filter(PredictCell);
638 break;
639
640 case Phi:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +0000641 case Flush:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000642 break;
643
644 case Breakpoint:
645 break;
646
647 case Call:
648 case Construct:
649 case Resolve:
650 case ResolveBase:
651 case ResolveBaseStrictPut:
652 case ResolveGlobal:
653 clobberStructures(nodeIndex);
654 forNode(nodeIndex).makeTop();
655 break;
656
657 case ForceOSRExit:
658 m_isValid = false;
659 break;
660
661 case Phantom:
662 break;
663 }
664
665 return m_isValid;
666}
667
668inline void AbstractState::clobberStructures(NodeIndex nodeIndex)
669{
670 PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING);
671 if (!m_haveStructures)
672 return;
673 for (size_t i = nodeIndex - m_block->begin + 1; i-- > 0;)
674 m_nodes[i].clobberStructures();
675 for (size_t i = 0; i < m_variables.numberOfArguments(); ++i)
676 m_variables.argument(i).clobberStructures();
677 for (size_t i = 0; i < m_variables.numberOfLocals(); ++i)
678 m_variables.local(i).clobberStructures();
679 m_haveStructures = false;
680}
681
682inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
683{
684 if (nodeIndex == NoNode)
685 return false;
686
687 AbstractValue* source;
688
689 Node& node = m_graph[nodeIndex];
690 if (!node.refCount())
691 return false;
692
693 switch (node.op) {
694 case Phi:
695 case SetArgument:
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +0000696 case Flush:
fpizlo@apple.com4ffd3952011-10-12 02:05:53 +0000697 // The block transfers the value from head to tail.
698 source = &inVariable;
699 break;
700
701 case GetLocal:
702 // The block refines the value with additional speculations.
703 source = &forNode(nodeIndex);
704 break;
705
706 case SetLocal:
707 // The block sets the variable, and potentially refines it, both
708 // before and after setting it.
709 source = &forNode(node.child1());
710 break;
711
712 default:
713 ASSERT_NOT_REACHED();
714 source = 0;
715 break;
716 }
717
718 if (destination == *source) {
719 // Abstract execution did not change the output value of the variable, for this
720 // basic block, on this iteration.
721 return false;
722 }
723
724 // Abstract execution reached a new conclusion about the speculations reached about
725 // this variable after execution of this basic block. Update the state, and return
726 // true to indicate that the fixpoint must go on!
727 destination = *source;
728 return true;
729}
730
731inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
732{
733 ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
734 ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
735
736 bool changed = false;
737
738 for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument)
739 changed |= mergeVariableBetweenBlocks(to->valuesAtHead.argument(argument), from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
740
741 for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local)
742 changed |= mergeVariableBetweenBlocks(to->valuesAtHead.local(local), from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
743
744 if (!to->cfaHasVisited)
745 changed = true;
746
747 to->cfaShouldRevisit |= changed;
748
749 return changed;
750}
751
752inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBlock)
753{
754 PROFILE(FLAG_FOR_MERGE_TO_SUCCESSORS);
755
756 Node& terminal = graph[basicBlock->end - 1];
757
758 ASSERT(terminal.isTerminal());
759
760 switch (terminal.op) {
761 case Jump:
762 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
763
764 case Branch:
765 return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get())
766 | merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
767
768 case Return:
769 case Throw:
770 case ThrowReferenceError:
771 return false;
772
773 default:
774 ASSERT_NOT_REACHED();
775 return false;
776 }
777}
778
779inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
780{
781 if (destinationNodeIndex == NoNode)
782 return false;
783
784 ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
785
786 // FIXME: We could do some sparse conditional propagation here!
787
788 return destination.merge(source);
789}
790
791#ifndef NDEBUG
792void AbstractState::dump(FILE* out)
793{
794 bool first = true;
795 for (size_t i = 0; i < m_nodes.size(); ++i) {
796 if (m_nodes[i].isClear())
797 continue;
798 if (first)
799 first = false;
800 else
801 fprintf(out, " ");
802 fprintf(out, "@%lu:", i + m_block->begin);
803 m_nodes[i].dump(out);
804 }
805}
806#endif
807
808} } // namespace JSC::DFG
809
810#endif // ENABLE(DFG_JIT)
811