diff options
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 21 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.h | 16 | ||||
| -rw-r--r-- | test/015-switch/src/Main.java | 109 |
3 files changed, 138 insertions, 8 deletions
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 3df55ae851..61e6b4bc5b 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -680,6 +680,15 @@ void JumpTableARMVIXL::EmitTable(CodeGeneratorARMVIXL* codegen) { CodeBufferCheckScope::kMaximumSize); // TODO(VIXL): Check that using lower case bind is fine here. codegen->GetVIXLAssembler()->bind(&table_start_); + for (uint32_t i = 0; i < num_entries; i++) { + codegen->GetVIXLAssembler()->place(bb_addresses_[i].get()); + } +} + +void JumpTableARMVIXL::FixTable(CodeGeneratorARMVIXL* codegen) { + uint32_t num_entries = switch_instr_->GetNumEntries(); + DCHECK_GE(num_entries, kPackedSwitchCompareJumpThreshold); + const ArenaVector<HBasicBlock*>& successors = switch_instr_->GetBlock()->GetSuccessors(); for (uint32_t i = 0; i < num_entries; i++) { vixl32::Label* target_label = codegen->GetLabelOf(successors[i]); @@ -691,21 +700,21 @@ void JumpTableARMVIXL::EmitTable(CodeGeneratorARMVIXL* codegen) { } DCHECK_GT(jump_offset, std::numeric_limits<int32_t>::min()); DCHECK_LE(jump_offset, std::numeric_limits<int32_t>::max()); - vixl32::Literal<int32_t> literal(jump_offset); - codegen->GetVIXLAssembler()->place(&literal); + + bb_addresses_[i].get()->UpdateValue(jump_offset, &codegen->GetVIXLAssembler()->GetBuffer()); } } -void CodeGeneratorARMVIXL::EmitJumpTables() { +void CodeGeneratorARMVIXL::FixJumpTables() { for (auto&& jump_table : jump_tables_) { - jump_table->EmitTable(this); + jump_table->FixTable(this); } } #define __ reinterpret_cast<ArmVIXLAssembler*>(GetAssembler())->GetVIXLAssembler()-> // NOLINT void CodeGeneratorARMVIXL::Finalize(CodeAllocator* allocator) { - EmitJumpTables(); + FixJumpTables(); GetAssembler()->FinalizeCode(); CodeGenerator::Finalize(allocator); } @@ -6113,6 +6122,8 @@ void InstructionCodeGeneratorARMVIXL::VisitPackedSwitch(HPackedSwitch* switch_in vixl32::Register target_address = table_base; __ Add(target_address, table_base, jump_offset); __ Bx(target_address); + + jump_table->EmitTable(codegen_); } } diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index e8bc2a9b88..302ee38368 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -194,16 +194,28 @@ class CodeGeneratorARMVIXL; class JumpTableARMVIXL : public DeletableArenaObject<kArenaAllocSwitchTable> { public: + typedef vixl::aarch32::Literal<int32_t> IntLiteral; + explicit JumpTableARMVIXL(HPackedSwitch* switch_instr) - : switch_instr_(switch_instr), table_start_() {} + : switch_instr_(switch_instr), + table_start_(), + bb_addresses_(switch_instr->GetArena()->Adapter(kArenaAllocCodeGenerator)) { + uint32_t num_entries = switch_instr_->GetNumEntries(); + for (uint32_t i = 0; i < num_entries; i++) { + IntLiteral *lit = new IntLiteral(0); + bb_addresses_.emplace_back(lit); + } + } vixl::aarch32::Label* GetTableStartLabel() { return &table_start_; } void EmitTable(CodeGeneratorARMVIXL* codegen); + void FixTable(CodeGeneratorARMVIXL* codegen); private: HPackedSwitch* const switch_instr_; vixl::aarch32::Label table_start_; + ArenaVector<std::unique_ptr<IntLiteral>> bb_addresses_; DISALLOW_COPY_AND_ASSIGN(JumpTableARMVIXL); }; @@ -513,7 +525,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; } - void EmitJumpTables(); + void FixJumpTables(); void GenerateMemoryBarrier(MemBarrierKind kind); void Finalize(CodeAllocator* allocator) OVERRIDE; void SetupBlockedRegisters() const OVERRIDE; diff --git a/test/015-switch/src/Main.java b/test/015-switch/src/Main.java index 2a7995a075..2b724a1e57 100644 --- a/test/015-switch/src/Main.java +++ b/test/015-switch/src/Main.java @@ -113,7 +113,7 @@ public class Main { } // Long packed-switch that might lead to not creating chained-ifs. - public static void packedSwitch7(int value) { + public static long packedSwitch7(int value) { switch (value) { case 1: System.out.println(1); break; @@ -148,6 +148,113 @@ public class Main { default: System.out.println("default"); break; } + + // Jump tables previously were emitted in the end of the method code buffer. The + // following boilerplate code aims to fill the emitted code buffer extensively + // and check that even for big method jump table is correctly emitted, its address + // is within a range of corresponded pc-relative instructions (this applies to + // ARM mainly). + long temp = value; + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + temp = Long.rotateLeft(temp, value); + + return temp; } // Sparse switch, just leave a gap. |