diff options
| -rw-r--r-- | compiler/intrinsics_list.h | 7 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 15 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics.cc | 2 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics.h | 43 | ||||
| -rw-r--r-- | runtime/image.cc | 2 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_intrinsics.cc | 24 | ||||
| -rwxr-xr-x | test/709-checker-varhandles/build | 20 | ||||
| -rw-r--r-- | test/709-checker-varhandles/expected.txt | 2 | ||||
| -rw-r--r-- | test/709-checker-varhandles/info.txt | 1 | ||||
| -rw-r--r-- | test/709-checker-varhandles/src-art/Main.java | 104 | ||||
| -rwxr-xr-x | test/988-method-trace/gen_srcs.py | 3 |
11 files changed, 200 insertions, 23 deletions
diff --git a/compiler/intrinsics_list.h b/compiler/intrinsics_list.h index c8a0119667..bfefead394 100644 --- a/compiler/intrinsics_list.h +++ b/compiler/intrinsics_list.h @@ -158,7 +158,12 @@ V(UnsafeFullFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \ V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \ V(IntegerValueOf, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "valueOf", "(I)Ljava/lang/Integer;") \ - V(ThreadInterrupted, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") + V(ThreadInterrupted, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") \ + V(VarHandleFullFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \ + V(VarHandleAcquireFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \ + 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") \ #endif // ART_COMPILER_INTRINSICS_LIST_H_ #undef ART_COMPILER_INTRINSICS_LIST_H_ // #define is only for lint. diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index cf1cbd578c..3164ce138f 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -2330,6 +2330,21 @@ void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { case Intrinsics::kUnsafeFullFence: SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny); break; + case Intrinsics::kVarHandleFullFence: + SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny); + break; + case Intrinsics::kVarHandleAcquireFence: + SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny); + break; + case Intrinsics::kVarHandleReleaseFence: + SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore); + break; + case Intrinsics::kVarHandleLoadLoadFence: + SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny); + break; + case Intrinsics::kVarHandleStoreStoreFence: + SimplifyMemBarrier(instruction, MemBarrierKind::kStoreStore); + break; default: break; } diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index daec634f28..0f14d2728b 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -34,7 +34,7 @@ namespace art { #define CHECK_INTRINSICS_ENUM_VALUES(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ static_assert( \ static_cast<uint32_t>(Intrinsics::k ## Name) <= (kAccIntrinsicBits >> CTZ(kAccIntrinsicBits)), \ - "Instrinsics enumeration space overflow: "); + "Instrinsics enumeration space overflow."); #include "intrinsics_list.h" INTRINSICS_LIST(CHECK_INTRINSICS_ENUM_VALUES) #undef INTRINSICS_LIST diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 6411e82f92..7abfd5b74e 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -256,25 +256,30 @@ void IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ << " should have been converted to HIR"; \ } -#define UNREACHABLE_INTRINSICS(Arch) \ -UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ -UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ -UNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ -UNREACHABLE_INTRINSIC(Arch, LongCompare) \ -UNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ -UNREACHABLE_INTRINSIC(Arch, LongSignum) \ -UNREACHABLE_INTRINSIC(Arch, StringCharAt) \ -UNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ -UNREACHABLE_INTRINSIC(Arch, StringLength) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) +#define UNREACHABLE_INTRINSICS(Arch) \ +UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ +UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ +UNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ +UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ +UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ +UNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ +UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ +UNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ +UNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ +UNREACHABLE_INTRINSIC(Arch, LongCompare) \ +UNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ +UNREACHABLE_INTRINSIC(Arch, LongSignum) \ +UNREACHABLE_INTRINSIC(Arch, StringCharAt) \ +UNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ +UNREACHABLE_INTRINSIC(Arch, StringLength) \ +UNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ +UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ +UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) \ +UNREACHABLE_INTRINSIC(Arch, VarHandleFullFence) \ +UNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence) \ +UNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence) \ +UNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence) \ +UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence) template <typename IntrinsicLocationsBuilder, typename Codegenerator> bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { diff --git a/runtime/image.cc b/runtime/image.cc index 4c6529b32c..aae572b68d 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', '4', '9', '\0' }; // 256 intrinsics +const uint8_t ImageHeader::kImageVersion[] = { '0', '4', 'A', '\0' }; // VarHandle fence intrinsics 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 74e6cd297d..26de6b4ff7 100644 --- a/runtime/interpreter/interpreter_intrinsics.cc +++ b/runtime/interpreter/interpreter_intrinsics.cc @@ -323,6 +323,25 @@ static ALWAYS_INLINE bool MterpStringEquals(ShadowFrame* shadow_frame, return true; } +#define VARHANDLE_FENCE_INTRINSIC(name, std_memory_operation) \ +static ALWAYS_INLINE bool name(ShadowFrame* /* shadow_frame */, \ + const Instruction* /* inst */, \ + uint16_t /* inst_data */, \ + JValue* /* result_register */) \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + std::atomic_thread_fence(std_memory_operation); \ + return true; \ +} + +// The VarHandle fence methods are static (unlike sun.misc.Unsafe versions). +// The fences for the LoadLoadFence and StoreStoreFence are stronger +// than strictly required, but the impact should be marginal. +VARHANDLE_FENCE_INTRINSIC(MterpVarHandleFullFence, std::memory_order_seq_cst) +VARHANDLE_FENCE_INTRINSIC(MterpVarHandleAcquireFence, std::memory_order_acquire) +VARHANDLE_FENCE_INTRINSIC(MterpVarHandleReleaseFence, std::memory_order_release) +VARHANDLE_FENCE_INTRINSIC(MterpVarHandleLoadLoadFence, std::memory_order_acquire) +VARHANDLE_FENCE_INTRINSIC(MterpVarHandleStoreStoreFence, std::memory_order_release) + // Macro to help keep track of what's left to implement. #define UNIMPLEMENTED_CASE(name) \ case Intrinsics::k##name: \ @@ -470,6 +489,11 @@ bool MterpHandleIntrinsic(ShadowFrame* shadow_frame, UNIMPLEMENTED_CASE(ReferenceGetReferent /* ()Ljava/lang/Object; */) UNIMPLEMENTED_CASE(IntegerValueOf /* (I)Ljava/lang/Integer; */) UNIMPLEMENTED_CASE(ThreadInterrupted /* ()Z */) + INTRINSIC_CASE(VarHandleFullFence) + INTRINSIC_CASE(VarHandleAcquireFence) + INTRINSIC_CASE(VarHandleReleaseFence) + INTRINSIC_CASE(VarHandleLoadLoadFence) + INTRINSIC_CASE(VarHandleStoreStoreFence) case Intrinsics::kNone: res = false; break; diff --git a/test/709-checker-varhandles/build b/test/709-checker-varhandles/build new file mode 100755 index 0000000000..2b0b2c1274 --- /dev/null +++ b/test/709-checker-varhandles/build @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright 2016 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. + +# make us exit on a failure +set -e + +./default-build "$@" --experimental method-handles diff --git a/test/709-checker-varhandles/expected.txt b/test/709-checker-varhandles/expected.txt new file mode 100644 index 0000000000..651da727af --- /dev/null +++ b/test/709-checker-varhandles/expected.txt @@ -0,0 +1,2 @@ +starting +passed diff --git a/test/709-checker-varhandles/info.txt b/test/709-checker-varhandles/info.txt new file mode 100644 index 0000000000..222124074c --- /dev/null +++ b/test/709-checker-varhandles/info.txt @@ -0,0 +1 @@ +Test support for intrinsics in Java 9 java.lang.invoke.VarHandle. diff --git a/test/709-checker-varhandles/src-art/Main.java b/test/709-checker-varhandles/src-art/Main.java new file mode 100644 index 0000000000..46aaa38f4b --- /dev/null +++ b/test/709-checker-varhandles/src-art/Main.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016 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.invoke.VarHandle; + +/** + * Checker test on the 1.8 unsafe operations. Note, this is by no means an + * exhaustive unit test for these CAS (compare-and-swap) and fence operations. + * Instead, this test ensures the methods are recognized as intrinsic and behave + * as expected. + */ +public class Main { + + // + // Fences (native). + // + + /// CHECK-START: void Main.fullFence() intrinsics_recognition (after) + /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleFullFence + // + /// CHECK-START: void Main.fullFence() instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleFullFence + // + /// CHECK-START: void Main.fullFence() instruction_simplifier (after) + /// CHECK-DAG: MemoryBarrier kind:AnyAny + private static void fullFence() { + VarHandle.fullFence(); + } + + /// CHECK-START: void Main.acquireFence() intrinsics_recognition (after) + /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleAcquireFence + // + /// CHECK-START: void Main.acquireFence() instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleAcquireFence + // + /// CHECK-START: void Main.acquireFence() instruction_simplifier (after) + /// CHECK-DAG: MemoryBarrier kind:LoadAny + private static void acquireFence() { + VarHandle.acquireFence(); + } + + /// CHECK-START: void Main.releaseFence() intrinsics_recognition (after) + /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleReleaseFence + // + /// CHECK-START: void Main.releaseFence() instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleReleaseFence + // + /// CHECK-START: void Main.releaseFence() instruction_simplifier (after) + /// CHECK-DAG: MemoryBarrier kind:AnyStore + private static void releaseFence() { + VarHandle.releaseFence(); + } + + /// CHECK-START: void Main.loadLoadFence() intrinsics_recognition (after) + /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleLoadLoadFence + // + /// CHECK-START: void Main.loadLoadFence() instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleLoadLoadFence + // + /// CHECK-START: void Main.loadLoadFence() instruction_simplifier (after) + /// CHECK-DAG: MemoryBarrier kind:LoadAny + private static void loadLoadFence() { + VarHandle.loadLoadFence(); + } + + /// CHECK-START: void Main.storeStoreFence() intrinsics_recognition (after) + /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleStoreStoreFence + // + /// CHECK-START: void Main.storeStoreFence() instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleStoreStoreFence + // + /// CHECK-START: void Main.storeStoreFence() instruction_simplifier (after) + /// CHECK-DAG: MemoryBarrier kind:StoreStore + private static void storeStoreFence() { + VarHandle.storeStoreFence(); + } + + // + // Driver. + // + + public static void main(String[] args) { + System.out.println("starting"); + acquireFence(); + releaseFence(); + loadLoadFence(); + storeStoreFence(); + fullFence(); + System.out.println("passed"); + } +} diff --git a/test/988-method-trace/gen_srcs.py b/test/988-method-trace/gen_srcs.py index c1ce35c278..8f1082ffbe 100755 --- a/test/988-method-trace/gen_srcs.py +++ b/test/988-method-trace/gen_srcs.py @@ -38,7 +38,8 @@ IDX_METHOD_NAME = -2 IDX_CLASS_NAME = -3 # Exclude all hidden API. -KLASS_BLACK_LIST = ['sun.misc.Unsafe', 'libcore.io.Memory', 'java.lang.StringFactory'] +KLASS_BLACK_LIST = ['sun.misc.Unsafe', 'libcore.io.Memory', 'java.lang.StringFactory', + 'java.lang.invoke.VarHandle' ] # TODO(b/65872996): Enable when VarHandle is visible. METHOD_BLACK_LIST = [('java.lang.ref.Reference', 'getReferent'), ('java.lang.String', 'getCharsNoCheck'), ('java.lang.System', 'arraycopy')] # arraycopy has a manual test. |