Also do some refactoring to have this code be just in CodeGenerator.
Change-Id: I88de109889138af8d60027973c12a64bee813cb7
DCHECK_EQ(frame_size_, kUninitializedFrameSize);
ComputeFrameSize(GetGraph()->GetMaximumNumberOfOutVRegs()
- + GetGraph()->GetNumberOfVRegs()
+ + GetGraph()->GetNumberOfLocalVRegs()
+ GetGraph()->GetNumberOfTemporaries()
+ 1 /* filler */);
GenerateFrameEntry();
return -1;
}
+void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots) {
+ SetFrameSize(RoundUp(
+ number_of_spill_slots * kVRegSize
+ + kVRegSize // Art method
+ + FrameEntrySpillSize(),
+ kStackAlignment));
+}
+
+Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const {
+ uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+ // Use the temporary region (right below the dex registers).
+ int32_t slot = GetFrameSize() - FrameEntrySpillSize()
+ - kVRegSize // filler
+ - (number_of_locals * kVRegSize)
+ - ((1 + temp->GetIndex()) * kVRegSize);
+ return Location::StackSlot(slot);
+}
+
+int32_t CodeGenerator::GetStackSlot(HLocal* local) const {
+ uint16_t reg_number = local->GetRegNumber();
+ uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+ if (reg_number >= number_of_locals) {
+ // Local is a parameter of the method. It is stored in the caller's frame.
+ return GetFrameSize() + kVRegSize // ART method
+ + (reg_number - number_of_locals) * kVRegSize;
+ } else {
+ // Local is a temporary in this method. It is stored in this method's frame.
+ return GetFrameSize() - FrameEntrySpillSize()
+ - kVRegSize // filler.
+ - (number_of_locals * kVRegSize)
+ + (reg_number * kVRegSize);
+ }
+}
void CodeGenerator::AllocateRegistersLocally(HInstruction* instruction) const {
LocationSummary* locations = instruction->GetLocations();
virtual HGraphVisitor* GetInstructionVisitor() = 0;
virtual Assembler* GetAssembler() = 0;
virtual size_t GetWordSize() const = 0;
- virtual void ComputeFrameSize(size_t number_of_spill_slots) = 0;
+ void ComputeFrameSize(size_t number_of_spill_slots);
+ virtual size_t FrameEntrySpillSize() const = 0;
+ int32_t GetStackSlot(HLocal* local) const;
+ Location GetTemporaryLocation(HTemporary* temp) const;
uint32_t GetFrameSize() const { return frame_size_; }
void SetFrameSize(uint32_t size) { frame_size_ = size; }
size_t AllocateFreeRegisterInternal(bool* blocked_registers, size_t number_of_registers) const;
virtual Location GetStackLocation(HLoadLocal* load) const = 0;
- virtual Location GetTemporaryLocation(HTemporary* temp) const = 0;
// Frame size required for this method.
uint32_t frame_size_;
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
+size_t CodeGeneratorARM::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kArmWordSize;
+}
+
static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
return blocked_registers + kNumberOfAllocIds;
}
assembler_(codegen->GetAssembler()),
codegen_(codegen) {}
-void CodeGeneratorARM::ComputeFrameSize(size_t number_of_spill_slots) {
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kArmWordSize,
- kStackAlignment));
-}
-
void CodeGeneratorARM::GenerateFrameEntry() {
core_spill_mask_ |= (1 << LR | 1 << R6 | 1 << R7);
__ PushList(1 << LR | 1 << R6 | 1 << R7);
__ Bind(label);
}
-Location CodeGeneratorARM::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
- - kVRegSize // filler.
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
Location CodeGeneratorARM::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
explicit CodeGeneratorARM(HGraph* graph);
virtual ~CodeGeneratorARM() { }
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
return kArmWordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
Primitive::Type type, bool* blocked_registers) const OVERRIDE;
virtual size_t GetNumberOfRegisters() const OVERRIDE;
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
return kNumberOfCoreRegisters;
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
-void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kX86WordSize,
- kStackAlignment));
+size_t CodeGeneratorX86::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kX86WordSize;
}
static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
__ movl(reg, Address(ESP, kCurrentMethodStackOffset));
}
-Location CodeGeneratorX86::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
- - kVRegSize // filler.
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
-
Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
explicit CodeGeneratorX86(HGraph* graph);
virtual ~CodeGeneratorX86() { }
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
return kX86WordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
virtual ManagedRegister AllocateFreeRegister(
Primitive::Type type, bool* blocked_registers) const OVERRIDE;
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
return kNumberOfCpuRegisters;
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
+size_t CodeGeneratorX86_64::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kX86_64WordSize;
+}
+
InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
: HGraphVisitor(graph),
assembler_(codegen->GetAssembler()),
blocked_registers[R15] = true;
}
-void CodeGeneratorX86_64::ComputeFrameSize(size_t number_of_spill_slots) {
- // Add the current ART method to the frame size, the return PC, and the filler.
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // filler
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kX86_64WordSize,
- kStackAlignment));
-}
-
void CodeGeneratorX86_64::GenerateFrameEntry() {
// Create a fake register to mimic Quick.
static const int kFakeReturnRegister = 16;
__ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
}
-Location CodeGeneratorX86_64::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86_64::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
explicit CodeGeneratorX86_64(HGraph* graph);
virtual ~CodeGeneratorX86_64() {}
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
return kX86_64WordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
return &move_resolver_;
}
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfRegisters() const OVERRIDE {
return kNumberOfRegIds;
return number_of_in_vregs_;
}
+ uint16_t GetNumberOfLocalVRegs() const {
+ return number_of_vregs_ - number_of_in_vregs_;
+ }
+
const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
return reverse_post_order_;
}
Forced GC
Forced GC
Forced GC
+Forced GC
if (m.$opt$TestOtherParameter(new Main()) == m) {
throw new Error("Unexpected value returned");
}
+
+ if (m.$opt$TestReturnNewObject(m) == m) {
+ throw new Error("Unexpected value returned");
+ }
}
static int $opt$TestInvokeIntParameter(int param) {
return other;
}
+ Object $opt$TestReturnNewObject(Object other) {
+ Object o = new Object();
+ forceGCStaticMethod();
+ return o;
+ }
+
public static void $opt$TestInvokeStatic() {
printStaticMethod();
printStaticMethodWith2Args(1, 2);