| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_REGISTER_ALLOCATOR_H_ | 5 #ifndef V8_REGISTER_ALLOCATOR_H_ |
| 6 #define V8_REGISTER_ALLOCATOR_H_ | 6 #define V8_REGISTER_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
| 9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 class PipelineStatistics; | |
| 16 | |
| 17 enum RegisterKind { | 15 enum RegisterKind { |
| 18 UNALLOCATED_REGISTERS, | 16 UNALLOCATED_REGISTERS, |
| 19 GENERAL_REGISTERS, | 17 GENERAL_REGISTERS, |
| 20 DOUBLE_REGISTERS | 18 DOUBLE_REGISTERS |
| 21 }; | 19 }; |
| 22 | 20 |
| 23 | 21 |
| 24 // This class represents a single point of a InstructionOperand's lifetime. For | 22 // This class represents a single point of a InstructionOperand's lifetime. For |
| 25 // each instruction there are exactly two lifetime positions: the beginning and | 23 // each instruction there are exactly two lifetime positions: the beginning and |
| 26 // the end of the instruction. Lifetime positions for different instructions are | 24 // the end of the instruction. Lifetime positions for different instructions are |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 InstructionOperand* current_hint_operand_; | 311 InstructionOperand* current_hint_operand_; |
| 314 InstructionOperand* spill_operand_; | 312 InstructionOperand* spill_operand_; |
| 315 int spill_start_index_; | 313 int spill_start_index_; |
| 316 | 314 |
| 317 friend class RegisterAllocator; // Assigns to kind_. | 315 friend class RegisterAllocator; // Assigns to kind_. |
| 318 | 316 |
| 319 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 317 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 320 }; | 318 }; |
| 321 | 319 |
| 322 | 320 |
| 323 class RegisterAllocator FINAL { | 321 class RegisterAllocator FINAL : public ZoneObject { |
| 324 public: | 322 public: |
| 325 explicit RegisterAllocator(const RegisterConfiguration* config, | 323 explicit RegisterAllocator(const RegisterConfiguration* config, |
| 326 Zone* local_zone, Frame* frame, | 324 Zone* local_zone, Frame* frame, |
| 327 InstructionSequence* code, | 325 InstructionSequence* code, |
| 328 const char* debug_name = nullptr); | 326 const char* debug_name = nullptr); |
| 329 | 327 |
| 330 bool Allocate(PipelineStatistics* stats = NULL); | |
| 331 bool AllocationOk() { return allocation_ok_; } | 328 bool AllocationOk() { return allocation_ok_; } |
| 332 BitVector* assigned_registers() { return assigned_registers_; } | |
| 333 BitVector* assigned_double_registers() { return assigned_double_registers_; } | |
| 334 | 329 |
| 335 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; } | 330 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; } |
| 336 const ZoneVector<LiveRange*>& fixed_live_ranges() const { | 331 const ZoneVector<LiveRange*>& fixed_live_ranges() const { |
| 337 return fixed_live_ranges_; | 332 return fixed_live_ranges_; |
| 338 } | 333 } |
| 339 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { | 334 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { |
| 340 return fixed_double_live_ranges_; | 335 return fixed_double_live_ranges_; |
| 341 } | 336 } |
| 342 InstructionSequence* code() const { return code_; } | 337 InstructionSequence* code() const { return code_; } |
| 343 // This zone is for datastructures only needed during register allocation. | 338 // This zone is for datastructures only needed during register allocation. |
| 344 Zone* local_zone() const { return local_zone_; } | 339 Zone* local_zone() const { return local_zone_; } |
| 345 | 340 |
| 341 // Phase 1 : insert moves to account for fixed register operands. |
| 342 void MeetRegisterConstraints(); |
| 343 |
| 344 // Phase 2: deconstruct SSA by inserting moves in successors and the headers |
| 345 // of blocks containing phis. |
| 346 void ResolvePhis(); |
| 347 |
| 348 // Phase 3: compute liveness of all virtual register. |
| 349 void BuildLiveRanges(); |
| 350 bool ExistsUseWithoutDefinition(); |
| 351 |
| 352 // Phase 4: compute register assignments. |
| 353 void AllocateGeneralRegisters(); |
| 354 void AllocateDoubleRegisters(); |
| 355 |
| 356 // Phase 5: compute values for pointer maps. |
| 357 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. |
| 358 |
| 359 // Phase 6: reconnect split ranges with moves. |
| 360 void ConnectRanges(); |
| 361 |
| 362 // Phase 7: insert moves to connect ranges across basic blocks. |
| 363 void ResolveControlFlow(); |
| 364 |
| 346 private: | 365 private: |
| 347 int GetVirtualRegister() { | 366 int GetVirtualRegister() { |
| 348 int vreg = code()->NextVirtualRegister(); | 367 int vreg = code()->NextVirtualRegister(); |
| 349 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { | 368 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { |
| 350 allocation_ok_ = false; | 369 allocation_ok_ = false; |
| 351 // Maintain the invariant that we return something below the maximum. | 370 // Maintain the invariant that we return something below the maximum. |
| 352 return 0; | 371 return 0; |
| 353 } | 372 } |
| 354 return vreg; | 373 return vreg; |
| 355 } | 374 } |
| 356 | 375 |
| 357 // Checks whether the value of a given virtual register is a reference. | 376 // Checks whether the value of a given virtual register is a reference. |
| 358 // TODO(titzer): rename this to IsReference. | 377 // TODO(titzer): rename this to IsReference. |
| 359 bool HasTaggedValue(int virtual_register) const; | 378 bool HasTaggedValue(int virtual_register) const; |
| 360 | 379 |
| 361 // Returns the register kind required by the given virtual register. | 380 // Returns the register kind required by the given virtual register. |
| 362 RegisterKind RequiredRegisterKind(int virtual_register) const; | 381 RegisterKind RequiredRegisterKind(int virtual_register) const; |
| 363 | 382 |
| 364 // This zone is for InstructionOperands and moves that live beyond register | 383 // This zone is for InstructionOperands and moves that live beyond register |
| 365 // allocation. | 384 // allocation. |
| 366 Zone* code_zone() const { return code()->zone(); } | 385 Zone* code_zone() const { return code()->zone(); } |
| 367 | 386 |
| 387 BitVector* assigned_registers() { return assigned_registers_; } |
| 388 BitVector* assigned_double_registers() { return assigned_double_registers_; } |
| 389 |
| 368 #ifdef DEBUG | 390 #ifdef DEBUG |
| 369 void Verify() const; | 391 void Verify() const; |
| 370 #endif | 392 #endif |
| 371 | 393 |
| 372 void MeetRegisterConstraints(); | |
| 373 void ResolvePhis(); | |
| 374 void BuildLiveRanges(); | |
| 375 void AllocateGeneralRegisters(); | |
| 376 void AllocateDoubleRegisters(); | |
| 377 void ConnectRanges(); | |
| 378 void ResolveControlFlow(); | |
| 379 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. | |
| 380 void AllocateRegisters(); | 394 void AllocateRegisters(); |
| 381 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | 395 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
| 382 bool SafePointsAreInOrder() const; | 396 bool SafePointsAreInOrder() const; |
| 383 | 397 |
| 384 // Liveness analysis support. | 398 // Liveness analysis support. |
| 385 void InitializeLivenessAnalysis(); | 399 void InitializeLivenessAnalysis(); |
| 386 BitVector* ComputeLiveOut(const InstructionBlock* block); | 400 BitVector* ComputeLiveOut(const InstructionBlock* block); |
| 387 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | 401 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
| 388 bool IsOutputRegisterOf(Instruction* instr, int index); | 402 bool IsOutputRegisterOf(Instruction* instr, int index); |
| 389 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); | 403 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); |
| 390 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | 404 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
| 391 bool ExistsUseWithoutDefinition(); | |
| 392 void MeetRegisterConstraints(const InstructionBlock* block); | 405 void MeetRegisterConstraints(const InstructionBlock* block); |
| 393 void MeetConstraintsBetween(Instruction* first, Instruction* second, | 406 void MeetConstraintsBetween(Instruction* first, Instruction* second, |
| 394 int gap_index); | 407 int gap_index); |
| 395 void MeetRegisterConstraintsForLastInstructionInBlock( | 408 void MeetRegisterConstraintsForLastInstructionInBlock( |
| 396 const InstructionBlock* block); | 409 const InstructionBlock* block); |
| 397 void ResolvePhis(const InstructionBlock* block); | 410 void ResolvePhis(const InstructionBlock* block); |
| 398 | 411 |
| 399 // Helper methods for building intervals. | 412 // Helper methods for building intervals. |
| 400 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | 413 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
| 401 bool is_tagged); | 414 bool is_tagged); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 #endif | 548 #endif |
| 536 | 549 |
| 537 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 550 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
| 538 }; | 551 }; |
| 539 | 552 |
| 540 } | 553 } |
| 541 } | 554 } |
| 542 } // namespace v8::internal::compiler | 555 } // namespace v8::internal::compiler |
| 543 | 556 |
| 544 #endif // V8_REGISTER_ALLOCATOR_H_ | 557 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |