From f583e5976e1de9aa206fb8de4f91000180685066 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Mon, 7 Apr 2014 13:20:42 +0100 Subject: Add support for taking parameters in optimizing compiler. - Fix stack layout to mimic Quick's. - Implement some sub operations. Change-Id: I8cf75a4d29b662381a64f02c0bc61d859482fc4e --- compiler/optimizing/builder.cc | 135 +++++++++++++++++++++++++----- compiler/optimizing/builder.h | 11 ++- compiler/optimizing/code_generator.cc | 13 ++- compiler/optimizing/code_generator_arm.cc | 83 ++++++++++++++++-- compiler/optimizing/code_generator_x86.cc | 83 +++++++++++++++--- compiler/optimizing/nodes.h | 60 ++++++++++++- 6 files changed, 336 insertions(+), 49 deletions(-) (limited to 'compiler') diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index d90405a..f89583d 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -25,7 +25,8 @@ namespace art { -void HGraphBuilder::InitializeLocals(int count) { +void HGraphBuilder::InitializeLocals(uint16_t count) { + graph_->SetNumberOfVRegs(count); locals_.SetSize(count); for (int i = 0; i < count; i++) { HLocal* local = new (arena_) HLocal(i); @@ -34,11 +35,54 @@ void HGraphBuilder::InitializeLocals(int count) { } } +bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { + // dex_compilation_unit_ is null only when unit testing. + if (dex_compilation_unit_ == nullptr) { + return true; + } + + graph_->SetNumberOfInVRegs(number_of_parameters); + const char* shorty = dex_compilation_unit_->GetShorty(); + int locals_index = locals_.Size() - number_of_parameters; + HBasicBlock* first_block = entry_block_->GetSuccessors()->Get(0); + int parameter_index = 0; + + if (!dex_compilation_unit_->IsStatic()) { + // Add the implicit 'this' argument, not expressed in the signature. + HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++); + first_block->AddInstruction(parameter); + HLocal* local = GetLocalAt(locals_index++); + first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter)); + number_of_parameters--; + } + + uint32_t pos = 1; + for (int i = 0; i < number_of_parameters; i++) { + switch (shorty[pos++]) { + case 'F': + case 'D': + case 'J': { + return false; + } + + default: { + // integer and reference parameters. + HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++); + first_block->AddInstruction(parameter); + HLocal* local = GetLocalAt(locals_index++); + // Store the parameter value in the local that the dex code will use + // to reference that parameter. + first_block->AddInstruction(new (arena_) HStoreLocal(local, parameter)); + break; + } + } + } + return true; +} + static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) { if (code_item.tries_size_ > 0) { return false; - } else if (code_item.ins_size_ > 0) { - return false; } return true; } @@ -66,6 +110,10 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { // start a new block, and create these blocks. ComputeBranchTargets(code_ptr, code_end); + if (!InitializeParameters(code_item.ins_size_)) { + return nullptr; + } + size_t dex_offset = 0; while (code_ptr < code_end) { // Update the current block if dex_offset starts a new block. @@ -139,6 +187,44 @@ HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const { return branch_targets_.Get(index); } +template +void HGraphBuilder::Binop_32x(const Instruction& instruction) { + HInstruction* first = LoadLocal(instruction.VRegB()); + HInstruction* second = LoadLocal(instruction.VRegC()); + current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + +template +void HGraphBuilder::Binop_12x(const Instruction& instruction) { + HInstruction* first = LoadLocal(instruction.VRegA()); + HInstruction* second = LoadLocal(instruction.VRegB()); + current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + +template +void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) { + HInstruction* first = LoadLocal(instruction.VRegB()); + HInstruction* second = GetConstant(instruction.VRegC_22s()); + if (reverse) { + std::swap(first, second); + } + current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + +template +void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) { + HInstruction* first = LoadLocal(instruction.VRegB()); + HInstruction* second = GetConstant(instruction.VRegC_22b()); + if (reverse) { + std::swap(first, second); + } + current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) { if (current_block_ == nullptr) { return true; // Dead code @@ -185,7 +271,8 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_ break; } - case Instruction::RETURN: { + case Instruction::RETURN: + case Instruction::RETURN_OBJECT: { HInstruction* value = LoadLocal(instruction.VRegA()); current_block_->AddInstruction(new (arena_) HReturn(value)); current_block_->AddSuccessor(exit_block_); @@ -250,34 +337,42 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_ } case Instruction::ADD_INT: { - HInstruction* first = LoadLocal(instruction.VRegB()); - HInstruction* second = LoadLocal(instruction.VRegC()); - current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second)); - UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); + Binop_32x(instruction); + break; + } + + case Instruction::SUB_INT: { + Binop_32x(instruction); break; } case Instruction::ADD_INT_2ADDR: { - HInstruction* first = LoadLocal(instruction.VRegA()); - HInstruction* second = LoadLocal(instruction.VRegB()); - current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second)); - UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); + Binop_12x(instruction); + break; + } + + case Instruction::SUB_INT_2ADDR: { + Binop_12x(instruction); break; } case Instruction::ADD_INT_LIT16: { - HInstruction* first = LoadLocal(instruction.VRegB()); - HInstruction* second = GetConstant(instruction.VRegC_22s()); - current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second)); - UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); + Binop_22s(instruction, false); + break; + } + + case Instruction::RSUB_INT: { + Binop_22s(instruction, true); break; } case Instruction::ADD_INT_LIT8: { - HInstruction* first = LoadLocal(instruction.VRegB()); - HInstruction* second = GetConstant(instruction.VRegC_22b()); - current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second)); - UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); + Binop_22b(instruction, false); + break; + } + + case Instruction::RSUB_INT_LIT8: { + Binop_22b(instruction, true); break; } diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 46ca9aa..df64d71 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -66,11 +66,20 @@ class HGraphBuilder : public ValueObject { HIntConstant* GetConstant0(); HIntConstant* GetConstant1(); HIntConstant* GetConstant(int constant); - void InitializeLocals(int count); + void InitializeLocals(uint16_t count); HLocal* GetLocalAt(int register_index) const; void UpdateLocal(int register_index, HInstruction* instruction) const; HInstruction* LoadLocal(int register_index) const; + // Temporarily returns whether the compiler supports the parameters + // of the method. + bool InitializeParameters(uint16_t number_of_parameters); + + template void Binop_32x(const Instruction& instruction); + template void Binop_12x(const Instruction& instruction); + template void Binop_22b(const Instruction& instruction, bool reverse); + template void Binop_22s(const Instruction& instruction, bool reverse); + ArenaAllocator* const arena_; // A list of the size of the dex code holding block information for diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index d6295db..40a7b6f 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -30,7 +30,6 @@ namespace art { void CodeGenerator::Compile(CodeAllocator* allocator) { - frame_size_ = GetGraph()->GetMaximumNumberOfOutVRegs() * GetWordSize(); const GrowableArray* blocks = GetGraph()->GetBlocks(); DCHECK(blocks->Get(0) == GetGraph()->GetEntryBlock()); DCHECK(GoesToNextBlock(GetGraph()->GetEntryBlock(), blocks->Get(1))); @@ -47,16 +46,14 @@ void CodeGenerator::Compile(CodeAllocator* allocator) { void CodeGenerator::CompileEntryBlock() { HGraphVisitor* location_builder = GetLocationBuilder(); HGraphVisitor* instruction_visitor = GetInstructionVisitor(); - // The entry block contains all locals for this method. By visiting the entry block, - // we're computing the required frame size. - for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) { - HInstruction* current = it.Current(); - // Instructions in the entry block should not generate code. - if (kIsDebugBuild) { + if (kIsDebugBuild) { + for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) { + HInstruction* current = it.Current(); + // Instructions in the entry block should not generate code. current->Accept(location_builder); DCHECK(current->GetLocations() == nullptr); + current->Accept(instruction_visitor); } - current->Accept(instruction_visitor); } GenerateFrameEntry(); } diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index cb77f57..2364bc8 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -38,9 +38,11 @@ void CodeGeneratorARM::GenerateFrameEntry() { core_spill_mask_ |= (1 << LR); __ PushList((1 << LR)); - // Add the current ART method to the frame size and the return PC. - SetFrameSize(RoundUp(GetFrameSize() + 2 * kArmWordSize, kStackAlignment)); - // The retrn PC has already been pushed on the stack. + // Add the current ART method to the frame size, the return PC, and the filler. + SetFrameSize(RoundUp(( + GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kArmWordSize, + kStackAlignment)); + // The return PC has already been pushed on the stack. __ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize)); __ str(R0, Address(SP, 0)); } @@ -55,7 +57,20 @@ void CodeGeneratorARM::Bind(Label* label) { } int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const { - return (GetGraph()->GetMaximumNumberOfOutVRegs() + local->GetRegNumber()) * kArmWordSize; + 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() + kArmWordSize // ART method + + (reg_number - number_of_vregs + number_of_in_vregs) * kArmWordSize; + } 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); + } } void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) { @@ -187,18 +202,18 @@ void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) { static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); -class InvokeStaticCallingConvention : public CallingConvention { +class InvokeDexCallingConvention : public CallingConvention { public: - InvokeStaticCallingConvention() + InvokeDexCallingConvention() : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} private: - DISALLOW_COPY_AND_ASSIGN(InvokeStaticCallingConvention); + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); }; void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument); - InvokeStaticCallingConvention calling_convention; + InvokeDexCallingConvention calling_convention; if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) { Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex())); locations->SetInAt(0, location); @@ -211,7 +226,7 @@ void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) { void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) { uint8_t argument_index = argument->GetArgumentIndex(); - InvokeStaticCallingConvention calling_convention; + InvokeDexCallingConvention calling_convention; size_t parameter_registers = calling_convention.GetNumberOfRegisters(); LocationSummary* locations = argument->GetLocations(); if (argument_index >= parameter_registers) { @@ -287,6 +302,34 @@ void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) { } } +void LocationsBuilderARM::VisitSub(HSub* sub) { + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub); + switch (sub->GetResultType()) { + case Primitive::kPrimInt: { + locations->SetInAt(0, Location(R0)); + locations->SetInAt(1, Location(R1)); + locations->SetOut(Location(R0)); + break; + } + default: + LOG(FATAL) << "Unimplemented"; + } + sub->SetLocations(locations); +} + +void InstructionCodeGeneratorARM::VisitSub(HSub* sub) { + LocationSummary* locations = sub->GetLocations(); + switch (sub->GetResultType()) { + case Primitive::kPrimInt: + __ sub(locations->Out().reg(), + locations->InAt(0).reg(), + ShifterOperand(locations->InAt(1).reg())); + break; + default: + LOG(FATAL) << "Unimplemented"; + } +} + static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1 }; static constexpr size_t kRuntimeParameterCoreRegistersLength = arraysize(kRuntimeParameterCoreRegisters); @@ -319,5 +362,27 @@ void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) { codegen_->RecordPcInfo(instruction->GetDexPc()); } +void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) { + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); + InvokeDexCallingConvention calling_convention; + uint32_t argument_index = instruction->GetIndex(); + if (argument_index < calling_convention.GetNumberOfRegisters()) { + locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index))); + } else { + locations->SetOut(Location(R0)); + } + instruction->SetLocations(locations); +} + +void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) { + LocationSummary* locations = instruction->GetLocations(); + InvokeDexCallingConvention calling_convention; + uint8_t argument_index = instruction->GetIndex(); + if (argument_index >= calling_convention.GetNumberOfRegisters()) { + uint8_t offset = calling_convention.GetStackOffsetOf(argument_index); + __ ldr(locations->Out().reg(), Address(SP, offset + codegen_->GetFrameSize())); + } +} + } // namespace arm } // namespace art diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index c695e26..540a72a 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -39,11 +39,13 @@ void CodeGeneratorX86::GenerateFrameEntry() { static const int kFakeReturnRegister = 8; core_spill_mask_ |= (1 << kFakeReturnRegister); - // Add the current ART method to the frame size and the return PC. - SetFrameSize(RoundUp(GetFrameSize() + 2 * kX86WordSize, kStackAlignment)); + // Add the current ART method to the frame size, the return PC, and the filler. + SetFrameSize(RoundUp(( + GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kX86WordSize, + kStackAlignment)); // The return PC has already been pushed on the stack. __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize)); - __ movl(Address(ESP, 0), EAX); + __ movl(Address(ESP, kCurrentMethodStackOffset), EAX); } void CodeGeneratorX86::GenerateFrameExit() { @@ -59,7 +61,20 @@ void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) { } int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const { - return (GetGraph()->GetMaximumNumberOfOutVRegs() + local->GetRegNumber()) * kX86WordSize; + 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() + kX86WordSize // ART method + + (reg_number - number_of_vregs + number_of_in_vregs) * kX86WordSize; + } 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); + } } void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) { @@ -122,7 +137,6 @@ void LocationsBuilderX86::VisitLocal(HLocal* local) { void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) { DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock()); - codegen_->SetFrameSize(codegen_->GetFrameSize() + kX86WordSize); } void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) { @@ -190,13 +204,13 @@ void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) { static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX }; static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); -class InvokeStaticCallingConvention : public CallingConvention { +class InvokeDexCallingConvention : public CallingConvention { public: - InvokeStaticCallingConvention() + InvokeDexCallingConvention() : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} private: - DISALLOW_COPY_AND_ASSIGN(InvokeStaticCallingConvention); + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); }; static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX }; @@ -215,7 +229,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention { void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument); - InvokeStaticCallingConvention calling_convention; + InvokeDexCallingConvention calling_convention; if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) { Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex())); locations->SetInAt(0, location); @@ -228,7 +242,7 @@ void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) { void InstructionCodeGeneratorX86::VisitPushArgument(HPushArgument* argument) { uint8_t argument_index = argument->GetArgumentIndex(); - InvokeStaticCallingConvention calling_convention; + InvokeDexCallingConvention calling_convention; size_t parameter_registers = calling_convention.GetNumberOfRegisters(); if (argument_index >= parameter_registers) { uint8_t offset = calling_convention.GetStackOffsetOf(argument_index); @@ -298,6 +312,33 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { } } +void LocationsBuilderX86::VisitSub(HSub* sub) { + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub); + switch (sub->GetResultType()) { + case Primitive::kPrimInt: { + locations->SetInAt(0, Location(EAX)); + locations->SetInAt(1, Location(ECX)); + locations->SetOut(Location(EAX)); + break; + } + default: + LOG(FATAL) << "Unimplemented"; + } + sub->SetLocations(locations); +} + +void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { + LocationSummary* locations = sub->GetLocations(); + switch (sub->GetResultType()) { + case Primitive::kPrimInt: + DCHECK_EQ(locations->InAt(0).reg(), locations->Out().reg()); + __ subl(locations->InAt(0).reg(), locations->InAt(1).reg()); + break; + default: + LOG(FATAL) << "Unimplemented"; + } +} + void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); locations->SetOut(Location(EAX)); @@ -316,5 +357,27 @@ void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) { codegen_->RecordPcInfo(instruction->GetDexPc()); } +void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) { + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); + InvokeDexCallingConvention calling_convention; + uint32_t argument_index = instruction->GetIndex(); + if (argument_index < calling_convention.GetNumberOfRegisters()) { + locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index))); + } else { + locations->SetOut(Location(EAX)); + } + instruction->SetLocations(locations); +} + +void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) { + LocationSummary* locations = instruction->GetLocations(); + InvokeDexCallingConvention calling_convention; + uint32_t argument_index = instruction->GetIndex(); + if (argument_index >= calling_convention.GetNumberOfRegisters()) { + uint8_t offset = calling_convention.GetStackOffsetOf(argument_index); + __ movl(locations->Out().reg(), Address(ESP, offset + codegen_->GetFrameSize())); + } +} + } // namespace x86 } // namespace art diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 830d0c7..d1f672f 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -42,6 +42,8 @@ class HGraph : public ArenaObject { blocks_(arena, kDefaultNumberOfBlocks), dominator_order_(arena, kDefaultNumberOfBlocks), maximum_number_of_out_vregs_(0), + number_of_vregs_(0), + number_of_in_vregs_(0), current_instruction_id_(0) { } ArenaAllocator* GetArena() const { return arena_; } @@ -68,6 +70,23 @@ class HGraph : public ArenaObject { maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_); } + void SetNumberOfVRegs(uint16_t number_of_vregs) { + number_of_vregs_ = number_of_vregs; + } + + uint16_t GetNumberOfVRegs() const { + return number_of_vregs_; + } + + void SetNumberOfInVRegs(uint16_t value) { + number_of_in_vregs_ = value; + } + + uint16_t GetNumberOfInVRegs() const { + return number_of_in_vregs_; + } + + private: HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; void VisitBlockForDominatorTree(HBasicBlock* block, @@ -90,9 +109,15 @@ class HGraph : public ArenaObject { HBasicBlock* entry_block_; HBasicBlock* exit_block_; - // The maximum number of arguments passed to a HInvoke in this graph. + // The maximum number of virtual registers arguments passed to a HInvoke in this graph. uint16_t maximum_number_of_out_vregs_; + // The number of virtual registers in this method. Contains the parameters. + uint16_t number_of_vregs_; + + // The number of virtual registers used by parameters of this method. + uint16_t number_of_in_vregs_; + // The current id to assign to a newly added instruction. See HInstruction.id_. int current_instruction_id_; @@ -202,10 +227,12 @@ class HBasicBlock : public ArenaObject { M(LoadLocal) \ M(Local) \ M(NewInstance) \ + M(ParameterValue) \ M(PushArgument) \ M(Return) \ M(ReturnVoid) \ M(StoreLocal) \ + M(Sub) \ #define FORWARD_DECLARATION(type) class H##type; FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) @@ -682,6 +709,37 @@ class HAdd : public HBinaryOperation { DISALLOW_COPY_AND_ASSIGN(HAdd); }; +class HSub : public HBinaryOperation { + public: + HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right) + : HBinaryOperation(result_type, left, right) {} + + virtual bool IsCommutative() { return false; } + + DECLARE_INSTRUCTION(Sub); + + private: + DISALLOW_COPY_AND_ASSIGN(HSub); +}; + +// The value of a parameter in this method. Its location depends on +// the calling convention. +class HParameterValue : public HTemplateInstruction<0> { + public: + explicit HParameterValue(uint8_t index) : index_(index) {} + + uint8_t GetIndex() const { return index_; } + + DECLARE_INSTRUCTION(ParameterValue); + + private: + // The index of this parameter in the parameters list. Must be less + // than HGraph::number_of_in_vregs_; + const uint8_t index_; + + DISALLOW_COPY_AND_ASSIGN(HParameterValue); +}; + class HGraphVisitor : public ValueObject { public: explicit HGraphVisitor(HGraph* graph) : graph_(graph) { } -- cgit v1.1