Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 ASSERT(is_optimizing()); | 390 ASSERT(is_optimizing()); |
| 391 CompilerDeoptInfo* info = | 391 CompilerDeoptInfo* info = |
| 392 new CompilerDeoptInfo(deopt_id, | 392 new CompilerDeoptInfo(deopt_id, |
| 393 kDeoptAtCall, | 393 kDeoptAtCall, |
| 394 pending_deoptimization_env_); | 394 pending_deoptimization_env_); |
| 395 info->set_pc_offset(assembler()->CodeSize()); | 395 info->set_pc_offset(assembler()->CodeSize()); |
| 396 deopt_infos_.Add(info); | 396 deopt_infos_.Add(info); |
| 397 } | 397 } |
| 398 | 398 |
| 399 | 399 |
| 400 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters | |
| 401 // and FlowGraphCompiler::SlowPathEnvironmentFor. | |
| 400 void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs) { | 402 void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs) { |
| 401 if (is_optimizing()) { | 403 if (is_optimizing()) { |
| 402 BitmapBuilder* bitmap = locs->stack_bitmap(); | 404 BitmapBuilder* bitmap = locs->stack_bitmap(); |
| 403 ASSERT(bitmap != NULL); | 405 ASSERT(bitmap != NULL); |
| 404 ASSERT(bitmap->Length() <= StackSize()); | 406 ASSERT(bitmap->Length() <= StackSize()); |
| 405 // Pad the bitmap out to describe all the spill slots. | 407 // Pad the bitmap out to describe all the spill slots. |
| 406 bitmap->SetLength(StackSize()); | 408 bitmap->SetLength(StackSize()); |
| 407 | 409 |
| 408 // Mark the bits in the stack map in the same order we push registers in | 410 // Mark the bits in the stack map in the same order we push registers in |
| 409 // slow path code (see FlowGraphCompiler::SaveLiveRegisters). | 411 // slow path code (see FlowGraphCompiler::SaveLiveRegisters). |
| 410 // | 412 // |
| 411 // Slow path code can have registers at the safepoint. | 413 // Slow path code can have registers at the safepoint. |
| 412 if (!locs->always_calls()) { | 414 if (!locs->always_calls()) { |
| 413 RegisterSet* regs = locs->live_registers(); | 415 RegisterSet* regs = locs->live_registers(); |
| 414 if (regs->fpu_regs_count() > 0) { | 416 if (regs->FpuRegisterCount() > 0) { |
| 415 // Denote FPU registers with 0 bits in the stackmap. Based on the | 417 // Denote FPU registers with 0 bits in the stackmap. Based on the |
| 416 // assumption that there are normally few live FPU registers, this | 418 // assumption that there are normally few live FPU registers, this |
| 417 // encoding is simpler and roughly as compact as storing a separate | 419 // encoding is simpler and roughly as compact as storing a separate |
| 418 // count of FPU registers. | 420 // count of FPU registers. |
| 419 // | 421 // |
| 420 // FPU registers have the highest register number at the highest | 422 // FPU registers have the highest register number at the highest |
| 421 // address (i.e., first in the stackmap). | 423 // address (i.e., first in the stackmap). |
| 422 const intptr_t kFpuRegisterSpillFactor = | 424 const intptr_t kFpuRegisterSpillFactor = |
| 423 kFpuRegisterSize / kWordSize; | 425 kFpuRegisterSize / kWordSize; |
| 424 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) { | 426 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 441 } | 443 } |
| 442 | 444 |
| 443 intptr_t register_bit_count = bitmap->Length() - StackSize(); | 445 intptr_t register_bit_count = bitmap->Length() - StackSize(); |
| 444 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 446 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 445 bitmap, | 447 bitmap, |
| 446 register_bit_count); | 448 register_bit_count); |
| 447 } | 449 } |
| 448 } | 450 } |
| 449 | 451 |
| 450 | 452 |
| 453 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and | |
| 454 // FlowGraphCompiler::SaveLiveRegisters. | |
| 455 Environment* FlowGraphCompiler::SlowPathEnvironmentFor( | |
| 456 Instruction* instruction) { | |
| 457 if (instruction->env() == NULL) return NULL; | |
| 458 | |
| 459 Environment* env = instruction->env()->DeepCopy(); | |
| 460 // 1. Iterate the registers in the order they will be spilled to compute | |
| 461 // the slots they will be spilled to. | |
| 462 intptr_t next_slot = StackSize(); | |
| 463 RegisterSet* regs = instruction->locs()->live_registers(); | |
| 464 intptr_t fpu_reg_slots[kNumberOfFpuRegisters]; | |
| 465 intptr_t cpu_reg_slots[kNumberOfCpuRegisters]; | |
| 466 const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize; | |
| 467 // FPU registers are spilled first from highest to lowest register number. | |
| 468 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) { | |
| 469 FpuRegister reg = static_cast<FpuRegister>(i); | |
| 470 if (regs->ContainsFpuRegister(reg)) { | |
| 471 // We use the lowest address (thus highest index) to identify a | |
| 472 // multi-word spill slot. | |
| 473 next_slot += kFpuRegisterSpillFactor; | |
| 474 fpu_reg_slots[i] = (next_slot - 1); | |
| 475 } else { | |
| 476 fpu_reg_slots[i] = -1; | |
| 477 } | |
| 478 } | |
| 479 // General purpose registers are spilled from lowest to highest register | |
| 480 // number. | |
| 481 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) { | |
| 482 Register reg = static_cast<Register>(i); | |
| 483 if (regs->ContainsRegister(reg)) { | |
| 484 cpu_reg_slots[i] = next_slot++; | |
| 485 } else { | |
| 486 cpu_reg_slots[i] = -1; | |
| 487 } | |
| 488 } | |
| 489 | |
| 490 // 2. Iterate the environment and replace register locations with the | |
| 491 // corresponding spill slot locations. | |
| 492 for (Environment::DeepIterator it(env); !it.Done(); it.Advance()) { | |
| 493 Location loc = it.CurrentLocation(); | |
| 494 if (loc.IsRegister()) { | |
| 495 intptr_t index = cpu_reg_slots[loc.reg()]; | |
| 496 ASSERT(index >= 0); | |
|
Florian Schneider
2013/10/17 14:38:52
Shouldn't this be even stronger?
ASSERT(index >=
| |
| 497 it.SetCurrentLocation(Location::StackSlot(index)); | |
| 498 } else if (loc.IsFpuRegister()) { | |
| 499 assembler()->Comment("You betcha!"); | |
|
Kevin Millikin (Google)
2013/10/14 16:12:52
Ignore this.
srdjan
2013/12/03 22:42:10
But it was submitted. Can we replace it with somet
| |
| 500 intptr_t index = fpu_reg_slots[loc.fpu_reg()]; | |
| 501 ASSERT(index >= 0); | |
|
Florian Schneider
2013/10/17 14:38:52
ASSERT(index >= 0 && index >= StackSize());
| |
| 502 Value* value = it.CurrentValue(); | |
| 503 switch (value->definition()->representation()) { | |
| 504 case kUnboxedDouble: | |
| 505 case kUnboxedMint: | |
| 506 it.SetCurrentLocation(Location::DoubleStackSlot(index)); | |
|
Kevin Millikin (Google)
2013/10/14 16:12:52
As discussed offline, I'm not sure that this index
| |
| 507 break; | |
| 508 case kUnboxedFloat32x4: | |
| 509 case kUnboxedUint32x4: | |
| 510 it.SetCurrentLocation(Location::QuadStackSlot(index)); | |
|
Florian Schneider
2013/10/17 14:38:52
Try to also have a test case for the quad-word cas
| |
| 511 break; | |
| 512 default: | |
| 513 UNREACHABLE(); | |
| 514 } | |
| 515 } | |
| 516 } | |
| 517 | |
| 518 return env; | |
| 519 } | |
| 520 | |
| 521 | |
| 451 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, | 522 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| 452 DeoptReasonId reason) { | 523 DeoptReasonId reason) { |
| 453 ASSERT(is_optimizing_); | 524 ASSERT(is_optimizing_); |
| 454 CompilerDeoptInfoWithStub* stub = | 525 CompilerDeoptInfoWithStub* stub = |
| 455 new CompilerDeoptInfoWithStub(deopt_id, | 526 new CompilerDeoptInfoWithStub(deopt_id, |
| 456 reason, | 527 reason, |
| 457 pending_deoptimization_env_); | 528 pending_deoptimization_env_); |
| 458 deopt_infos_.Add(stub); | 529 deopt_infos_.Add(stub); |
| 459 return stub->entry_label(); | 530 return stub->entry_label(); |
| 460 } | 531 } |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 | 1205 |
| 1135 for (int i = 0; i < len; i++) { | 1206 for (int i = 0; i < len; i++) { |
| 1136 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), | 1207 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), |
| 1137 &Function::ZoneHandle(ic_data.GetTargetAt(i)), | 1208 &Function::ZoneHandle(ic_data.GetTargetAt(i)), |
| 1138 ic_data.GetCountAt(i))); | 1209 ic_data.GetCountAt(i))); |
| 1139 } | 1210 } |
| 1140 sorted->Sort(HighestCountFirst); | 1211 sorted->Sort(HighestCountFirst); |
| 1141 } | 1212 } |
| 1142 | 1213 |
| 1143 } // namespace dart | 1214 } // namespace dart |
| OLD | NEW |