diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/quick/arm/call_arm.cc | 214 | ||||
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 9 | ||||
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 1 |
3 files changed, 95 insertions, 129 deletions
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc index fdc609a..a30e80a 100644 --- a/compiler/dex/quick/arm/call_arm.cc +++ b/compiler/dex/quick/arm/call_arm.cc @@ -24,70 +24,62 @@ namespace art { - -/* Return the position of an ssa name within the argument list */ -int ArmMir2Lir::InPosition(int s_reg) { - int v_reg = mir_graph_->SRegToVReg(s_reg); - return v_reg - cu_->num_regs; -} - -/* - * Describe an argument. If it's already in an arg register, just leave it - * there. NOTE: all live arg registers must be locked prior to this call - * to avoid having them allocated as a temp by downstream utilities. - */ -RegLocation ArmMir2Lir::ArgLoc(RegLocation loc) { - int arg_num = InPosition(loc.s_reg_low); - if (loc.wide) { - if (arg_num == 2) { - // Bad case - half in register, half in frame. Just punt - loc.location = kLocInvalid; - } else if (arg_num < 2) { - loc.low_reg = rARM_ARG1 + arg_num; - loc.high_reg = loc.low_reg + 1; - loc.location = kLocPhysReg; - } else { - loc.location = kLocDalvikFrame; - } - } else { - if (arg_num < 3) { - loc.low_reg = rARM_ARG1 + arg_num; - loc.location = kLocPhysReg; - } else { - loc.location = kLocDalvikFrame; - } +// TODO: generalize & move to RegUtil.cc +// The number of dalvik registers passed in core registers. +constexpr int kInArgsInCoreRegs = 3; +// The core register corresponding to the first (index 0) input argument. +constexpr int kInArg0CoreReg = r1; // r0 is Method*. +// Offset, in words, for getting args from stack (even core reg args have space on stack). +constexpr int kInArgToStackOffset = 1; + +/* Lock argument if it's in register. */ +void ArmMir2Lir::LockArg(int in_position, bool wide) { + if (in_position < kInArgsInCoreRegs) { + LockTemp(kInArg0CoreReg + in_position); + } + if (wide && in_position + 1 < kInArgsInCoreRegs) { + LockTemp(kInArg0CoreReg + in_position + 1); } - return loc; } -/* - * Load an argument. If already in a register, just return. If in - * the frame, we can't use the normal LoadValue() because it assumed - * a proper frame - and we're frameless. - */ -RegLocation ArmMir2Lir::LoadArg(RegLocation loc) { - if (loc.location == kLocDalvikFrame) { - int start = (InPosition(loc.s_reg_low) + 1) * sizeof(uint32_t); - loc.low_reg = AllocTemp(); - LoadWordDisp(rARM_SP, start, loc.low_reg); - if (loc.wide) { - loc.high_reg = AllocTemp(); - LoadWordDisp(rARM_SP, start + sizeof(uint32_t), loc.high_reg); +/* Load argument into register. LockArg(in_position, wide) must have been previously called. */ +int ArmMir2Lir::LoadArg(int in_position, bool wide) { + if (in_position < kInArgsInCoreRegs) { + int low_reg = kInArg0CoreReg + in_position; + if (!wide) { + return low_reg; } - loc.location = kLocPhysReg; + int high_reg = (in_position != kInArgsInCoreRegs - 1) ? low_reg + 1 : LoadArg(in_position + 1); + return (low_reg & 0xff) | ((high_reg & 0xff) << 8); + } + int low_reg = AllocTemp(); + int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t); + if (!wide) { + LoadWordDisp(rARM_SP, offset, low_reg); + return low_reg; } - return loc; + int high_reg = AllocTemp(); + LoadBaseDispWide(rARM_SP, offset, low_reg, high_reg, INVALID_SREG); + return (low_reg & 0xff) | ((high_reg & 0xff) << 8); } -/* Lock any referenced arguments that arrive in registers */ -void ArmMir2Lir::LockLiveArgs(MIR* mir) { - int first_in = cu_->num_regs; - const int num_arg_regs = 3; // TODO: generalize & move to RegUtil.cc - for (int i = 0; i < mir->ssa_rep->num_uses; i++) { - int v_reg = mir_graph_->SRegToVReg(mir->ssa_rep->uses[i]); - int InPosition = v_reg - first_in; - if (InPosition < num_arg_regs) { - LockTemp(rARM_ARG1 + InPosition); +void ArmMir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) { + int reg = kInArg0CoreReg + in_position; + int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t); + if (!rl_dest.wide) { + if (in_position < kInArgsInCoreRegs) { + OpRegCopy(rl_dest.low_reg, reg); + } else { + LoadWordDisp(rARM_SP, offset, rl_dest.low_reg); + } + } else { + if (in_position < kInArgsInCoreRegs - 1) { + OpRegCopyWide(rl_dest.low_reg, rl_dest.high_reg, reg, reg + 1); + } else if (in_position == kInArgsInCoreRegs - 1) { + OpRegCopy(rl_dest.low_reg, reg); + LoadWordDisp(rARM_SP, offset + sizeof(uint32_t), rl_dest.high_reg); + } else { + LoadBaseDispWide(rARM_SP, offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG); } } } @@ -134,26 +126,22 @@ MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& spec return NULL; // The object is not "this" and has to be null-checked. } - OpSize size = static_cast<OpSize>(data.op_size); DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong. - bool long_or_double = (data.op_size == kLong); - bool is_object = data.is_object; - - // TODO: Generate the method using only the data in special. - RegLocation rl_obj = mir_graph_->GetSrc(mir, 0); - LockLiveArgs(mir); - rl_obj = ArmMir2Lir::ArgLoc(rl_obj); - RegLocation rl_dest; - if (long_or_double) { - rl_dest = GetReturnWide(false); - } else { - rl_dest = GetReturn(false); - } + bool wide = (data.op_size == kLong); + // Point of no return - no aborts after this ArmMir2Lir::GenPrintLabel(mir); - rl_obj = LoadArg(rl_obj); - uint32_t field_idx = mir->dalvikInsn.vC; - GenIGet(field_idx, mir->optimization_flags, size, rl_dest, rl_obj, long_or_double, is_object); + LockArg(data.object_arg); + RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false); + int reg_obj = LoadArg(data.object_arg); + if (wide) { + LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG); + } else { + LoadBaseDisp(reg_obj, data.field_offset, rl_dest.low_reg, kWord, INVALID_SREG); + } + if (data.is_volatile) { + GenMemBarrier(kLoadLoad); + } return GetNextMir(bb, mir); } @@ -164,63 +152,42 @@ MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& spec return NULL; // The object is not "this" and has to be null-checked. } - OpSize size = static_cast<OpSize>(data.op_size); DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong. - bool long_or_double = (data.op_size == kLong); - bool is_object = data.is_object; - - // TODO: Generate the method using only the data in special. - RegLocation rl_src; - RegLocation rl_obj; - LockLiveArgs(mir); - if (long_or_double) { - rl_src = mir_graph_->GetSrcWide(mir, 0); - rl_obj = mir_graph_->GetSrc(mir, 2); - } else { - rl_src = mir_graph_->GetSrc(mir, 0); - rl_obj = mir_graph_->GetSrc(mir, 1); - } - rl_src = ArmMir2Lir::ArgLoc(rl_src); - rl_obj = ArmMir2Lir::ArgLoc(rl_obj); - // Reject if source is split across registers & frame - if (rl_src.location == kLocInvalid) { - ResetRegPool(); - return NULL; - } + bool wide = (data.op_size == kLong); + // Point of no return - no aborts after this ArmMir2Lir::GenPrintLabel(mir); - rl_obj = LoadArg(rl_obj); - rl_src = LoadArg(rl_src); - uint32_t field_idx = mir->dalvikInsn.vC; - GenIPut(field_idx, mir->optimization_flags, size, rl_src, rl_obj, long_or_double, is_object); - return GetNextMir(bb, mir); -} - -MIR* ArmMir2Lir::SpecialIdentity(MIR* mir) { - RegLocation rl_src; - RegLocation rl_dest; - bool wide = (mir->ssa_rep->num_uses == 2); + LockArg(data.object_arg); + LockArg(data.src_arg, wide); + int reg_obj = LoadArg(data.object_arg); + int reg_src = LoadArg(data.src_arg, wide); + if (data.is_volatile) { + GenMemBarrier(kStoreStore); + } if (wide) { - rl_src = mir_graph_->GetSrcWide(mir, 0); - rl_dest = GetReturnWide(false); + StoreBaseDispWide(reg_obj, data.field_offset, reg_src & 0xff, reg_src >> 8); } else { - rl_src = mir_graph_->GetSrc(mir, 0); - rl_dest = GetReturn(false); + StoreBaseDisp(reg_obj, data.field_offset, reg_src, kWord); + } + if (data.is_volatile) { + GenMemBarrier(kLoadLoad); } - LockLiveArgs(mir); - rl_src = ArmMir2Lir::ArgLoc(rl_src); - if (rl_src.location == kLocInvalid) { - ResetRegPool(); - return NULL; + if (data.is_object) { + MarkGCCard(reg_src, reg_obj); } + return GetNextMir(bb, mir); +} + +MIR* ArmMir2Lir::SpecialIdentity(MIR* mir, const InlineMethod& special) { + const InlineReturnArgData& data = special.d.return_data; + DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong. + bool wide = (data.op_size == kLong); + // Point of no return - no aborts after this ArmMir2Lir::GenPrintLabel(mir); - rl_src = LoadArg(rl_src); - if (wide) { - StoreValueWide(rl_dest, rl_src); - } else { - StoreValue(rl_dest, rl_src); - } + LockArg(data.arg, wide); + RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false); + LoadArgDirect(data.arg, rl_dest); return mir; } @@ -249,8 +216,7 @@ void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, next_mir = SpecialIPut(&bb, mir, special); break; case kInlineOpReturnArg: - // TODO: Generate the method using only the data in special. - next_mir = SpecialIdentity(mir); + next_mir = SpecialIdentity(mir, special); break; default: return; diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 598da89..7ee241c 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -167,7 +167,6 @@ class ArmMir2Lir : public Mir2Lir { void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi); void OpTlsCmp(ThreadOffset offset, int val); - RegLocation ArgLoc(RegLocation loc); LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size, int s_reg); LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size); @@ -186,13 +185,13 @@ class ArmMir2Lir : public Mir2Lir { private: void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val, ConditionCode ccode); - int InPosition(int s_reg); - RegLocation LoadArg(RegLocation loc); - void LockLiveArgs(MIR* mir); + void LockArg(int in_position, bool wide = false); + int LoadArg(int in_position, bool wide = false); + void LoadArgDirect(int in_position, RegLocation rl_dest); MIR* GetNextMir(BasicBlock** p_bb, MIR* mir); MIR* SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special); MIR* SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special); - MIR* SpecialIdentity(MIR* mir); + MIR* SpecialIdentity(MIR* mir, const InlineMethod& special); LIR* LoadFPConstantValue(int r_dest, int value); void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 150794e..43928fc 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -357,6 +357,7 @@ void ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, } else { // Handle overlap if (src_hi == dest_lo) { + DCHECK_NE(src_lo, dest_hi); OpRegCopy(dest_hi, src_hi); OpRegCopy(dest_lo, src_lo); } else { |