OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 predecessors_(2), | 63 predecessors_(2), |
64 dominator_(NULL), | 64 dominator_(NULL), |
65 dominated_blocks_(4), | 65 dominated_blocks_(4), |
66 last_environment_(NULL), | 66 last_environment_(NULL), |
67 argument_count_(-1), | 67 argument_count_(-1), |
68 first_instruction_index_(-1), | 68 first_instruction_index_(-1), |
69 last_instruction_index_(-1), | 69 last_instruction_index_(-1), |
70 deleted_phis_(4), | 70 deleted_phis_(4), |
71 parent_loop_header_(NULL), | 71 parent_loop_header_(NULL), |
72 is_inline_return_target_(false), | 72 is_inline_return_target_(false), |
73 is_deoptimizing_(false) { } | 73 is_deoptimizing_(false), |
| 74 dominates_loop_successors_(false) { } |
74 | 75 |
75 | 76 |
76 void HBasicBlock::AttachLoopInformation() { | 77 void HBasicBlock::AttachLoopInformation() { |
77 ASSERT(!IsLoopHeader()); | 78 ASSERT(!IsLoopHeader()); |
78 loop_information_ = new(zone()) HLoopInformation(this); | 79 loop_information_ = new(zone()) HLoopInformation(this); |
79 } | 80 } |
80 | 81 |
81 | 82 |
82 void HBasicBlock::DetachLoopInformation() { | 83 void HBasicBlock::DetachLoopInformation() { |
83 ASSERT(IsLoopHeader()); | 84 ASSERT(IsLoopHeader()); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 if (dominator_ != first) { | 309 if (dominator_ != first) { |
309 ASSERT(dominator_->dominated_blocks_.Contains(this)); | 310 ASSERT(dominator_->dominated_blocks_.Contains(this)); |
310 dominator_->dominated_blocks_.RemoveElement(this); | 311 dominator_->dominated_blocks_.RemoveElement(this); |
311 dominator_ = first; | 312 dominator_ = first; |
312 first->AddDominatedBlock(this); | 313 first->AddDominatedBlock(this); |
313 } | 314 } |
314 } | 315 } |
315 } | 316 } |
316 | 317 |
317 | 318 |
| 319 void HBasicBlock::AssignLoopSuccessorDominators() { |
| 320 // Mark blocks that dominate all subsequent reachable blocks inside their |
| 321 // loop. Exploit the fact that blocks are sorted in reverse post order. When |
| 322 // the loop is visited in increasing block id order, if the number of |
| 323 // non-loop-exiting successor edges at the dominator_candidate block doesn't |
| 324 // exceed the number of previously encountered predecessor edges, there is no |
| 325 // path from the loop header to any block with higher id that doesn't go |
| 326 // through the dominator_candidate block. In this case, the |
| 327 // dominator_candidate block is guaranteed to dominate all blocks reachable |
| 328 // from it with higher ids. |
| 329 HBasicBlock* last = loop_information()->GetLastBackEdge(); |
| 330 int outstanding_successors = 1; // one edge from the pre-header |
| 331 // Header always dominates everything. |
| 332 MarkAsLoopSuccessorDominator(); |
| 333 for (int j = block_id(); j <= last->block_id(); ++j) { |
| 334 HBasicBlock* dominator_candidate = graph_->blocks()->at(j); |
| 335 for (HPredecessorIterator it(dominator_candidate); !it.Done(); |
| 336 it.Advance()) { |
| 337 HBasicBlock* predecessor = it.Current(); |
| 338 // Don't count back edges. |
| 339 if (predecessor->block_id() < dominator_candidate->block_id()) { |
| 340 outstanding_successors--; |
| 341 } |
| 342 } |
| 343 |
| 344 // If more successors than predecessors have been seen in the loop up to |
| 345 // now, it's not possible to guarantee that the current block dominates |
| 346 // all of the blocks with higher IDs. In this case, assume conservatively |
| 347 // that those paths through loop that don't go through the current block |
| 348 // contain all of the loop's dependencies. Also be careful to record |
| 349 // dominator information about the current loop that's being processed, |
| 350 // and not nested loops, which will be processed when |
| 351 // AssignLoopSuccessorDominators gets called on their header. |
| 352 ASSERT(outstanding_successors >= 0); |
| 353 HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); |
| 354 if (outstanding_successors == 0 && |
| 355 (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { |
| 356 dominator_candidate->MarkAsLoopSuccessorDominator(); |
| 357 } |
| 358 HControlInstruction* end = dominator_candidate->end(); |
| 359 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
| 360 HBasicBlock* successor = it.Current(); |
| 361 // Only count successors that remain inside the loop and don't loop back |
| 362 // to a loop header. |
| 363 if (successor->block_id() > dominator_candidate->block_id() && |
| 364 successor->block_id() <= last->block_id()) { |
| 365 // Backwards edges must land on loop headers. |
| 366 ASSERT(successor->block_id() > dominator_candidate->block_id() || |
| 367 successor->IsLoopHeader()); |
| 368 outstanding_successors++; |
| 369 } |
| 370 } |
| 371 } |
| 372 } |
| 373 |
| 374 |
318 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { | 375 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { |
319 for (int i = 0; i < predecessors_.length(); ++i) { | 376 for (int i = 0; i < predecessors_.length(); ++i) { |
320 if (predecessors_[i] == predecessor) return i; | 377 if (predecessors_[i] == predecessor) return i; |
321 } | 378 } |
322 UNREACHABLE(); | 379 UNREACHABLE(); |
323 return -1; | 380 return -1; |
324 } | 381 } |
325 | 382 |
326 | 383 |
327 #ifdef DEBUG | 384 #ifdef DEBUG |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 ASSERT(block->end()->SecondSuccessor() == NULL || | 802 ASSERT(block->end()->SecondSuccessor() == NULL || |
746 order->Contains(block->end()->SecondSuccessor()) || | 803 order->Contains(block->end()->SecondSuccessor()) || |
747 block->end()->SecondSuccessor()->IsLoopHeader()); | 804 block->end()->SecondSuccessor()->IsLoopHeader()); |
748 order->Add(block); | 805 order->Add(block); |
749 } | 806 } |
750 | 807 |
751 | 808 |
752 void HGraph::AssignDominators() { | 809 void HGraph::AssignDominators() { |
753 HPhase phase("Assign dominators", this); | 810 HPhase phase("Assign dominators", this); |
754 for (int i = 0; i < blocks_.length(); ++i) { | 811 for (int i = 0; i < blocks_.length(); ++i) { |
755 if (blocks_[i]->IsLoopHeader()) { | 812 HBasicBlock* block = blocks_[i]; |
| 813 if (block->IsLoopHeader()) { |
756 // Only the first predecessor of a loop header is from outside the loop. | 814 // Only the first predecessor of a loop header is from outside the loop. |
757 // All others are back edges, and thus cannot dominate the loop header. | 815 // All others are back edges, and thus cannot dominate the loop header. |
758 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); | 816 block->AssignCommonDominator(block->predecessors()->first()); |
| 817 block->AssignLoopSuccessorDominators(); |
759 } else { | 818 } else { |
760 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { | 819 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { |
761 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 820 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
762 } | 821 } |
763 } | 822 } |
764 } | 823 } |
765 } | 824 } |
766 | 825 |
767 // Mark all blocks that are dominated by an unconditional soft deoptimize to | 826 // Mark all blocks that are dominated by an unconditional soft deoptimize to |
768 // prevent code motion across those blocks. | 827 // prevent code motion across those blocks. |
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 | 1425 |
1367 private: | 1426 private: |
1368 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( | 1427 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
1369 HBasicBlock* dominator, | 1428 HBasicBlock* dominator, |
1370 HBasicBlock* dominated); | 1429 HBasicBlock* dominated); |
1371 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); | 1430 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); |
1372 void ComputeBlockSideEffects(); | 1431 void ComputeBlockSideEffects(); |
1373 void LoopInvariantCodeMotion(); | 1432 void LoopInvariantCodeMotion(); |
1374 void ProcessLoopBlock(HBasicBlock* block, | 1433 void ProcessLoopBlock(HBasicBlock* block, |
1375 HBasicBlock* before_loop, | 1434 HBasicBlock* before_loop, |
1376 GVNFlagSet loop_kills); | 1435 GVNFlagSet loop_kills, |
| 1436 GVNFlagSet* accumulated_first_time_depends); |
1377 bool AllowCodeMotion(); | 1437 bool AllowCodeMotion(); |
1378 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1438 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
1379 | 1439 |
1380 HGraph* graph() { return graph_; } | 1440 HGraph* graph() { return graph_; } |
1381 CompilationInfo* info() { return info_; } | 1441 CompilationInfo* info() { return info_; } |
1382 Zone* zone() { return graph_->zone(); } | 1442 Zone* zone() { return graph_->zone(); } |
1383 | 1443 |
1384 HGraph* graph_; | 1444 HGraph* graph_; |
1385 CompilationInfo* info_; | 1445 CompilationInfo* info_; |
1386 bool removed_side_effects_; | 1446 bool removed_side_effects_; |
1387 | 1447 |
1388 // A map of block IDs to their side effects. | 1448 // A map of block IDs to their side effects. |
1389 ZoneList<GVNFlagSet> block_side_effects_; | 1449 ZoneList<GVNFlagSet> block_side_effects_; |
1390 | 1450 |
1391 // A map of loop header block IDs to their loop's side effects. | 1451 // A map of loop header block IDs to their loop's side effects. |
1392 ZoneList<GVNFlagSet> loop_side_effects_; | 1452 ZoneList<GVNFlagSet> loop_side_effects_; |
1393 | 1453 |
1394 // Used when collecting side effects on paths from dominator to | 1454 // Used when collecting side effects on paths from dominator to |
1395 // dominated. | 1455 // dominated. |
1396 SparseSet visited_on_paths_; | 1456 SparseSet visited_on_paths_; |
1397 }; | 1457 }; |
1398 | 1458 |
1399 | 1459 |
1400 bool HGlobalValueNumberer::Analyze() { | 1460 bool HGlobalValueNumberer::Analyze() { |
| 1461 removed_side_effects_ = false; |
1401 ComputeBlockSideEffects(); | 1462 ComputeBlockSideEffects(); |
1402 if (FLAG_loop_invariant_code_motion) { | 1463 if (FLAG_loop_invariant_code_motion) { |
1403 LoopInvariantCodeMotion(); | 1464 LoopInvariantCodeMotion(); |
1404 } | 1465 } |
1405 HValueMap* map = new(zone()) HValueMap(); | 1466 HValueMap* map = new(zone()) HValueMap(); |
1406 AnalyzeBlock(graph_->entry_block(), map); | 1467 AnalyzeBlock(graph_->entry_block(), map); |
1407 return removed_side_effects_; | 1468 return removed_side_effects_; |
1408 } | 1469 } |
1409 | 1470 |
1410 | 1471 |
1411 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1472 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
| 1473 // The Analyze phase of GVN can be called multiple times. Clear loop side |
| 1474 // effects before computing them to erase the contents from previous Analyze |
| 1475 // passes. |
| 1476 for (int i = 0; i < loop_side_effects_.length(); ++i) { |
| 1477 loop_side_effects_[i].RemoveAll(); |
| 1478 } |
1412 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1479 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
1413 // Compute side effects for the block. | 1480 // Compute side effects for the block. |
1414 HBasicBlock* block = graph_->blocks()->at(i); | 1481 HBasicBlock* block = graph_->blocks()->at(i); |
1415 HInstruction* instr = block->first(); | 1482 HInstruction* instr = block->first(); |
1416 int id = block->block_id(); | 1483 int id = block->block_id(); |
1417 GVNFlagSet side_effects; | 1484 GVNFlagSet side_effects; |
1418 while (instr != NULL) { | 1485 while (instr != NULL) { |
1419 side_effects.Add(instr->ChangesFlags()); | 1486 side_effects.Add(instr->ChangesFlags()); |
1420 instr = instr->next(); | 1487 instr = instr->next(); |
1421 } | 1488 } |
(...skipping 17 matching lines...) Expand all Loading... |
1439 | 1506 |
1440 void HGlobalValueNumberer::LoopInvariantCodeMotion() { | 1507 void HGlobalValueNumberer::LoopInvariantCodeMotion() { |
1441 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1508 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
1442 HBasicBlock* block = graph_->blocks()->at(i); | 1509 HBasicBlock* block = graph_->blocks()->at(i); |
1443 if (block->IsLoopHeader()) { | 1510 if (block->IsLoopHeader()) { |
1444 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; | 1511 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; |
1445 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", | 1512 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", |
1446 block->block_id(), | 1513 block->block_id(), |
1447 side_effects.ToIntegral()); | 1514 side_effects.ToIntegral()); |
1448 | 1515 |
| 1516 GVNFlagSet accumulated_first_time_depends; |
1449 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); | 1517 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); |
1450 for (int j = block->block_id(); j <= last->block_id(); ++j) { | 1518 for (int j = block->block_id(); j <= last->block_id(); ++j) { |
1451 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); | 1519 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, |
| 1520 &accumulated_first_time_depends); |
1452 } | 1521 } |
1453 } | 1522 } |
1454 } | 1523 } |
1455 } | 1524 } |
1456 | 1525 |
1457 | 1526 |
1458 void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, | 1527 void HGlobalValueNumberer::ProcessLoopBlock( |
1459 HBasicBlock* loop_header, | 1528 HBasicBlock* block, |
1460 GVNFlagSet loop_kills) { | 1529 HBasicBlock* loop_header, |
| 1530 GVNFlagSet loop_kills, |
| 1531 GVNFlagSet* accumulated_first_time_depends) { |
1461 HBasicBlock* pre_header = loop_header->predecessors()->at(0); | 1532 HBasicBlock* pre_header = loop_header->predecessors()->at(0); |
1462 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); | 1533 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); |
1463 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", | 1534 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", |
1464 block->block_id(), | 1535 block->block_id(), |
1465 depends_flags.ToIntegral()); | 1536 depends_flags.ToIntegral()); |
1466 HInstruction* instr = block->first(); | 1537 HInstruction* instr = block->first(); |
1467 while (instr != NULL) { | 1538 while (instr != NULL) { |
1468 HInstruction* next = instr->next(); | 1539 HInstruction* next = instr->next(); |
1469 if (instr->CheckFlag(HValue::kUseGVN) && | 1540 bool hoisted = false; |
1470 !instr->gvn_flags().ContainsAnyOf(depends_flags)) { | 1541 if (instr->CheckFlag(HValue::kUseGVN)) { |
1471 TraceGVN("Checking instruction %d (%s)\n", | 1542 TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, " |
| 1543 "loop kills 0x%X\n", |
1472 instr->id(), | 1544 instr->id(), |
1473 instr->Mnemonic()); | 1545 instr->Mnemonic(), |
1474 bool inputs_loop_invariant = true; | 1546 instr->gvn_flags().ToIntegral(), |
1475 for (int i = 0; i < instr->OperandCount(); ++i) { | 1547 depends_flags.ToIntegral()); |
1476 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { | 1548 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
1477 inputs_loop_invariant = false; | 1549 if (!can_hoist && instr->IsTransitionElementsKind()) { |
| 1550 // It's only possible to hoist one time side effects if there are no |
| 1551 // dependencies on their changes from the loop header to the current |
| 1552 // instruction. |
| 1553 GVNFlagSet converted_changes = |
| 1554 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); |
| 1555 TraceGVN("Checking dependencies on one-time instruction %d (%s) " |
| 1556 "converted changes 0x%X, accumulated depends 0x%X\n", |
| 1557 instr->id(), |
| 1558 instr->Mnemonic(), |
| 1559 converted_changes.ToIntegral(), |
| 1560 accumulated_first_time_depends->ToIntegral()); |
| 1561 // It's possible to hoist one-time side effects from the current loop |
| 1562 // loop only if they dominate all of the successor blocks in the same |
| 1563 // loop and there are not any instructions that have Changes/DependsOn |
| 1564 // that intervene between it and the beginning of the loop header. |
| 1565 bool in_nested_loop = block != loop_header && |
| 1566 ((block->parent_loop_header() != loop_header) || |
| 1567 block->IsLoopHeader()); |
| 1568 can_hoist = !in_nested_loop && |
| 1569 block->IsLoopSuccessorDominator() && |
| 1570 !accumulated_first_time_depends->ContainsAnyOf(converted_changes); |
| 1571 } |
| 1572 |
| 1573 if (can_hoist) { |
| 1574 bool inputs_loop_invariant = true; |
| 1575 for (int i = 0; i < instr->OperandCount(); ++i) { |
| 1576 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { |
| 1577 inputs_loop_invariant = false; |
| 1578 } |
| 1579 } |
| 1580 |
| 1581 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { |
| 1582 TraceGVN("Hoisting loop invariant instruction %d\n", instr->id()); |
| 1583 // Move the instruction out of the loop. |
| 1584 instr->Unlink(); |
| 1585 instr->InsertBefore(pre_header->end()); |
| 1586 if (instr->HasSideEffects()) removed_side_effects_ = true; |
| 1587 hoisted = true; |
1478 } | 1588 } |
1479 } | 1589 } |
1480 | 1590 } |
1481 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { | 1591 if (!hoisted) { |
1482 TraceGVN("Found loop invariant instruction %d\n", instr->id()); | 1592 // If an instruction is not hoisted, we have to account for its side |
1483 // Move the instruction out of the loop. | 1593 // effects when hoisting later HTransitionElementsKind instructions. |
1484 instr->Unlink(); | 1594 accumulated_first_time_depends->Add(instr->DependsOnFlags()); |
1485 instr->InsertBefore(pre_header->end()); | 1595 GVNFlagSet converted_changes = |
1486 } | 1596 HValue::ConvertChangesToDependsFlags(instr->SideEffectFlags()); |
| 1597 accumulated_first_time_depends->Add(converted_changes); |
1487 } | 1598 } |
1488 instr = next; | 1599 instr = next; |
1489 } | 1600 } |
1490 } | 1601 } |
1491 | 1602 |
1492 | 1603 |
1493 bool HGlobalValueNumberer::AllowCodeMotion() { | 1604 bool HGlobalValueNumberer::AllowCodeMotion() { |
1494 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; | 1605 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; |
1495 } | 1606 } |
1496 | 1607 |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2385 | 2496 |
2386 // Perform common subexpression elimination and loop-invariant code motion. | 2497 // Perform common subexpression elimination and loop-invariant code motion. |
2387 if (FLAG_use_gvn) { | 2498 if (FLAG_use_gvn) { |
2388 HPhase phase("Global value numbering", graph()); | 2499 HPhase phase("Global value numbering", graph()); |
2389 HGlobalValueNumberer gvn(graph(), info()); | 2500 HGlobalValueNumberer gvn(graph(), info()); |
2390 bool removed_side_effects = gvn.Analyze(); | 2501 bool removed_side_effects = gvn.Analyze(); |
2391 // Trigger a second analysis pass to further eliminate duplicate values that | 2502 // Trigger a second analysis pass to further eliminate duplicate values that |
2392 // could only be discovered by removing side-effect-generating instructions | 2503 // could only be discovered by removing side-effect-generating instructions |
2393 // during the first pass. | 2504 // during the first pass. |
2394 if (FLAG_smi_only_arrays && removed_side_effects) { | 2505 if (FLAG_smi_only_arrays && removed_side_effects) { |
2395 gvn.Analyze(); | 2506 removed_side_effects = gvn.Analyze(); |
| 2507 ASSERT(!removed_side_effects); |
2396 } | 2508 } |
2397 } | 2509 } |
2398 | 2510 |
2399 if (FLAG_use_range) { | 2511 if (FLAG_use_range) { |
2400 HRangeAnalysis rangeAnalysis(graph()); | 2512 HRangeAnalysis rangeAnalysis(graph()); |
2401 rangeAnalysis.Analyze(); | 2513 rangeAnalysis.Analyze(); |
2402 } | 2514 } |
2403 graph()->ComputeMinusZeroChecks(); | 2515 graph()->ComputeMinusZeroChecks(); |
2404 | 2516 |
2405 // Eliminate redundant stack checks on backwards branches. | 2517 // Eliminate redundant stack checks on backwards branches. |
(...skipping 4787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7193 } else { | 7305 } else { |
7194 PrintIndent(); | 7306 PrintIndent(); |
7195 trace_.Add("successors"); | 7307 trace_.Add("successors"); |
7196 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { | 7308 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { |
7197 trace_.Add(" \"B%d\"", it.Current()->block_id()); | 7309 trace_.Add(" \"B%d\"", it.Current()->block_id()); |
7198 } | 7310 } |
7199 trace_.Add("\n"); | 7311 trace_.Add("\n"); |
7200 } | 7312 } |
7201 | 7313 |
7202 PrintEmptyProperty("xhandlers"); | 7314 PrintEmptyProperty("xhandlers"); |
7203 PrintEmptyProperty("flags"); | 7315 const char* flags = current->IsLoopSuccessorDominator() |
| 7316 ? "dom-loop-succ" |
| 7317 : ""; |
| 7318 PrintStringProperty("flags", flags); |
7204 | 7319 |
7205 if (current->dominator() != NULL) { | 7320 if (current->dominator() != NULL) { |
7206 PrintBlockProperty("dominator", current->dominator()->block_id()); | 7321 PrintBlockProperty("dominator", current->dominator()->block_id()); |
7207 } | 7322 } |
7208 | 7323 |
7209 PrintIntProperty("loop_depth", current->LoopNestingDepth()); | 7324 PrintIntProperty("loop_depth", current->LoopNestingDepth()); |
7210 | 7325 |
7211 if (chunk != NULL) { | 7326 if (chunk != NULL) { |
7212 int first_index = current->first_instruction_index(); | 7327 int first_index = current->first_instruction_index(); |
7213 int last_index = current->last_instruction_index(); | 7328 int last_index = current->last_instruction_index(); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7453 } | 7568 } |
7454 } | 7569 } |
7455 | 7570 |
7456 #ifdef DEBUG | 7571 #ifdef DEBUG |
7457 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7572 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
7458 if (allocator_ != NULL) allocator_->Verify(); | 7573 if (allocator_ != NULL) allocator_->Verify(); |
7459 #endif | 7574 #endif |
7460 } | 7575 } |
7461 | 7576 |
7462 } } // namespace v8::internal | 7577 } } // namespace v8::internal |
OLD | NEW |