diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-04-02 17:09:17 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-04-02 17:48:05 -0700 |
commit | 7c95cefc168ba81b17a9ed2d987ac5bcf0b05781 (patch) | |
tree | f358d12353183bb5800e91f459a158a514039a09 /compiler/dex | |
parent | 0807e7bbbafc4b4e8e7fb1d2d54fbcb011c05c82 (diff) | |
download | art-7c95cefc168ba81b17a9ed2d987ac5bcf0b05781.zip art-7c95cefc168ba81b17a9ed2d987ac5bcf0b05781.tar.gz art-7c95cefc168ba81b17a9ed2d987ac5bcf0b05781.tar.bz2 |
Use temp register in Unsafe Get/Put intrisics for displaced offset.
Previously, the object register would get clobberd by the adding the
offset for wide UnsafeGets and wide UnsafePuts. This resulted in heap
corruption in AtomicLongFieldUpdater.compareAndSet and possibly other
places.
Bug: 13744490
Change-Id: Ic368d930b855c5c57e22060b32b73d0745328ef2
Diffstat (limited to 'compiler/dex')
-rw-r--r-- | compiler/dex/quick/gen_invoke.cc | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 0746913..352130d 100644 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -1408,8 +1408,15 @@ bool Mir2Lir::GenInlinedUnsafeGet(CallInfo* info, RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); if (is_long) { - OpRegReg(kOpAdd, rl_object.reg, rl_offset.reg); - LoadBaseDispWide(rl_object.reg, 0, rl_result.reg, INVALID_SREG); + if (cu_->instruction_set == kX86) { + LoadBaseIndexedDisp(rl_object.reg, rl_offset.reg, 1, 0, rl_result.reg.GetLow(), + rl_result.reg.GetHigh(), kLong, INVALID_SREG); + } else { + RegStorage rl_temp_offset = AllocTemp(); + OpRegRegReg(kOpAdd, rl_temp_offset, rl_object.reg, rl_offset.reg); + LoadBaseDispWide(rl_temp_offset, 0, rl_result.reg, INVALID_SREG); + FreeTemp(rl_temp_offset.GetReg()); + } } else { LoadBaseIndexed(rl_object.reg, rl_offset.reg, rl_result.reg, 0, kWord); } @@ -1449,8 +1456,15 @@ bool Mir2Lir::GenInlinedUnsafePut(CallInfo* info, bool is_long, RegLocation rl_value; if (is_long) { rl_value = LoadValueWide(rl_src_value, kCoreReg); - OpRegReg(kOpAdd, rl_object.reg, rl_offset.reg); - StoreBaseDispWide(rl_object.reg, 0, rl_value.reg); + if (cu_->instruction_set == kX86) { + StoreBaseIndexedDisp(rl_object.reg, rl_offset.reg, 1, 0, rl_value.reg.GetLow(), + rl_value.reg.GetHigh(), kLong, INVALID_SREG); + } else { + RegStorage rl_temp_offset = AllocTemp(); + OpRegRegReg(kOpAdd, rl_temp_offset, rl_object.reg, rl_offset.reg); + StoreBaseDispWide(rl_temp_offset, 0, rl_value.reg); + FreeTemp(rl_temp_offset.GetReg()); + } } else { rl_value = LoadValue(rl_src_value, kCoreReg); StoreBaseIndexed(rl_object.reg, rl_offset.reg, rl_value.reg, 0, kWord); |