diff options
Diffstat (limited to 'compiler/dex/quick/gen_common.cc')
| -rw-r--r-- | compiler/dex/quick/gen_common.cc | 107 |
1 files changed, 51 insertions, 56 deletions
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index bb19516b96..1847921ccb 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -91,62 +91,6 @@ 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: @@ -741,7 +685,58 @@ 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 = |