diff options
author | Mingyao Yang <mingyao@google.com> | 2014-04-18 00:18:27 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-04-18 00:18:27 +0000 |
commit | 957e2a2bb9ca9a59b4fb41170b1b1a53e99bed67 (patch) | |
tree | 43f4c2518035b346d7b7ecd46c4b79d1ef45d882 /compiler | |
parent | 48a35cbc17fdf91869a7aabee3dd6290b0d045cb (diff) | |
parent | 9d46314a309aff327f9913789b5f61200c162609 (diff) | |
download | art-957e2a2bb9ca9a59b4fb41170b1b1a53e99bed67.zip art-957e2a2bb9ca9a59b4fb41170b1b1a53e99bed67.tar.gz art-957e2a2bb9ca9a59b4fb41170b1b1a53e99bed67.tar.bz2 |
Merge "Use LIRSlowPath for throwing ArrayOutOfBoundsException."
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/compiler_enums.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 12 | ||||
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 107 | ||||
-rw-r--r-- | compiler/dex/quick/gen_invoke.cc | 25 | ||||
-rw-r--r-- | compiler/dex/quick/mips/int_mips.cc | 8 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 6 | ||||
-rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 82 |
8 files changed, 169 insertions, 75 deletions
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h index 8a88d61..6f4fa3a 100644 --- a/compiler/dex/compiler_enums.h +++ b/compiler/dex/compiler_enums.h @@ -323,8 +323,6 @@ enum X86ConditionCode { std::ostream& operator<<(std::ostream& os, const X86ConditionCode& kind); enum ThrowKind { - kThrowArrayBounds, - kThrowConstantArrayBounds, kThrowNoSuchMethod, }; diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index c876b3a..d5b34a5 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -1167,9 +1167,9 @@ void ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, if (needs_range_check) { if (constant_index) { - GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds); + GenArrayBoundsCheck(mir_graph_->ConstantValue(rl_index), reg_len); } else { - GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); } FreeTemp(reg_len); } @@ -1196,7 +1196,7 @@ void ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size); @@ -1271,9 +1271,9 @@ void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, } if (needs_range_check) { if (constant_index) { - GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds); + GenArrayBoundsCheck(mir_graph_->ConstantValue(rl_index), reg_len); } else { - GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); } FreeTemp(reg_len); } @@ -1289,7 +1289,7 @@ void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset); rl_src = LoadValue(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size); diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 055f60c..68f606b 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -91,6 +91,62 @@ void Mir2Lir::AddDivZeroCheckSlowPath(LIR* branch) { AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch)); } +void Mir2Lir::GenArrayBoundsCheck(RegStorage index, RegStorage length) { + class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath { + public: + ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, RegStorage index, RegStorage length) + : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch), + index_(index), length_(length) { + } + + void Compile() OVERRIDE { + m2l_->ResetRegPool(); + m2l_->ResetDefTracking(); + GenerateTargetLabel(); + m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds), + index_, length_, true); + } + + private: + RegStorage index_; + RegStorage length_; + }; + + LIR* branch = OpCmpBranch(kCondUge, index, length, nullptr); + AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length)); +} + +void Mir2Lir::GenArrayBoundsCheck(int index, RegStorage length) { + class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath { + public: + ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, int index, RegStorage length) + : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch), + index_(index), length_(length) { + } + + void Compile() OVERRIDE { + m2l_->ResetRegPool(); + m2l_->ResetDefTracking(); + GenerateTargetLabel(); + // kArg0 will be used to hold the constant index. + if (length_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) { + m2l_->OpRegCopy(m2l_->TargetReg(kArg1), length_); + length_ = m2l_->TargetReg(kArg1); + } + m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_); + m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds), + m2l_->TargetReg(kArg0), length_, true); + } + + private: + int index_; + RegStorage length_; + }; + + LIR* branch = OpCmpImmBranch(kCondLs, length, index, nullptr); + AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length)); +} + LIR* Mir2Lir::GenNullCheck(RegStorage reg) { class NullCheckSlowPath : public Mir2Lir::LIRSlowPath { public: @@ -685,58 +741,7 @@ void Mir2Lir::HandleThrowLaunchPads() { AppendLIR(lab); ThreadOffset<4> func_offset(-1); int v1 = lab->operands[2]; - int v2 = lab->operands[3]; - const bool target_x86 = cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64; switch (lab->operands[0]) { - case kThrowConstantArrayBounds: // v1 is length reg (for Arm/Mips), v2 constant index - // v1 holds the constant array index. Mips/Arm uses v2 for length, x86 reloads. - if (target_x86) { - OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v1), - mirror::Array::LengthOffset().Int32Value()); - } else { - OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v1)); - } - // Make sure the following LoadConstant doesn't mess with kArg1. - LockTemp(TargetReg(kArg1)); - LoadConstant(TargetReg(kArg0), v2); - func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds); - break; - case kThrowArrayBounds: - // Move v1 (array index) to kArg0 and v2 (array length) to kArg1 - if (v2 != TargetReg(kArg0).GetReg()) { - OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1)); - if (target_x86) { - // x86 leaves the array pointer in v2, so load the array length that the handler expects - OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2), - mirror::Array::LengthOffset().Int32Value()); - } else { - OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2)); - } - } else { - if (v1 == TargetReg(kArg1).GetReg()) { - // Swap v1 and v2, using kArg2 as a temp - OpRegCopy(TargetReg(kArg2), RegStorage::Solo32(v1)); - if (target_x86) { - // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2), - mirror::Array::LengthOffset().Int32Value()); - } else { - OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2)); - } - OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); - } else { - if (target_x86) { - // x86 leaves the array pointer in v2; load the array length that the handler expects - OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2), - mirror::Array::LengthOffset().Int32Value()); - } else { - OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2)); - } - OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1)); - } - } - func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds); - break; case kThrowNoSuchMethod: OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1)); func_offset = diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 4aae16d..758096b 100644 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -255,12 +255,27 @@ void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(ThreadOffset<4> helper_off CallHelper(r_tgt, helper_offset, safepoint_pc); } +void Mir2Lir::CopyToArgumentRegs(RegStorage arg0, RegStorage arg1) { + if (arg1.GetReg() == TargetReg(kArg0).GetReg()) { + if (arg0.GetReg() == TargetReg(kArg1).GetReg()) { + // Swap kArg0 and kArg1 with kArg2 as temp. + OpRegCopy(TargetReg(kArg2), arg1); + OpRegCopy(TargetReg(kArg0), arg0); + OpRegCopy(TargetReg(kArg1), TargetReg(kArg2)); + } else { + OpRegCopy(TargetReg(kArg1), arg1); + OpRegCopy(TargetReg(kArg0), arg0); + } + } else { + OpRegCopy(TargetReg(kArg0), arg0); + OpRegCopy(TargetReg(kArg1), arg1); + } +} + void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset<4> helper_offset, RegStorage arg0, RegStorage arg1, bool safepoint_pc) { RegStorage r_tgt = CallHelperSetup(helper_offset); - DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg()); // check copy into arg0 won't clobber arg1 - OpRegCopy(TargetReg(kArg0), arg0); - OpRegCopy(TargetReg(kArg1), arg1); + CopyToArgumentRegs(arg0, arg1); ClobberCallerSave(); CallHelper(r_tgt, helper_offset, safepoint_pc); } @@ -268,9 +283,7 @@ void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset<4> helper_offset, RegStorage void Mir2Lir::CallRuntimeHelperRegRegImm(ThreadOffset<4> helper_offset, RegStorage arg0, RegStorage arg1, int arg2, bool safepoint_pc) { RegStorage r_tgt = CallHelperSetup(helper_offset); - DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg()); // check copy into arg0 won't clobber arg1 - OpRegCopy(TargetReg(kArg0), arg0); - OpRegCopy(TargetReg(kArg1), arg1); + CopyToArgumentRegs(arg0, arg1); LoadConstant(TargetReg(kArg2), arg2); ClobberCallerSave(); CallHelper(r_tgt, helper_offset, safepoint_pc); diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index ac0847f..968965b 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -513,7 +513,7 @@ void MipsMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } LoadBaseDispWide(reg_ptr, 0, rl_result.reg, INVALID_SREG); @@ -524,7 +524,7 @@ void MipsMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, rl_result = EvalLoc(rl_dest, reg_class, true); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size); @@ -590,7 +590,7 @@ void MipsMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, rl_src = LoadValueWide(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } @@ -598,7 +598,7 @@ void MipsMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, } else { rl_src = LoadValue(rl_src, reg_class); if (needs_range_check) { - GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, reg_len); FreeTemp(reg_len); } StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size); diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 65910e9..a7a3635 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -567,6 +567,8 @@ class Mir2Lir : public Backend { void GenDivZeroCheck(ConditionCode c_code); // reg holds divisor. void GenDivZeroCheck(RegStorage reg); + void GenArrayBoundsCheck(RegStorage index, RegStorage length); + void GenArrayBoundsCheck(int index, RegStorage length); LIR* GenNullCheck(RegStorage reg); void MarkPossibleNullPointerException(int opt_flags); void MarkPossibleStackOverflowException(); @@ -1227,6 +1229,10 @@ class Mir2Lir : public Backend { void AddDivZeroCheckSlowPath(LIR* branch); + // Copy arg0 and arg1 to kArg0 and kArg1 safely, possibly using + // kArg2 as temp. + void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1); + public: // TODO: add accessors for these. LIR* literal_list_; // Constants. diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 0b9823d..7be7c23 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -136,6 +136,8 @@ class X86Mir2Lir FINAL : public Mir2Lir { RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div); void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); void GenDivZeroCheckWide(RegStorage reg); + void GenArrayBoundsCheck(RegStorage index, RegStorage array_base, int len_offset); + void GenArrayBoundsCheck(int index, RegStorage array_base, int len_offset); void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); void GenExitSequence(); void GenSpecialExitSequence(); diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 4ffb9a4..e45e7a8 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -891,6 +891,78 @@ void X86Mir2Lir::GenDivZeroCheckWide(RegStorage reg) { FreeTemp(t_reg); } +void X86Mir2Lir::GenArrayBoundsCheck(RegStorage index, + RegStorage array_base, + int len_offset) { + class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath { + public: + ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, + RegStorage index, RegStorage array_base, int len_offset) + : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch), + index_(index), array_base_(array_base), len_offset_(len_offset) { + } + + void Compile() OVERRIDE { + m2l_->ResetRegPool(); + m2l_->ResetDefTracking(); + GenerateTargetLabel(); + // Load array length to array_base_. + m2l_->OpRegMem(kOpMov, array_base_, array_base_, len_offset_); + m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds), + index_, array_base_, true); + } + + private: + RegStorage index_; + RegStorage array_base_; + int len_offset_; + }; + + OpRegMem(kOpCmp, index, array_base, len_offset); + LIR* branch = OpCondBranch(kCondUge, nullptr); + AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, + index, array_base, len_offset)); +} + +void X86Mir2Lir::GenArrayBoundsCheck(int index, + RegStorage array_base, + int len_offset) { + class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath { + public: + ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, + int index, RegStorage array_base, int len_offset) + : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch), + index_(index), array_base_(array_base), len_offset_(len_offset) { + } + + void Compile() OVERRIDE { + m2l_->ResetRegPool(); + m2l_->ResetDefTracking(); + GenerateTargetLabel(); + // kArg0 will be used to hold the constant index. + if (array_base_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) { + m2l_->OpRegCopy(m2l_->TargetReg(kArg1), array_base_); + array_base_ = m2l_->TargetReg(kArg1); + } + m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_); + // Load array length to kArg1. + m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_); + m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds), + m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true); + } + + private: + int index_; + RegStorage array_base_; + int len_offset_; + }; + + NewLIR3(IS_SIMM8(index) ? kX86Cmp32MI8 : kX86Cmp32MI, array_base.GetReg(), len_offset, index); + LIR* branch = OpCondBranch(kCondLs, nullptr); + AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, + index, array_base, len_offset)); +} + // Test suspend flag, return target of taken suspend branch LIR* X86Mir2Lir::OpTestSuspend(LIR* target) { OpTlsCmp(Thread::ThreadFlagsOffset<4>(), 0); @@ -1348,10 +1420,9 @@ void X86Mir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) { if (constant_index) { - GenMemImmedCheck(kCondLs, rl_array.reg, len_offset, - constant_index_value, kThrowConstantArrayBounds); + GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset); } else { - GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset); } } rl_result = EvalLoc(rl_dest, reg_class, true); @@ -1400,10 +1471,9 @@ void X86Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) { if (constant_index) { - GenMemImmedCheck(kCondLs, rl_array.reg, len_offset, - constant_index_value, kThrowConstantArrayBounds); + GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset); } else { - GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds); + GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset); } } if ((size == kLong) || (size == kDouble)) { |