summaryrefslogtreecommitdiff
path: root/compiler/optimizing/intrinsics_x86.cc
diff options
context:
space:
mode:
author Roland Levillain <rpl@google.com> 2015-07-01 15:41:14 +0100
committer Roland Levillain <rpl@google.com> 2015-07-01 16:31:41 +0100
commit4d02711ea578dbb789abb30cbaf12f9926e13d81 (patch)
tree29c802afff6e73c06021c44e6b2ec9d8340c75e9 /compiler/optimizing/intrinsics_x86.cc
parent312f1bfcfd8f655e635c941dda147377d8bff814 (diff)
Implement heap poisoning in ART's Optimizing compiler.
- Instrument ARM, ARM64, x86 and x86-64 code generators. - Note: To turn heap poisoning on in Optimizing, set the environment variable `ART_HEAP_POISONING' to "true" before compiling ART. Bug: 12687968 Change-Id: Ib3120b38cf805a8a50207a314b9ccc90c8d93740
Diffstat (limited to 'compiler/optimizing/intrinsics_x86.cc')
-rw-r--r--compiler/optimizing/intrinsics_x86.cc35
1 files changed, 31 insertions, 4 deletions
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index b04cc5cace..0d6ca09f31 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1335,9 +1335,14 @@ static void GenUnsafeGet(LocationSummary* locations, Primitive::Type type,
switch (type) {
case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- __ movl(output.AsRegister<Register>(), Address(base, offset, ScaleFactor::TIMES_1, 0));
+ case Primitive::kPrimNot: {
+ Register output_reg = output.AsRegister<Register>();
+ __ movl(output_reg, Address(base, offset, ScaleFactor::TIMES_1, 0));
+ if (type == Primitive::kPrimNot) {
+ __ MaybeUnpoisonHeapReference(output_reg);
+ }
break;
+ }
case Primitive::kPrimLong: {
Register output_lo = output.AsRegisterPairLow<Register>();
@@ -1436,7 +1441,7 @@ static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena,
locations->SetInAt(3, Location::RequiresRegister());
if (type == Primitive::kPrimNot) {
// Need temp registers for card-marking.
- locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too.
// Ensure the value is in a byte register.
locations->AddTemp(Location::RegisterLocation(ECX));
} else if (type == Primitive::kPrimLong && is_volatile) {
@@ -1498,6 +1503,11 @@ static void GenUnsafePut(LocationSummary* locations,
__ movl(Address(base, offset, ScaleFactor::TIMES_1, 0), value_lo);
__ movl(Address(base, offset, ScaleFactor::TIMES_1, 4), value_hi);
}
+ } else if (kPoisonHeapReferences && type == Primitive::kPrimNot) {
+ Register temp = locations->GetTemp(0).AsRegister<Register>();
+ __ movl(temp, value_loc.AsRegister<Register>());
+ __ PoisonHeapReference(temp);
+ __ movl(Address(base, offset, ScaleFactor::TIMES_1, 0), temp);
} else {
__ movl(Address(base, offset, ScaleFactor::TIMES_1, 0), value_loc.AsRegister<Register>());
}
@@ -1604,7 +1614,8 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code
__ LockCmpxchg8b(Address(base, offset, TIMES_1, 0));
} else {
// Integer or object.
- DCHECK_EQ(locations->InAt(3).AsRegister<Register>(), EAX);
+ Register expected = locations->InAt(3).AsRegister<Register>();
+ DCHECK_EQ(expected, EAX);
Register value = locations->InAt(4).AsRegister<Register>();
if (type == Primitive::kPrimNot) {
// Mark card for object assuming new value is stored.
@@ -1614,6 +1625,11 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code
base,
value,
value_can_be_null);
+
+ if (kPoisonHeapReferences) {
+ __ PoisonHeapReference(expected);
+ __ PoisonHeapReference(value);
+ }
}
__ LockCmpxchgl(Address(base, offset, TIMES_1, 0), value);
@@ -1625,6 +1641,13 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code
// Convert ZF into the boolean result.
__ setb(kZero, out.AsRegister<Register>());
__ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+
+ if (kPoisonHeapReferences && type == Primitive::kPrimNot) {
+ Register value = locations->InAt(4).AsRegister<Register>();
+ __ UnpoisonHeapReference(value);
+ // Do not unpoison the reference contained in register `expected`,
+ // as it is the same as register `out`.
+ }
}
void IntrinsicCodeGeneratorX86::VisitUnsafeCASInt(HInvoke* invoke) {
@@ -1734,5 +1757,9 @@ UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
+#undef UNIMPLEMENTED_INTRINSIC
+
+#undef __
+
} // namespace x86
} // namespace art