summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc8
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc8
-rw-r--r--compiler/optimizing/intrinsics_mips.cc8
-rw-r--r--compiler/optimizing/intrinsics_mips64.cc8
-rw-r--r--compiler/optimizing/intrinsics_x86.cc7
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc8
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/interpreter/interpreter_intrinsics.cc11
-rw-r--r--runtime/intrinsics_list.h1
-rw-r--r--test/036-finalizer/src/Main.java2
-rw-r--r--test/072-reachability-fence/expected.txt5
-rw-r--r--test/072-reachability-fence/info.txt4
-rw-r--r--test/072-reachability-fence/src/Main.java61
13 files changed, 132 insertions, 1 deletions
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 2f8e33f941..0e6485be9f 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -3045,6 +3045,14 @@ void IntrinsicCodeGeneratorARM64::VisitThreadInterrupted(HInvoke* invoke) {
__ Bind(&done);
}
+void IntrinsicLocationsBuilderARM64::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorARM64::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
+
UNIMPLEMENTED_INTRINSIC(ARM64, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(ARM64, StringStringIndexOf);
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 830d0403e4..97a145664c 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -3363,6 +3363,14 @@ void IntrinsicCodeGeneratorARMVIXL::VisitThreadInterrupted(HInvoke* invoke) {
}
}
+void IntrinsicLocationsBuilderARMVIXL::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
+
UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundDouble) // Could be done by changing rounding mode, maybe?
UNIMPLEMENTED_INTRINSIC(ARMVIXL, UnsafeCASLong) // High register pressure.
UNIMPLEMENTED_INTRINSIC(ARMVIXL, SystemArrayCopyChar)
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index cafa5228d9..b7936b9c8e 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -3239,6 +3239,14 @@ void IntrinsicCodeGeneratorMIPS::VisitThreadInterrupted(HInvoke* invoke) {
__ Bind(&done);
}
+void IntrinsicLocationsBuilderMIPS::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
+
// Unimplemented intrinsics.
UNIMPLEMENTED_INTRINSIC(MIPS, MathCeil)
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 89f1818be2..4668c561ed 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -2622,6 +2622,14 @@ void IntrinsicCodeGeneratorMIPS64::VisitThreadInterrupted(HInvoke* invoke) {
__ Bind(&done);
}
+void IntrinsicLocationsBuilderMIPS64::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorMIPS64::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
+
UNIMPLEMENTED_INTRINSIC(MIPS64, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(MIPS64, SystemArrayCopy)
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 46b7f3f1ce..0763ef2352 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -3359,6 +3359,13 @@ void IntrinsicCodeGeneratorX86::VisitThreadInterrupted(HInvoke* invoke) {
__ Bind(&done);
}
+void IntrinsicLocationsBuilderX86::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorX86::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
UNIMPLEMENTED_INTRINSIC(X86, MathRoundDouble)
UNIMPLEMENTED_INTRINSIC(X86, ReferenceGetReferent)
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 6483b7cb2a..91a505ede1 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -3035,6 +3035,14 @@ void IntrinsicCodeGeneratorX86_64::VisitThreadInterrupted(HInvoke* invoke) {
__ Bind(&done);
}
+void IntrinsicLocationsBuilderX86_64::VisitReachabilityFence(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::Any());
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
+
UNIMPLEMENTED_INTRINSIC(X86_64, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite)
diff --git a/runtime/image.cc b/runtime/image.cc
index 0955c3a3ca..3b13d05d80 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '5', '\0' }; // Bitstring type check off.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '6', '\0' }; // ReachabilityFence.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/interpreter/interpreter_intrinsics.cc b/runtime/interpreter/interpreter_intrinsics.cc
index 681a582b5d..f0cf2af7c7 100644
--- a/runtime/interpreter/interpreter_intrinsics.cc
+++ b/runtime/interpreter/interpreter_intrinsics.cc
@@ -399,6 +399,16 @@ VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetAcquire)
VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetPlain)
VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetRelease)
+static ALWAYS_INLINE bool MterpReachabilityFence(ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
+ const Instruction* inst ATTRIBUTE_UNUSED,
+ uint16_t inst_data ATTRIBUTE_UNUSED,
+ JValue* result_register ATTRIBUTE_UNUSED)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Do nothing; Its only purpose is to keep the argument reference live
+ // at preceding suspend points. That's automatic in the interpreter.
+ return true;
+}
+
// Macro to help keep track of what's left to implement.
#define UNIMPLEMENTED_CASE(name) \
case Intrinsics::k##name: \
@@ -499,6 +509,7 @@ bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
UNIMPLEMENTED_CASE(MemoryPokeIntNative /* (JI)V */)
UNIMPLEMENTED_CASE(MemoryPokeLongNative /* (JJ)V */)
UNIMPLEMENTED_CASE(MemoryPokeShortNative /* (JS)V */)
+ INTRINSIC_CASE(ReachabilityFence /* (Ljava/lang/Object;)V */)
INTRINSIC_CASE(StringCharAt)
INTRINSIC_CASE(StringCompareTo)
INTRINSIC_CASE(StringEquals)
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index da08793f59..2f91f5dfe0 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -218,6 +218,7 @@
V(VarHandleReleaseFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \
+ V(ReachabilityFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \
SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V)
#endif // ART_RUNTIME_INTRINSICS_LIST_H_
diff --git a/test/036-finalizer/src/Main.java b/test/036-finalizer/src/Main.java
index ff6186b240..9bfd74f91b 100644
--- a/test/036-finalizer/src/Main.java
+++ b/test/036-finalizer/src/Main.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -74,6 +75,7 @@ public class Main {
// Reference ft so we are sure the WeakReference cannot be cleared.
FinalizerTest keepLive = wimp.get();
System.out.println("wimp: " + wimpString(wimp));
+ Reference.reachabilityFence(keepLive);
}
public static void main(String[] args) {
diff --git a/test/072-reachability-fence/expected.txt b/test/072-reachability-fence/expected.txt
new file mode 100644
index 0000000000..fdd0d7bd59
--- /dev/null
+++ b/test/072-reachability-fence/expected.txt
@@ -0,0 +1,5 @@
+Starting
+Reference 0 was live.
+Reference 3 was live.
+Reference 4 was live.
+Finished
diff --git a/test/072-reachability-fence/info.txt b/test/072-reachability-fence/info.txt
new file mode 100644
index 0000000000..21b6d6a39f
--- /dev/null
+++ b/test/072-reachability-fence/info.txt
@@ -0,0 +1,4 @@
+Check that reachabilityFence() prevents garbage collection of objects only referred to by a dead
+reference.
+
+This is not very convincing, since we currently usually keep such objects around anyway.
diff --git a/test/072-reachability-fence/src/Main.java b/test/072-reachability-fence/src/Main.java
new file mode 100644
index 0000000000..ac1e131d99
--- /dev/null
+++ b/test/072-reachability-fence/src/Main.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Starting");
+ WeakReference wrefs[] = new WeakReference[5];
+ String str0 = generateString("String", 0);
+ String str1 = generateString("String", 1);
+ String str2 = generateString("String", 2);
+ String str3 = generateString("String", 3);
+ String str4 = generateString("String", 4);
+ wrefs[0] = new WeakReference(str0);
+ wrefs[1] = new WeakReference(str1);
+ wrefs[2] = new WeakReference(str2);
+ wrefs[3] = new WeakReference(str3);
+ wrefs[4] = new WeakReference(str4);
+ // Clear a couple as a sanity check.
+ str1 = null;
+ str2 = null;
+ // str<n> dead here; in the future we will possibly reuse the registers.
+ // Give the compiler something to fill the registers with.
+ String str5 = generateString("String", 5);
+ String str6 = generateString("String", 6);
+ String str7 = generateString("String", 7);
+ String str8 = generateString("String", 8);
+ String str9 = generateString("String", 9);
+ Runtime.getRuntime().gc();
+ for (int i = 0; i < 5; ++i) {
+ if (wrefs[i].get() != null) {
+ System.out.println("Reference " + i + " was live.");
+ }
+ }
+ Reference.reachabilityFence(str0);
+ Reference.reachabilityFence(str1);
+ Reference.reachabilityFence(str2);
+ Reference.reachabilityFence(str3);
+ Reference.reachabilityFence(str4);
+ System.out.println("Finished");
+ }
+
+ private static String generateString(String base, int num) {
+ return base + num;
+ }
+}