diff options
| author | 2012-11-28 17:22:17 -0800 | |
|---|---|---|
| committer | 2012-11-28 17:38:24 -0800 | |
| commit | 5f61f678d0b61cda8cac954fb176edbfdb1a831e (patch) | |
| tree | a508e465a79ee97e00f9a5ff2ab35cd8efb636a6 /src/compiler/codegen | |
| parent | bc43860b7e5326264ada842c35a840dd4cda8120 (diff) | |
Workaround for Issue 7250540
There's a problem (originating with Dalvik's failure to properly type constants) with
Dalvik vregs that are used in both reference and floating point situations. In
particular, if a constant zero is used in a floating point context, the verifier in
some cases will treat it as a null pointer for the purposes generating the GC map.
If that vreg ends up promoted to a floating point value, the run-time value of that
vreg will not be found during garbage collection. As a quick workaround, this
CL causes the compiler to detect this special case of an immediate zero being loaded
into a promoted floating point register and also store a zero in the core/ref identity
of that vreg.
Note, the CL also excludes references from store elimination.
Change-Id: I72f0a96744823ff9c5a2bd961a5e39ac4bbc707b
Diffstat (limited to 'src/compiler/codegen')
| -rw-r--r-- | src/compiler/codegen/codegen.h | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/gen_loadstore.cc | 28 | ||||
| -rw-r--r-- | src/compiler/codegen/mir_to_gbc.cc | 1 | ||||
| -rw-r--r-- | src/compiler/codegen/mir_to_lir.cc | 2 | ||||
| -rw-r--r-- | src/compiler/codegen/ralloc_util.cc | 2 | ||||
| -rw-r--r-- | src/compiler/codegen/ralloc_util.h | 1 |
6 files changed, 35 insertions, 2 deletions
diff --git a/src/compiler/codegen/codegen.h b/src/compiler/codegen/codegen.h index 9dfa6091c3..06981568b8 100644 --- a/src/compiler/codegen/codegen.h +++ b/src/compiler/codegen/codegen.h @@ -381,6 +381,9 @@ class Codegen { virtual void OpRegCopyWide(CompilationUnit* cu, int dest_lo, int dest_hi, int src_lo, int src_hi) = 0; virtual void OpTlsCmp(CompilationUnit* cu, int offset, int val) = 0; + + // Temp workaround + void Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int value); }; // Class Codegen } // namespace art diff --git a/src/compiler/codegen/gen_loadstore.cc b/src/compiler/codegen/gen_loadstore.cc index 7d28e1be3e..11b4a62469 100644 --- a/src/compiler/codegen/gen_loadstore.cc +++ b/src/compiler/codegen/gen_loadstore.cc @@ -35,6 +35,29 @@ LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value) return LoadConstantNoClobber(cu, r_dest, value); } +/* + * Temporary workaround for Issue 7250540. If we're loading a constant zero into a + * promoted floating point register, also copy a zero into the int/ref identity of + * that sreg. + */ +void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int value) +{ + if (rl_dest.fp && (value == 0)) { + int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low); + if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) { + if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) { + // Promoted - just copy in a zero + LoadConstant(cu, cu->promotion_map[pmap_index].core_reg, 0); + } else { + // Lives in the frame, need to store. + int temp_reg = AllocTemp(cu); + LoadConstant(cu, temp_reg, 0); + StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), temp_reg, kWord); + } + } + } +} + /* Load a word at base + displacement. Displacement must be word multiple */ LIR* Codegen::LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest) { @@ -172,7 +195,10 @@ void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation r rl_dest.low_reg, kWord); MarkClean(cu, rl_dest); def_end = cu->last_lir_insn; - MarkDef(cu, rl_dest, def_start, def_end); + if (!rl_dest.ref) { + // Exclude references from store elimination + MarkDef(cu, rl_dest, def_start, def_end); + } } } diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc index b5ad0243fb..19b069c40d 100644 --- a/src/compiler/codegen/mir_to_gbc.cc +++ b/src/compiler/codegen/mir_to_gbc.cc @@ -2576,6 +2576,7 @@ static void CvtConst(CompilationUnit* cu, llvm::CallInst* call_inst) } else { cg->LoadConstantNoClobber(cu, rl_result.low_reg, immval & 0xffffffff); cg->StoreValue(cu, rl_dest, rl_result); + cg->Workaround7250540(cu, rl_dest, immval & 0xffffffff); } } diff --git a/src/compiler/codegen/mir_to_lir.cc b/src/compiler/codegen/mir_to_lir.cc index 5a6a5fc8c4..3dc6d59a9b 100644 --- a/src/compiler/codegen/mir_to_lir.cc +++ b/src/compiler/codegen/mir_to_lir.cc @@ -141,12 +141,14 @@ static bool CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB); cg->StoreValue(cu, rl_dest, rl_result); + cg->Workaround7250540(cu, rl_dest, vB); break; case Instruction::CONST_HIGH16: rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB << 16); cg->StoreValue(cu, rl_dest, rl_result); + cg->Workaround7250540(cu, rl_dest, vB); break; case Instruction::CONST_WIDE_16: diff --git a/src/compiler/codegen/ralloc_util.cc b/src/compiler/codegen/ralloc_util.cc index 7cc3fad1b8..999c6527e9 100644 --- a/src/compiler/codegen/ralloc_util.cc +++ b/src/compiler/codegen/ralloc_util.cc @@ -146,7 +146,7 @@ void ClobberSReg(CompilationUnit* cu, int s_reg) * ssa name (above the last original Dalvik register). This function * maps SSA names to positions in the promotion_map array. */ -static int SRegToPMap(CompilationUnit* cu, int s_reg) +int SRegToPMap(CompilationUnit* cu, int s_reg) { DCHECK_LT(s_reg, cu->num_ssa_regs); DCHECK_GE(s_reg, 0); diff --git a/src/compiler/codegen/ralloc_util.h b/src/compiler/codegen/ralloc_util.h index 78a623b129..3526f4cd20 100644 --- a/src/compiler/codegen/ralloc_util.h +++ b/src/compiler/codegen/ralloc_util.h @@ -156,6 +156,7 @@ int SRegOffset(CompilationUnit* cu, int reg); void RecordCorePromotion(CompilationUnit* cu, int reg, int s_reg); void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg); int ComputeFrameSize(CompilationUnit* cu); +int SRegToPMap(CompilationUnit* cu, int s_reg); } // namespace art |