Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 10831261: Build and use stack maps in the SSA compiler. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_allocator.h" 5 #include "vm/flow_graph_allocator.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 ProcessOneInstruction(block, current); 475 ProcessOneInstruction(block, current);
476 } 476 }
477 current = current->previous(); 477 current = current->previous();
478 } 478 }
479 479
480 ConnectIncomingPhiMoves(block); 480 ConnectIncomingPhiMoves(block);
481 } 481 }
482 482
483 const bool copied = builder_->copied_parameter_count() > 0; 483 const bool copied = builder_->copied_parameter_count() > 0;
484 484
485 // Process incoming parameters. 485 // Process incoming parameters. Do this after all other instructions so
486 // that safepoints for all calls have already been found.
486 const intptr_t fixed_parameters_count = 487 const intptr_t fixed_parameters_count =
487 builder_->parsed_function().function().num_fixed_parameters(); 488 builder_->parsed_function().function().num_fixed_parameters();
488 489
489 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); 490 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry();
490 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { 491 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) {
491 Value* val = graph_entry->start_env()->values()[i]; 492 Value* val = graph_entry->start_env()->values()[i];
492 if (val->IsUse()) { 493 if (val->IsUse()) {
493 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); 494 ParameterInstr* param = val->AsUse()->definition()->AsParameter();
494 495
495 LiveRange* range = GetLiveRange(param->ssa_temp_index()); 496 LiveRange* range = GetLiveRange(param->ssa_temp_index());
(...skipping 17 matching lines...) Expand all
513 range->finger()->Initialize(range); 514 range->finger()->Initialize(range);
514 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( 515 UsePosition* use = range->finger()->FirstRegisterBeneficialUse(
515 graph_entry->start_pos()); 516 graph_entry->start_pos());
516 if (use != NULL) { 517 if (use != NULL) {
517 LiveRange* tail = SplitBetween(range, 518 LiveRange* tail = SplitBetween(range,
518 graph_entry->start_pos(), 519 graph_entry->start_pos(),
519 use->pos()); 520 use->pos());
520 AddToUnallocated(tail); 521 AddToUnallocated(tail);
521 } 522 }
522 ConvertAllUses(range); 523 ConvertAllUses(range);
524 if (copied) {
525 for (intptr_t i = 0; i < safepoints_.length(); ++i) {
Vyacheslav Egorov (Google) 2012/08/13 12:54:46 Please move this code into a separate function. I
Kevin Millikin (Google) 2012/08/13 15:10:37 OK.
526 if (range->Covers(safepoints_[i].position)) {
527 TRACE_ALLOC(OS::Print(" marking S[%d] in stack bitmap at %d\n",
528 slot_index,
529 safepoints_[i].position));
530 safepoints_[i].stack_bitmap->Set(slot_index, true);
531 }
532 }
533 }
523 } 534 }
524 } 535 }
525 } 536 }
526 537
527 // 538 //
528 // When describing shape of live ranges in comments below we are going to use 539 // When describing shape of live ranges in comments below we are going to use
529 // the following notation: 540 // the following notation:
530 // 541 //
531 // B block entry 542 // B block entry
532 // g g' start and end of goto instruction 543 // g g' start and end of goto instruction
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } else if (temp.IsUnallocated()) { 752 } else if (temp.IsUnallocated()) {
742 LiveRange* range = MakeLiveRangeForTemporary(); 753 LiveRange* range = MakeLiveRangeForTemporary();
743 range->AddUseInterval(pos, pos + 1); 754 range->AddUseInterval(pos, pos + 1);
744 range->AddUse(pos, locs->temp_slot(j)); 755 range->AddUse(pos, locs->temp_slot(j));
745 AddToUnallocated(range); 756 AddToUnallocated(range);
746 } else { 757 } else {
747 UNREACHABLE(); 758 UNREACHABLE();
748 } 759 }
749 } 760 }
750 761
751 // Block all allocatable registers for calls. 762 // Block all allocatable registers for calls and record the stack bitmap.
752 if (locs->is_call()) { 763 if (locs->is_call()) {
753 // Expected shape of live range: 764 // Expected shape of live range:
754 // 765 //
755 // i i' 766 // i i'
756 // [--) 767 // [--)
757 // 768 //
769 // The stack bitmap describes the position i.
770 Safepoint safepoint = { pos, locs->stack_bitmap() };
771 safepoints_.Add(safepoint);
758 772
759 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 773 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
760 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 774 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
761 pos, 775 pos,
762 pos + 1); 776 pos + 1);
763 } 777 }
764 778
765 #if defined(DEBUG) 779 #if defined(DEBUG)
766 // Verify that temps, inputs and output were specified as fixed 780 // Verify that temps, inputs and output were specified as fixed
767 // locations. Every register is blocked now so attempt to 781 // locations. Every register is blocked now so attempt to
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 } 1319 }
1306 1320
1307 spill_slots_[idx] = last_sibling->End(); 1321 spill_slots_[idx] = last_sibling->End();
1308 1322
1309 range->set_spill_slot(Location::StackSlot(idx)); 1323 range->set_spill_slot(Location::StackSlot(idx));
1310 1324
1311 spilled_.Add(range); 1325 spilled_.Add(range);
1312 } 1326 }
1313 1327
1314 1328
1329 bool LiveRange::Covers(intptr_t pos) const {
1330 const LiveRange* current = this;
1331 while (current != NULL) {
1332 UseInterval* interval = current->first_use_interval_;
1333 while (interval != NULL) {
1334 if (interval->Contains(pos)) return true;
1335 interval = interval->next();
1336 }
1337 current = current->next_sibling_;
1338 }
1339 return false;
1340 }
1341
1342
1315 void FlowGraphAllocator::Spill(LiveRange* range) { 1343 void FlowGraphAllocator::Spill(LiveRange* range) {
1316 LiveRange* parent = GetLiveRange(range->vreg()); 1344 LiveRange* parent = GetLiveRange(range->vreg());
1317 1345
1318 if (parent->spill_slot().IsInvalid()) AllocateSpillSlotFor(parent); 1346 if (parent->spill_slot().IsInvalid()) {
1347 AllocateSpillSlotFor(parent);
1348 intptr_t stack_index = parent->spill_slot().stack_index();
1349 ASSERT(stack_index >= 0);
1350 for (intptr_t i = 0; i < safepoints_.length(); ++i) {
1351 if (parent->Covers(safepoints_[i].position)) {
1352 TRACE_ALLOC(OS::Print(" marking S[%d] in stack bitmap at %d\n",
1353 stack_index,
1354 safepoints_[i].position));
1355 safepoints_[i].stack_bitmap->Set(stack_index, true);
1356 }
1357 }
1358 }
1319 1359
1320 range->set_assigned_location(parent->spill_slot()); 1360 range->set_assigned_location(parent->spill_slot());
1321 ConvertAllUses(range); 1361 ConvertAllUses(range);
1322 } 1362 }
1323 1363
1324 1364
1325 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( 1365 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
1326 Register reg, LiveRange* unallocated) { 1366 Register reg, LiveRange* unallocated) {
1327 intptr_t intersection = kMaxPosition; 1367 intptr_t intersection = kMaxPosition;
1328 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { 1368 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) {
1329 LiveRange* allocated = cpu_regs_[reg][i]; 1369 LiveRange* allocated = cpu_regs_[reg][i];
1330 if (allocated == NULL) continue; 1370 if (allocated == NULL) continue;
1331 1371
1332 UseInterval* allocated_head = 1372 UseInterval* allocated_head =
1333 allocated->finger()->first_pending_use_interval(); 1373 allocated->finger()->first_pending_use_interval();
1334 if (allocated_head->start() >= intersection) continue; 1374 if (allocated_head->start() >= intersection) continue;
1335 1375
1336 const intptr_t pos = FirstIntersection( 1376 const intptr_t pos = FirstIntersection(
1337 unallocated->finger()->first_pending_use_interval(), 1377 unallocated->finger()->first_pending_use_interval(),
1338 allocated_head); 1378 allocated_head);
1339 if (pos < intersection) intersection = pos; 1379 if (pos < intersection) intersection = pos;
1340 } 1380 }
1341 return intersection; 1381 return intersection;
1342 } 1382 }
1343 1383
1344 1384
1345 1385
1346 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { 1386 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
1347 Register candidate = kNoRegister; 1387 Register candidate = kNoRegister;
1348 intptr_t free_until = 0; 1388 intptr_t free_until = 0;
(...skipping 18 matching lines...) Expand all
1367 free_until = kMaxPosition; 1407 free_until = kMaxPosition;
1368 break; 1408 break;
1369 } 1409 }
1370 } 1410 }
1371 } 1411 }
1372 1412
1373 ASSERT(0 <= kMaxPosition); 1413 ASSERT(0 <= kMaxPosition);
1374 if (free_until != kMaxPosition) { 1414 if (free_until != kMaxPosition) {
1375 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) { 1415 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) {
1376 if (blocked_cpu_regs_[reg] || (reg == candidate)) continue; 1416 if (blocked_cpu_regs_[reg] || (reg == candidate)) continue;
1377
1378 const intptr_t intersection = 1417 const intptr_t intersection =
1379 FirstIntersectionWithAllocated(static_cast<Register>(reg), unallocated); 1418 FirstIntersectionWithAllocated(static_cast<Register>(reg),
1380 1419 unallocated);
1381 if (intersection > free_until) { 1420 if (intersection > free_until) {
1382 candidate = static_cast<Register>(reg); 1421 candidate = static_cast<Register>(reg);
1383 free_until = intersection; 1422 free_until = intersection;
1384 if (free_until == kMaxPosition) break; 1423 if (free_until == kMaxPosition) break;
1385 } 1424 }
1386 } 1425 }
1387 } 1426 }
1388 1427
1389 // All registers are blocked by active ranges. 1428 // All registers are blocked by active ranges.
1390 if (free_until <= unallocated->Start()) return false; 1429 if (free_until <= unallocated->Start()) return false;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 allocated->finger()->first_pending_use_interval(); 1506 allocated->finger()->first_pending_use_interval();
1468 if (first_pending_use_interval->Contains(start)) { 1507 if (first_pending_use_interval->Contains(start)) {
1469 // This is an active interval. 1508 // This is an active interval.
1470 if (allocated->vreg() < 0) { 1509 if (allocated->vreg() < 0) {
1471 // This register blocked by an interval that 1510 // This register blocked by an interval that
1472 // can't be spilled. 1511 // can't be spilled.
1473 return false; 1512 return false;
1474 } 1513 }
1475 1514
1476 const UsePosition* use = 1515 const UsePosition* use =
1477 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); 1516 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start());
1478 1517
1479 if ((use != NULL) && ((use->pos() - start) <= 1)) { 1518 if ((use != NULL) && ((use->pos() - start) <= 1)) {
1480 // This register is blocked by interval that is used 1519 // This register is blocked by interval that is used
1481 // as register in the current instruction and can't 1520 // as register in the current instruction and can't
1482 // be spilled. 1521 // be spilled.
1483 return false; 1522 return false;
1484 } 1523 }
1485 1524
1486 const intptr_t use_pos = (use != NULL) ? use->pos() 1525 const intptr_t use_pos = (use != NULL) ? use->pos()
1487 : allocated->End(); 1526 : allocated->End();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1541 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 1580 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
1542 1581
1543 cpu_regs_[reg].Add(unallocated); 1582 cpu_regs_[reg].Add(unallocated);
1544 unallocated->set_assigned_location(Location::RegisterLocation(reg)); 1583 unallocated->set_assigned_location(Location::RegisterLocation(reg));
1545 } 1584 }
1546 1585
1547 1586
1548 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 1587 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
1549 LiveRange* unallocated) { 1588 LiveRange* unallocated) {
1550 UseInterval* first_unallocated = 1589 UseInterval* first_unallocated =
1551 unallocated->finger()->first_pending_use_interval(); 1590 unallocated->finger()->first_pending_use_interval();
1552 const intptr_t intersection = FirstIntersection( 1591 const intptr_t intersection = FirstIntersection(
1553 allocated->finger()->first_pending_use_interval(), 1592 allocated->finger()->first_pending_use_interval(),
1554 first_unallocated); 1593 first_unallocated);
1555 if (intersection == kMaxPosition) return false; 1594 if (intersection == kMaxPosition) return false;
1556 1595
1557 const intptr_t spill_position = first_unallocated->start(); 1596 const intptr_t spill_position = first_unallocated->start();
1558 UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position); 1597 UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position);
1559 if (use == NULL) { 1598 if (use == NULL) {
1560 // No register uses after this point. 1599 // No register uses after this point.
1561 SpillAfter(allocated, spill_position); 1600 SpillAfter(allocated, spill_position);
1562 } else { 1601 } else {
1563 const intptr_t restore_position = 1602 const intptr_t restore_position =
1564 (spill_position < intersection) ? MinPosition(intersection, use->pos()) 1603 (spill_position < intersection) ? MinPosition(intersection, use->pos())
1565 : use->pos(); 1604 : use->pos();
1566 1605
1567 SpillBetween(allocated, spill_position, restore_position); 1606 SpillBetween(allocated, spill_position, restore_position);
1568 } 1607 }
1569 1608
1570 return true; 1609 return true;
1571 } 1610 }
1572 1611
1573 1612
1574 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos, 1613 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos,
1575 Location to, 1614 Location to,
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 1926 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
1888 function.ToFullyQualifiedCString()); 1927 function.ToFullyQualifiedCString());
1889 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 1928 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1890 printer.PrintBlocks(); 1929 printer.PrintBlocks();
1891 OS::Print("----------------------------------------------\n"); 1930 OS::Print("----------------------------------------------\n");
1892 } 1931 }
1893 } 1932 }
1894 1933
1895 1934
1896 } // namespace dart 1935 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698