diff options
| -rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 7 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 8 | ||||
| -rw-r--r-- | runtime/image.cc | 2 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_intrinsics.cc | 11 | ||||
| -rw-r--r-- | runtime/intrinsics_list.h | 1 | ||||
| -rw-r--r-- | test/036-finalizer/src/Main.java | 2 | ||||
| -rw-r--r-- | test/072-reachability-fence/expected.txt | 5 | ||||
| -rw-r--r-- | test/072-reachability-fence/info.txt | 4 | ||||
| -rw-r--r-- | test/072-reachability-fence/src/Main.java | 61 |
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; + } +} |