diff options
| -rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 37 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 39 | ||||
| -rw-r--r-- | oatdump/oatdump.cc | 28 | ||||
| -rw-r--r-- | test/004-UnsafeTest/src/Main.java | 48 |
4 files changed, 113 insertions, 39 deletions
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 97fe5872bf..e8912b39ab 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -807,7 +807,8 @@ void IntrinsicCodeGeneratorARM::VisitUnsafePutLongVolatile(HInvoke* invoke) { } static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, - HInvoke* invoke) { + HInvoke* invoke, + Primitive::Type type) { LocationSummary* locations = new (arena) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); @@ -817,11 +818,15 @@ static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, locations->SetInAt(3, Location::RequiresRegister()); locations->SetInAt(4, Location::RequiresRegister()); - locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + // If heap poisoning is enabled, we don't want the unpoisoning + // operations to potentially clobber the output. + Location::OutputOverlap overlaps = (kPoisonHeapReferences && type == Primitive::kPrimNot) + ? Location::kOutputOverlap + : Location::kNoOutputOverlap; + locations->SetOut(Location::RequiresRegister(), overlaps); locations->AddTemp(Location::RequiresRegister()); // Pointer. locations->AddTemp(Location::RequiresRegister()); // Temp 1. - locations->AddTemp(Location::RequiresRegister()); // Temp 2. } static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGeneratorARM* codegen) { @@ -856,7 +861,12 @@ static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGenerat if (kPoisonHeapReferences && type == Primitive::kPrimNot) { codegen->GetAssembler()->PoisonHeapReference(expected_lo); - codegen->GetAssembler()->PoisonHeapReference(value_lo); + if (value_lo == expected_lo) { + // Do not poison `value_lo`, as it is the same register as + // `expected_lo`, which has just been poisoned. + } else { + codegen->GetAssembler()->PoisonHeapReference(value_lo); + } } // do { @@ -892,13 +902,18 @@ static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGenerat __ mov(out, ShifterOperand(0), CC); if (kPoisonHeapReferences && type == Primitive::kPrimNot) { - codegen->GetAssembler()->UnpoisonHeapReference(value_lo); codegen->GetAssembler()->UnpoisonHeapReference(expected_lo); + if (value_lo == expected_lo) { + // Do not unpoison `value_lo`, as it is the same register as + // `expected_lo`, which has just been unpoisoned. + } else { + codegen->GetAssembler()->UnpoisonHeapReference(value_lo); + } } } void IntrinsicLocationsBuilderARM::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke); + CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, Primitive::kPrimInt); } void IntrinsicLocationsBuilderARM::VisitUnsafeCASObject(HInvoke* invoke) { // The UnsafeCASObject intrinsic is missing a read barrier, and @@ -906,16 +921,12 @@ void IntrinsicLocationsBuilderARM::VisitUnsafeCASObject(HInvoke* invoke) { // Turn it off temporarily as a quick fix, until the read barrier is // implemented (see TODO in GenCAS below). // - // Also, the UnsafeCASObject intrinsic does not always work when heap - // poisoning is enabled (it breaks run-test 004-UnsafeTest); turn it - // off temporarily as a quick fix (b/26204023). - // - // TODO(rpl): Fix these two issues and re-enable this intrinsic. - if (kEmitCompilerReadBarrier || kPoisonHeapReferences) { + // TODO(rpl): Fix this issue and re-enable this intrinsic with read barriers. + if (kEmitCompilerReadBarrier) { return; } - CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke); + CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, Primitive::kPrimNot); } void IntrinsicCodeGeneratorARM::VisitUnsafeCASInt(HInvoke* invoke) { GenCas(invoke->GetLocations(), Primitive::kPrimInt, codegen_); diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index c888f01841..d5ed58530d 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -986,7 +986,9 @@ void IntrinsicCodeGeneratorARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) { codegen_); } -static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, HInvoke* invoke) { +static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, + HInvoke* invoke, + Primitive::Type type) { LocationSummary* locations = new (arena) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); @@ -996,7 +998,12 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, HInvoke* invoke) { locations->SetInAt(3, Location::RequiresRegister()); locations->SetInAt(4, Location::RequiresRegister()); - locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + // If heap poisoning is enabled, we don't want the unpoisoning + // operations to potentially clobber the output. + Location::OutputOverlap overlaps = (kPoisonHeapReferences && type == Primitive::kPrimNot) + ? Location::kOutputOverlap + : Location::kNoOutputOverlap; + locations->SetOut(Location::RequiresRegister(), overlaps); } static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGeneratorARM64* codegen) { @@ -1027,7 +1034,12 @@ static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGenerat if (kPoisonHeapReferences && type == Primitive::kPrimNot) { codegen->GetAssembler()->PoisonHeapReference(expected); - codegen->GetAssembler()->PoisonHeapReference(value); + if (value.Is(expected)) { + // Do not poison `value`, as it is the same register as + // `expected`, which has just been poisoned. + } else { + codegen->GetAssembler()->PoisonHeapReference(value); + } } // do { @@ -1077,16 +1089,21 @@ static void GenCas(LocationSummary* locations, Primitive::Type type, CodeGenerat __ Cset(out, eq); if (kPoisonHeapReferences && type == Primitive::kPrimNot) { - codegen->GetAssembler()->UnpoisonHeapReference(value); codegen->GetAssembler()->UnpoisonHeapReference(expected); + if (value.Is(expected)) { + // Do not unpoison `value`, as it is the same register as + // `expected`, which has just been unpoisoned. + } else { + codegen->GetAssembler()->UnpoisonHeapReference(value); + } } } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, invoke); + CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimInt); } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASLong(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, invoke); + CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimLong); } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASObject(HInvoke* invoke) { // The UnsafeCASObject intrinsic is missing a read barrier, and @@ -1094,16 +1111,12 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafeCASObject(HInvoke* invoke) { // Turn it off temporarily as a quick fix, until the read barrier is // implemented (see TODO in GenCAS below). // - // Also, the UnsafeCASObject intrinsic does not always work when heap - // poisoning is enabled (it breaks run-test 004-UnsafeTest); turn it - // off temporarily as a quick fix (b/26204023). - // - // TODO(rpl): Fix these two issues and re-enable this intrinsic. - if (kEmitCompilerReadBarrier || kPoisonHeapReferences) { + // TODO(rpl): Fix this issue and re-enable this intrinsic with read barriers. + if (kEmitCompilerReadBarrier) { return; } - CreateIntIntIntIntIntToInt(arena_, invoke); + CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimNot); } void IntrinsicCodeGeneratorARM64::VisitUnsafeCASInt(HInvoke* invoke) { diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index a1f6eee42c..5d06919463 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -153,6 +153,7 @@ class OatSymbolizer FINAL { strtab->Start(); strtab->Write(""); // strtab should start with empty string. + AddTrampolineSymbols(); Walk(&art::OatSymbolizer::AddSymbol); strtab->End(); @@ -165,6 +166,33 @@ class OatSymbolizer FINAL { return builder_->Good(); } + void AddTrampolineSymbol(const char* name, uint32_t code_offset) { + if (code_offset != 0) { + uint32_t name_offset = builder_->GetStrTab()->Write(name); + uint64_t symbol_value = code_offset - oat_file_->GetOatHeader().GetExecutableOffset(); + builder_->GetSymTab()->Add(name_offset, builder_->GetText(), symbol_value, + /* is_relative */ true, /* size */ 0, STB_GLOBAL, STT_FUNC); + } + } + + void AddTrampolineSymbols() { + const OatHeader& oat_header = oat_file_->GetOatHeader(); + AddTrampolineSymbol("interpreterToInterpreterBridge", + oat_header.GetInterpreterToInterpreterBridgeOffset()); + AddTrampolineSymbol("interpreterToCompiledCodeBridge", + oat_header.GetInterpreterToCompiledCodeBridgeOffset()); + AddTrampolineSymbol("jniDlsymLookup", + oat_header.GetJniDlsymLookupOffset()); + AddTrampolineSymbol("quickGenericJniTrampoline", + oat_header.GetQuickGenericJniTrampolineOffset()); + AddTrampolineSymbol("quickImtConflictTrampoline", + oat_header.GetQuickImtConflictTrampolineOffset()); + AddTrampolineSymbol("quickResolutionTrampoline", + oat_header.GetQuickResolutionTrampolineOffset()); + AddTrampolineSymbol("quickToInterpreterBridge", + oat_header.GetQuickToInterpreterBridgeOffset()); + } + void Walk(Callback callback) { std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles(); for (size_t i = 0; i < oat_dex_files.size(); i++) { diff --git a/test/004-UnsafeTest/src/Main.java b/test/004-UnsafeTest/src/Main.java index 5b22e88014..a9a7a058e0 100644 --- a/test/004-UnsafeTest/src/Main.java +++ b/test/004-UnsafeTest/src/Main.java @@ -110,23 +110,35 @@ public class Main { check(unsafe.getObject(t, objectOffset), objectValue, "Unsafe.getObject(Object, long)"); if (unsafe.compareAndSwapInt(t, intOffset, 0, 1)) { - System.out.println("Unexpectedly succeeding compareAndSwap..."); + System.out.println("Unexpectedly succeeding compareAndSwapInt(t, intOffset, 0, 1)"); } if (!unsafe.compareAndSwapInt(t, intOffset, intValue, 0)) { - System.out.println("Unexpectedly not succeeding compareAndSwap..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapInt(t, intOffset, intValue, 0)"); } if (!unsafe.compareAndSwapInt(t, intOffset, 0, 1)) { - System.out.println("Unexpectedly not succeeding compareAndSwap..."); + System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 0, 1)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapInt using the same + // integer (1) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapInt(t, intOffset, 1, 1)) { + System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 1, 1)"); } if (unsafe.compareAndSwapLong(t, longOffset, 0, 1)) { - System.out.println("Unexpectedly succeeding compareAndSwapLong..."); + System.out.println("Unexpectedly succeeding compareAndSwapLong(t, longOffset, 0, 1)"); } if (!unsafe.compareAndSwapLong(t, longOffset, longValue, 0)) { - System.out.println("Unexpectedly not succeeding compareAndSwapLong..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapLong(t, longOffset, longValue, 0)"); } if (!unsafe.compareAndSwapLong(t, longOffset, 0, 1)) { - System.out.println("Unexpectedly not succeeding compareAndSwapLong..."); + System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 0, 1)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapLong using the same + // integer (1) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapLong(t, longOffset, 1, 1)) { + System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 1, 1)"); } // We do not use `null` as argument to sun.misc.Unsafe.compareAndSwapObject @@ -135,31 +147,41 @@ public class Main { // references). This way, when heap poisoning is enabled, we can // better exercise its implementation within that method. if (unsafe.compareAndSwapObject(t, objectOffset, new Object(), new Object())) { - System.out.println("Unexpectedly succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly succeeding " + + "compareAndSwapObject(t, objectOffset, new Object(), new Object())"); } Object objectValue2 = new Object(); if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue, objectValue2)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue, objectValue2)"); } Object objectValue3 = new Object(); if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapObject using the same + // object (`objectValue3`) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)) { + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)"); } - // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj` and `newValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, t)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, objectValue3, t)"); } // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj`, `expectedValue` and `newValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, t, t)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, t)"); } // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj` and `expectedValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, t, new Object())) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, new Object())"); } } |