diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 8 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 164 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 32 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 194 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 32 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 19 |
7 files changed, 213 insertions, 244 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 637cf17f64..1efdd389d8 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -282,9 +282,7 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, size_t start_index = 0; if (is_instance_call) { HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot); - HInstruction* push = new (arena_) HPushArgument(arg, 0); - current_block_->AddInstruction(push); - invoke->SetArgumentAt(0, push); + invoke->SetArgumentAt(0, arg); start_index = 1; } @@ -305,9 +303,7 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, return false; } HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type); - HInstruction* push = new (arena_) HPushArgument(arg, i); - current_block_->AddInstruction(push); - invoke->SetArgumentAt(argument_index, push); + invoke->SetArgumentAt(argument_index, arg); if (type == Primitive::kPrimLong) { i++; } diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index d459dd5f44..5c7cac1e5c 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -26,6 +26,8 @@ namespace art { +static size_t constexpr kVRegSize = 4; + class DexCompilationUnit; class CodeAllocator { @@ -323,10 +325,10 @@ class CallingConvention { return registers_[index]; } - uint8_t GetStackOffsetOf(size_t index) const { + uint8_t GetStackOffsetOf(size_t index, size_t word_size) const { // We still reserve the space for parameters passed by registers. - // Add kWordSize for the method pointer. - return index * kWordSize + kWordSize; + // Add word_size for the method pointer. + return index * kVRegSize + word_size; } private: diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index fe61333c8f..27691ac080 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -48,9 +48,11 @@ void CodeGeneratorARM::GenerateFrameEntry() { core_spill_mask_ |= (1 << LR); __ PushList((1 << LR)); - // Add the current ART method to the frame size, the return PC, and the filler. - SetFrameSize(RoundUp(( - GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kArmWordSize, + SetFrameSize(RoundUp( + (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize + + kVRegSize // filler + + kArmWordSize // Art method + + kNumberOfPushedRegistersAtEntry * kArmWordSize, kStackAlignment)); // The return PC has already been pushed on the stack. __ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize)); @@ -73,33 +75,56 @@ int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const { 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() + kArmWordSize // ART method - + (reg_number - number_of_vregs + number_of_in_vregs) * kArmWordSize; + + (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) - - kArmWordSize // filler. - - (number_of_vregs * kArmWordSize) - + (reg_number * kArmWordSize); + - kVRegSize // filler. + - (number_of_vregs * kVRegSize) + + (reg_number * kVRegSize); } } -static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; -static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 }; -static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); +Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) { + switch (type) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: { + uint32_t index = gp_index_++; + if (index < calling_convention.GetNumberOfRegisters()) { + return ArmCoreLocation(calling_convention.GetRegisterAt(index)); + } else { + return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kArmWordSize)); + } + } -class InvokeDexCallingConvention : public CallingConvention<Register> { - public: - InvokeDexCallingConvention() - : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} + case Primitive::kPrimLong: { + uint32_t index = gp_index_; + gp_index_ += 2; + if (index + 1 < calling_convention.GetNumberOfRegisters()) { + return Location::RegisterLocation(ArmManagedRegister::FromRegisterPair( + calling_convention.GetRegisterPairAt(index))); + } else if (index + 1 == calling_convention.GetNumberOfRegisters()) { + return Location::QuickParameter(index); + } else { + return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kArmWordSize)); + } + } - RegisterPair GetRegisterPairAt(size_t argument_index) { - DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); - return kParameterCorePairRegisters[argument_index]; - } + case Primitive::kPrimDouble: + case Primitive::kPrimFloat: + LOG(FATAL) << "Unimplemented parameter type " << type; + break; - private: - DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); -}; + case Primitive::kPrimVoid: + LOG(FATAL) << "Unexpected parameter type " << type; + break; + } + return Location(); +} void CodeGeneratorARM::Move32(Location destination, Location source) { if (source.Equals(destination)) { @@ -136,7 +161,7 @@ void CodeGeneratorARM::Move64(Location destination, Location source) { __ Mov(destination.AsArm().AsRegisterPairLow(), calling_convention.GetRegisterAt(argument_index)); __ ldr(destination.AsArm().AsRegisterPairHigh(), - Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize())); } else { DCHECK(source.IsDoubleStackSlot()); if (destination.AsArm().AsRegisterPair() == R1_R2) { @@ -153,12 +178,12 @@ void CodeGeneratorARM::Move64(Location destination, Location source) { if (source.IsRegister()) { __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow()); __ str(source.AsArm().AsRegisterPairHigh(), - Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1))); + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize))); } else { DCHECK(source.IsDoubleStackSlot()); __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex())); __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize))); - __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1))); + __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize))); } } else { DCHECK(destination.IsDoubleStackSlot()); @@ -176,7 +201,7 @@ void CodeGeneratorARM::Move64(Location destination, Location source) { __ str(calling_convention.GetRegisterAt(argument_index), Address(SP, destination.GetStackIndex())); __ ldr(R0, - Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize())); __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize))); } else { DCHECK(source.IsDoubleStackSlot()); @@ -417,52 +442,17 @@ void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) { codegen_->GenerateFrameExit(); } -void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) { - LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument); - InvokeDexCallingConvention calling_convention; - uint32_t argument_index = argument->GetArgumentIndex(); - switch (argument->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { - if (argument_index < calling_convention.GetNumberOfRegisters()) { - locations->SetInAt(0, ArmCoreLocation(calling_convention.GetRegisterAt(argument_index))); - } else { - locations->SetInAt( - 0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index))); - } - break; - } - case Primitive::kPrimLong: { - if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { - Location location = Location::RegisterLocation(ArmManagedRegister::FromRegisterPair( - calling_convention.GetRegisterPairAt(argument_index))); - locations->SetInAt(0, location); - } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { - locations->SetInAt(0, Location::QuickParameter(argument_index)); - } else { - locations->SetInAt( - 0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index))); - } - break; - } - default: - LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType(); - } - argument->SetLocations(locations); -} - -void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) { - // Nothing to do. -} - void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke); locations->AddTemp(ArmCoreLocation(R0)); - switch (invoke->GetType()) { + + InvokeDexCallingConventionVisitor calling_convention_visitor; + for (int i = 0; i < invoke->InputCount(); i++) { + HInstruction* input = invoke->InputAt(i); + locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType())); + } + + switch (invoke->GetType()) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: case Primitive::kPrimChar: @@ -677,39 +667,13 @@ void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) { void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - InvokeDexCallingConvention calling_convention; - uint32_t argument_index = instruction->GetIndex(); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - if (argument_index < calling_convention.GetNumberOfRegisters()) { - locations->SetOut(ArmCoreLocation(calling_convention.GetRegisterAt(argument_index))); - } else { - locations->SetOut(Location::StackSlot( - calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); - } - break; - - case Primitive::kPrimLong: - if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { - locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair( - (calling_convention.GetRegisterPairAt(argument_index))))); - } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { - // Spanning a register and a stack slot. Use the quick parameter kind. - locations->SetOut(Location::QuickParameter(argument_index)); - } else { - locations->SetOut(Location::DoubleStackSlot( - calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); - } - break; - - default: - LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType(); + Location location = parameter_visitor_.GetNextLocation(instruction->GetType()); + if (location.IsStackSlot()) { + location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); + } else if (location.IsDoubleStackSlot()) { + location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); } + locations->SetOut(location); instruction->SetLocations(locations); } diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index 3fbe63119f..ed35f94e2b 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -28,6 +28,37 @@ class CodeGeneratorARM; static constexpr size_t kArmWordSize = 4; +static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; +static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 }; +static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); + +class InvokeDexCallingConvention : public CallingConvention<Register> { + public: + InvokeDexCallingConvention() + : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} + + RegisterPair GetRegisterPairAt(size_t argument_index) { + DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); + return kParameterCorePairRegisters[argument_index]; + } + + private: + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); +}; + +class InvokeDexCallingConventionVisitor { + public: + InvokeDexCallingConventionVisitor() : gp_index_(0) {} + + Location GetNextLocation(Primitive::Type type); + + private: + InvokeDexCallingConvention calling_convention; + uint32_t gp_index_; + + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor); +}; + class LocationsBuilderARM : public HGraphVisitor { public: explicit LocationsBuilderARM(HGraph* graph, CodeGeneratorARM* codegen) @@ -42,6 +73,7 @@ class LocationsBuilderARM : public HGraphVisitor { private: CodeGeneratorARM* const codegen_; + InvokeDexCallingConventionVisitor parameter_visitor_; DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM); }; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 7507ee7ea7..114263161d 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -49,10 +49,13 @@ void CodeGeneratorX86::GenerateFrameEntry() { static const int kFakeReturnRegister = 8; core_spill_mask_ |= (1 << kFakeReturnRegister); - // Add the current ART method to the frame size, the return PC, and the filler. - SetFrameSize(RoundUp(( - GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kX86WordSize, + SetFrameSize(RoundUp( + (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize + + kVRegSize // filler + + kX86WordSize // Art method + + kNumberOfPushedRegistersAtEntry * kX86WordSize, kStackAlignment)); + // The return PC has already been pushed on the stack. __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize)); __ movl(Address(ESP, kCurrentMethodStackOffset), EAX); @@ -77,34 +80,71 @@ int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const { 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() + kX86WordSize // ART method - + (reg_number - number_of_vregs + number_of_in_vregs) * kX86WordSize; + + (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) - - kX86WordSize // filler. - - (number_of_vregs * kX86WordSize) - + (reg_number * kX86WordSize); + - kVRegSize // filler. + - (number_of_vregs * kVRegSize) + + (reg_number * kVRegSize); } } -static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX }; -static constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX }; -static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); +static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX }; +static constexpr size_t kRuntimeParameterCoreRegistersLength = + arraysize(kRuntimeParameterCoreRegisters); -class InvokeDexCallingConvention : public CallingConvention<Register> { +class InvokeRuntimeCallingConvention : public CallingConvention<Register> { public: - InvokeDexCallingConvention() - : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} - - RegisterPair GetRegisterPairAt(size_t argument_index) { - DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); - return kParameterCorePairRegisters[argument_index]; - } + InvokeRuntimeCallingConvention() + : CallingConvention(kRuntimeParameterCoreRegisters, + kRuntimeParameterCoreRegistersLength) {} private: - DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); + DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); }; +Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) { + switch (type) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: { + uint32_t index = gp_index_++; + if (index < calling_convention.GetNumberOfRegisters()) { + return X86CpuLocation(calling_convention.GetRegisterAt(index)); + } else { + return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize)); + } + } + + case Primitive::kPrimLong: { + uint32_t index = gp_index_; + gp_index_ += 2; + if (index + 1 < calling_convention.GetNumberOfRegisters()) { + return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair( + calling_convention.GetRegisterPairAt(index))); + } else if (index + 1 == calling_convention.GetNumberOfRegisters()) { + return Location::QuickParameter(index); + } else { + return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize)); + } + } + + case Primitive::kPrimDouble: + case Primitive::kPrimFloat: + LOG(FATAL) << "Unimplemented parameter type " << type; + break; + + case Primitive::kPrimVoid: + LOG(FATAL) << "Unexpected parameter type " << type; + break; + } + return Location(); +} + void CodeGeneratorX86::Move32(Location destination, Location source) { if (source.Equals(destination)) { return; @@ -140,9 +180,8 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { InvokeDexCallingConvention calling_convention; __ movl(destination.AsX86().AsRegisterPairLow(), calling_convention.GetRegisterAt(argument_index)); - __ movl(destination.AsX86().AsRegisterPairHigh(), - Address(ESP, - calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP, + calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize())); } else { DCHECK(source.IsDoubleStackSlot()); __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex())); @@ -154,14 +193,14 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { uint32_t argument_index = destination.GetQuickParameterIndex(); if (source.IsRegister()) { __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow()); - __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)), + __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), source.AsX86().AsRegisterPairHigh()); } else { DCHECK(source.IsDoubleStackSlot()); __ movl(calling_convention.GetRegisterAt(argument_index), Address(ESP, source.GetStackIndex())); __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize))); - __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)), EAX); + __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX); } } else { if (source.IsRegister()) { @@ -173,9 +212,8 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { uint32_t argument_index = source.GetQuickParameterIndex(); __ movl(Address(ESP, destination.GetStackIndex()), calling_convention.GetRegisterAt(argument_index)); - __ movl(EAX, - Address(ESP, - calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + __ movl(EAX, Address(ESP, + calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize())); __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX); } else { DCHECK(source.IsDoubleStackSlot()); @@ -413,67 +451,16 @@ void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) { __ ret(); } -static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX }; -static constexpr size_t kRuntimeParameterCoreRegistersLength = - arraysize(kRuntimeParameterCoreRegisters); - -class InvokeRuntimeCallingConvention : public CallingConvention<Register> { - public: - InvokeRuntimeCallingConvention() - : CallingConvention(kRuntimeParameterCoreRegisters, - kRuntimeParameterCoreRegistersLength) {} - - private: - DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); -}; - -void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) { - LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument); - InvokeDexCallingConvention calling_convention; - uint32_t argument_index = argument->GetArgumentIndex(); - switch (argument->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { - if (argument_index < calling_convention.GetNumberOfRegisters()) { - locations->SetInAt( - 0, X86CpuLocation(calling_convention.GetRegisterAt(argument->GetArgumentIndex()))); - } else { - locations->SetInAt( - 0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index))); - } - break; - } - case Primitive::kPrimLong: { - if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { - Location location = Location::RegisterLocation(X86ManagedRegister::FromRegisterPair( - calling_convention.GetRegisterPairAt(argument_index))); - locations->SetInAt(0, location); - } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { - locations->SetInAt(0, Location::QuickParameter(argument_index)); - } else { - locations->SetInAt( - 0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index))); - } - break; - } - default: - LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType(); - } - - argument->SetLocations(locations); -} - -void InstructionCodeGeneratorX86::VisitPushArgument(HPushArgument* argument) { - // Nothing to do. -} - void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke); locations->AddTemp(X86CpuLocation(EAX)); + + InvokeDexCallingConventionVisitor calling_convention_visitor; + for (int i = 0; i < invoke->InputCount(); i++) { + HInstruction* input = invoke->InputAt(i); + locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType())); + } + switch (invoke->GetType()) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: @@ -673,38 +660,13 @@ void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) { void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - InvokeDexCallingConvention calling_convention; - uint32_t argument_index = instruction->GetIndex(); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - if (argument_index < calling_convention.GetNumberOfRegisters()) { - locations->SetOut(X86CpuLocation(calling_convention.GetRegisterAt(argument_index))); - } else { - locations->SetOut(Location::StackSlot( - calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); - } - break; - - case Primitive::kPrimLong: - if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { - locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair( - (calling_convention.GetRegisterPairAt(argument_index))))); - } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { - locations->SetOut(Location::QuickParameter(argument_index)); - } else { - locations->SetOut(Location::DoubleStackSlot( - calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); - } - break; - - default: - LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType(); + Location location = parameter_visitor_.GetNextLocation(instruction->GetType()); + if (location.IsStackSlot()) { + location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); + } else if (location.IsDoubleStackSlot()) { + location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); } + locations->SetOut(location); instruction->SetLocations(locations); } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 9108f80d79..f22890e708 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -28,6 +28,37 @@ static constexpr size_t kX86WordSize = 4; class CodeGeneratorX86; +static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX }; +static constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX }; +static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); + +class InvokeDexCallingConvention : public CallingConvention<Register> { + public: + InvokeDexCallingConvention() + : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} + + RegisterPair GetRegisterPairAt(size_t argument_index) { + DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); + return kParameterCorePairRegisters[argument_index]; + } + + private: + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); +}; + +class InvokeDexCallingConventionVisitor { + public: + InvokeDexCallingConventionVisitor() : gp_index_(0) {} + + Location GetNextLocation(Primitive::Type type); + + private: + InvokeDexCallingConvention calling_convention; + uint32_t gp_index_; + + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor); +}; + class LocationsBuilderX86 : public HGraphVisitor { public: LocationsBuilderX86(HGraph* graph, CodeGeneratorX86* codegen) @@ -42,6 +73,7 @@ class LocationsBuilderX86 : public HGraphVisitor { private: CodeGeneratorX86* const codegen_; + InvokeDexCallingConventionVisitor parameter_visitor_; DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86); }; diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index d7e74f8262..3da9ed9461 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -230,7 +230,6 @@ class HBasicBlock : public ArenaObject { M(NewInstance) \ M(Not) \ M(ParameterValue) \ - M(PushArgument) \ M(Return) \ M(ReturnVoid) \ M(StoreLocal) \ @@ -717,24 +716,6 @@ class HNewInstance : public HTemplateInstruction<0> { DISALLOW_COPY_AND_ASSIGN(HNewInstance); }; -// HPushArgument nodes are inserted after the evaluation of an argument -// of a call. Their mere purpose is to ease the code generator's work. -class HPushArgument : public HTemplateInstruction<1> { - public: - HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) { - SetRawInputAt(0, argument); - } - - uint8_t GetArgumentIndex() const { return argument_index_; } - - DECLARE_INSTRUCTION(PushArgument) - - private: - const uint8_t argument_index_; - - DISALLOW_COPY_AND_ASSIGN(HPushArgument); -}; - class HAdd : public HBinaryOperation { public: HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right) |