summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--Android.mk4
-rw-r--r--adbconnection/adbconnection.cc14
-rw-r--r--benchmark/type-check/info.txt1
-rw-r--r--benchmark/type-check/src/TypeCheckBenchmark.java147
-rw-r--r--build/Android.gtest.mk40
-rw-r--r--compiler/Android.bp3
-rw-r--r--compiler/jni/jni_compiler_test.cc5
-rw-r--r--compiler/optimizing/code_generator_mips.cc355
-rw-r--r--compiler/optimizing/instruction_builder.cc8
-rw-r--r--compiler/optimizing/nodes.h2
-rw-r--r--compiler/optimizing/reference_type_propagation.cc7
-rw-r--r--compiler/utils/x86/assembler_x86.cc2
-rw-r--r--compiler/utils/x86/assembler_x86_test.cc4
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc2
-rw-r--r--compiler/utils/x86_64/assembler_x86_64_test.cc5
-rw-r--r--dex2oat/Android.bp4
-rw-r--r--dex2oat/dex2oat.cc14
-rw-r--r--dex2oat/dex2oat_options.cc5
-rw-r--r--dex2oat/dex2oat_options.def1
-rw-r--r--dex2oat/dex2oat_test.cc116
-rw-r--r--dex2oat/linker/image_writer.cc2
-rw-r--r--dex2oat/linker/oat_writer.cc88
-rw-r--r--dexdump/Android.bp1
-rw-r--r--dexlayout/Android.bp11
-rw-r--r--libdexfile/Android.bp125
-rw-r--r--libdexfile/dex/base64_test_util.h (renamed from runtime/dex/base64_test_util.h)6
-rw-r--r--libdexfile/dex/code_item_accessors-inl.h (renamed from runtime/dex/code_item_accessors-inl.h)6
-rw-r--r--libdexfile/dex/code_item_accessors.h (renamed from runtime/dex/code_item_accessors.h)7
-rw-r--r--libdexfile/dex/code_item_accessors_test.cc (renamed from runtime/dex/code_item_accessors_test.cc)0
-rw-r--r--libdexfile/dex/compact_dex_debug_info.cc (renamed from runtime/dex/compact_dex_debug_info.cc)0
-rw-r--r--libdexfile/dex/compact_dex_debug_info.h (renamed from runtime/dex/compact_dex_debug_info.h)6
-rw-r--r--libdexfile/dex/compact_dex_debug_info_test.cc (renamed from runtime/dex/compact_dex_debug_info_test.cc)0
-rw-r--r--libdexfile/dex/compact_dex_file.cc (renamed from runtime/dex/compact_dex_file.cc)0
-rw-r--r--libdexfile/dex/compact_dex_file.h (renamed from runtime/dex/compact_dex_file.h)6
-rw-r--r--libdexfile/dex/compact_dex_file_test.cc (renamed from runtime/dex/compact_dex_file_test.cc)0
-rw-r--r--libdexfile/dex/compact_dex_level.h (renamed from runtime/dex/compact_dex_level.h)6
-rw-r--r--libdexfile/dex/compact_dex_utils.h (renamed from runtime/dex/compact_dex_utils.h)6
-rw-r--r--libdexfile/dex/descriptors_names.cc (renamed from runtime/dex/descriptors_names.cc)0
-rw-r--r--libdexfile/dex/descriptors_names.h (renamed from runtime/dex/descriptors_names.h)6
-rw-r--r--libdexfile/dex/dex_file-inl.h (renamed from runtime/dex/dex_file-inl.h)6
-rw-r--r--libdexfile/dex/dex_file.cc (renamed from runtime/dex/dex_file.cc)0
-rw-r--r--libdexfile/dex/dex_file.h (renamed from runtime/dex/dex_file.h)6
-rw-r--r--libdexfile/dex/dex_file_exception_helpers.cc (renamed from runtime/dex/dex_file_exception_helpers.cc)0
-rw-r--r--libdexfile/dex/dex_file_exception_helpers.h (renamed from runtime/dex/dex_file_exception_helpers.h)6
-rw-r--r--libdexfile/dex/dex_file_loader.cc (renamed from runtime/dex/dex_file_loader.cc)0
-rw-r--r--libdexfile/dex/dex_file_loader.h (renamed from runtime/dex/dex_file_loader.h)6
-rw-r--r--libdexfile/dex/dex_file_loader_test.cc (renamed from runtime/dex/dex_file_test.cc)482
-rw-r--r--libdexfile/dex/dex_file_reference.h (renamed from runtime/dex/dex_file_reference.h)6
-rw-r--r--libdexfile/dex/dex_file_tracking_registrar.cc (renamed from runtime/dex/dex_file_tracking_registrar.cc)0
-rw-r--r--libdexfile/dex/dex_file_tracking_registrar.h (renamed from runtime/dex/dex_file_tracking_registrar.h)6
-rw-r--r--libdexfile/dex/dex_file_types.h (renamed from runtime/dex/dex_file_types.h)6
-rw-r--r--libdexfile/dex/dex_file_verifier.cc (renamed from runtime/dex/dex_file_verifier.cc)0
-rw-r--r--libdexfile/dex/dex_file_verifier.h (renamed from runtime/dex/dex_file_verifier.h)7
-rw-r--r--libdexfile/dex/dex_file_verifier_test.cc (renamed from runtime/dex/dex_file_verifier_test.cc)0
-rw-r--r--libdexfile/dex/dex_instruction-inl.h (renamed from runtime/dex/dex_instruction-inl.h)6
-rw-r--r--libdexfile/dex/dex_instruction.cc (renamed from runtime/dex/dex_instruction.cc)7
-rw-r--r--libdexfile/dex/dex_instruction.h (renamed from runtime/dex/dex_instruction.h)23
-rw-r--r--libdexfile/dex/dex_instruction_iterator.h (renamed from runtime/dex/dex_instruction_iterator.h)6
-rw-r--r--libdexfile/dex/dex_instruction_list.h (renamed from runtime/dex/dex_instruction_list.h)8
-rw-r--r--libdexfile/dex/dex_instruction_test.cc (renamed from runtime/dex/dex_instruction_test.cc)0
-rw-r--r--libdexfile/dex/dex_instruction_utils.h (renamed from runtime/dex/dex_instruction_utils.h)6
-rw-r--r--libdexfile/dex/invoke_type.h (renamed from runtime/dex/invoke_type.h)6
-rw-r--r--libdexfile/dex/modifiers.cc (renamed from runtime/dex/modifiers.cc)0
-rw-r--r--libdexfile/dex/modifiers.h (renamed from runtime/dex/modifiers.h)6
-rw-r--r--libdexfile/dex/standard_dex_file.cc (renamed from runtime/dex/standard_dex_file.cc)0
-rw-r--r--libdexfile/dex/standard_dex_file.h (renamed from runtime/dex/standard_dex_file.h)6
-rw-r--r--libdexfile/dex/utf-inl.h (renamed from runtime/dex/utf-inl.h)6
-rw-r--r--libdexfile/dex/utf.cc (renamed from runtime/dex/utf.cc)0
-rw-r--r--libdexfile/dex/utf.h (renamed from runtime/dex/utf.h)6
-rw-r--r--libdexfile/dex/utf_test.cc (renamed from runtime/dex/utf_test.cc)0
l---------libdexfile/generate-operator-out.py1
-rw-r--r--oatdump/Android.bp4
-rw-r--r--oatdump/oatdump.cc8
-rw-r--r--openjdkjvmti/Android.bp3
-rw-r--r--openjdkjvmti/OpenjdkJvmTi.cc61
-rw-r--r--openjdkjvmti/deopt_manager.cc6
-rw-r--r--openjdkjvmti/events.cc5
-rw-r--r--openjdkjvmti/transform.cc2
-rw-r--r--profman/Android.bp3
-rw-r--r--profman/profile_assistant_test.cc22
-rw-r--r--profman/profman.cc27
-rw-r--r--runtime/Android.bp95
-rw-r--r--runtime/arch/memcmp16_test.cc2
-rw-r--r--runtime/art_method-inl.h1
-rw-r--r--runtime/art_method.h2
-rw-r--r--runtime/base/bit_vector.cc2
-rw-r--r--runtime/base/stringpiece.cc7
-rw-r--r--runtime/base/stringpiece.h7
-rw-r--r--runtime/check_jni.cc31
-rw-r--r--runtime/class_linker-inl.h9
-rw-r--r--runtime/class_linker.cc61
-rw-r--r--runtime/class_linker.h7
-rw-r--r--runtime/common_throws.cc37
-rw-r--r--runtime/common_throws.h19
-rw-r--r--runtime/dex/art_dex_file_loader.cc8
-rw-r--r--runtime/dex/art_dex_file_loader.h2
-rw-r--r--runtime/dex/art_dex_file_loader_test.cc307
-rw-r--r--runtime/dex/code_item_accessors-no_art-inl.h23
-rw-r--r--runtime/dex/dex_file_annotations.cc2
-rw-r--r--runtime/dex/dex_file_annotations.h2
-rw-r--r--runtime/dex/dex_file_layout.cc3
-rw-r--r--runtime/dexopt_test.cc13
-rw-r--r--runtime/dexopt_test.h6
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h3
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc10
-rw-r--r--runtime/gc/accounting/atomic_stack.h2
-rw-r--r--runtime/gc/accounting/space_bitmap-inl.h11
-rw-r--r--runtime/gc/accounting/space_bitmap.cc11
-rw-r--r--runtime/gc/accounting/space_bitmap.h21
-rw-r--r--runtime/gc/accounting/space_bitmap_test.cc2
-rw-r--r--runtime/gc/collector/concurrent_copying-inl.h9
-rw-r--r--runtime/gc/collector/concurrent_copying.cc219
-rw-r--r--runtime/gc/collector/concurrent_copying.h27
-rw-r--r--runtime/gc/collector/mark_sweep.cc30
-rw-r--r--runtime/gc/collector/sticky_mark_sweep.cc2
-rw-r--r--runtime/gc/heap.cc19
-rw-r--r--runtime/gc/heap.h8
-rw-r--r--runtime/gc/heap_test.cc1
-rw-r--r--runtime/gc/space/region_space-inl.h60
-rw-r--r--runtime/gc/space/region_space.cc83
-rw-r--r--runtime/gc/space/region_space.h120
-rw-r--r--runtime/gc/space/space.cc3
-rw-r--r--runtime/gc/space/space.h9
-rw-r--r--runtime/gc/space/zygote_space.h2
-rw-r--r--runtime/gc/verification.cc2
-rw-r--r--runtime/hidden_api.h74
-rw-r--r--runtime/hidden_api_access_flags.h18
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/instrumentation.cc15
-rw-r--r--runtime/interpreter/interpreter_common.cc380
-rw-r--r--runtime/interpreter/interpreter_common.h5
-rw-r--r--runtime/interpreter/mterp/arm/entry.S2
-rw-r--r--runtime/interpreter/mterp/arm/header.S2
-rw-r--r--runtime/interpreter/mterp/arm64/entry.S2
-rw-r--r--runtime/interpreter/mterp/arm64/header.S2
-rw-r--r--runtime/interpreter/mterp/cfi_asm_support.h30
-rwxr-xr-xruntime/interpreter/mterp/gen_mterp.py2
-rw-r--r--runtime/interpreter/mterp/mips/entry.S2
-rw-r--r--runtime/interpreter/mterp/mips/header.S2
-rw-r--r--runtime/interpreter/mterp/mips64/entry.S2
-rw-r--r--runtime/interpreter/mterp/mips64/header.S2
-rw-r--r--runtime/interpreter/mterp/out/mterp_arm.S4
-rw-r--r--runtime/interpreter/mterp/out/mterp_arm64.S4
-rw-r--r--runtime/interpreter/mterp/out/mterp_mips.S4
-rw-r--r--runtime/interpreter/mterp/out/mterp_mips64.S4
-rw-r--r--runtime/interpreter/mterp/out/mterp_x86.S4
-rw-r--r--runtime/interpreter/mterp/out/mterp_x86_64.S4
-rw-r--r--runtime/interpreter/mterp/x86/entry.S2
-rw-r--r--runtime/interpreter/mterp/x86/header.S2
-rw-r--r--runtime/interpreter/mterp/x86_64/entry.S2
-rw-r--r--runtime/interpreter/mterp/x86_64/header.S2
-rw-r--r--runtime/interpreter/unstarted_runtime.cc20
-rw-r--r--runtime/interpreter/unstarted_runtime_list.h2
-rw-r--r--runtime/java_vm_ext.h2
-rw-r--r--runtime/jdwp/jdwp_adb.cc13
-rw-r--r--runtime/jit/profile_compilation_info.cc55
-rw-r--r--runtime/jit/profile_compilation_info.h8
-rw-r--r--runtime/jit/profile_compilation_info_test.cc40
-rw-r--r--runtime/jit/profile_saver.cc2
-rw-r--r--runtime/jni_env_ext.h11
-rw-r--r--runtime/jni_internal.cc3
-rw-r--r--runtime/lock_word.h6
-rw-r--r--runtime/method_handles.cc2
-rw-r--r--runtime/method_handles.h18
-rw-r--r--runtime/mirror/class-inl.h2
-rw-r--r--runtime/mirror/class.cc48
-rw-r--r--runtime/mirror/class.h6
-rw-r--r--runtime/mirror/emulated_stack_frame.cc2
-rw-r--r--runtime/mirror/object-inl.h192
-rw-r--r--runtime/mirror/object-readbarrier-inl.h2
-rw-r--r--runtime/mirror/object.h61
-rw-r--r--runtime/mirror/var_handle.cc1592
-rw-r--r--runtime/mirror/var_handle.h68
-rw-r--r--runtime/mirror/var_handle_test.cc8
-rw-r--r--runtime/native/dalvik_system_DexFile.cc53
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc13
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc10
-rw-r--r--runtime/native/java_lang_Class.cc10
-rw-r--r--runtime/native/java_lang_Void.cc43
-rw-r--r--runtime/native_stack_dump.cc3
-rw-r--r--runtime/oat.h1
-rw-r--r--runtime/oat_file.cc35
-rw-r--r--runtime/oat_file.h2
-rw-r--r--runtime/oat_file_assistant.cc23
-rw-r--r--runtime/oat_file_assistant.h14
-rw-r--r--runtime/oat_file_assistant_test.cc32
-rw-r--r--runtime/oat_file_test.cc42
-rw-r--r--runtime/parsed_options.cc6
-rw-r--r--runtime/runtime.cc28
-rw-r--r--runtime/runtime.h2
-rw-r--r--runtime/runtime_options.def3
-rw-r--r--runtime/subtype_check.h3
-rw-r--r--runtime/thread.cc31
-rw-r--r--runtime/verifier/method_verifier.cc18
-rw-r--r--runtime/verifier/reg_type_cache.cc2
-rw-r--r--runtime/well_known_classes.cc38
-rw-r--r--runtime/well_known_classes.h7
-rw-r--r--test/030-bad-finalizer/expected.txt1
-rwxr-xr-x[-rw-r--r--]test/030-bad-finalizer/run (renamed from test/911-get-stack-trace/build)7
-rw-r--r--test/034-call-null/expected.txt1
-rwxr-xr-xtest/034-call-null/run (renamed from test/1937-transform-soft-fail/check)10
-rw-r--r--test/038-inner-null/expected.txt1
-rwxr-xr-xtest/038-inner-null/run19
-rw-r--r--test/046-reflect/src/Main.java4
-rw-r--r--test/054-uncaught/expected.txt1
-rwxr-xr-xtest/054-uncaught/run19
-rw-r--r--test/075-verification-error/src/Main.java2
-rwxr-xr-xtest/134-nodex2oat-nofallback/run2
-rw-r--r--test/1917-get-stack-frame/expected.txt4
-rw-r--r--test/1917-get-stack-frame/src/art/StackTrace.java3
-rw-r--r--test/1927-exception-event/expected.txt48
-rw-r--r--test/1927-exception-event/src/art/StackTrace.java3
-rw-r--r--test/1928-exception-event-exception/expected.txt132
-rw-r--r--test/1928-exception-event-exception/src/art/StackTrace.java3
-rw-r--r--test/1928-exception-event-exception/src/art/Test1928.java2
-rw-r--r--test/1929-exception-catch-exception/expected.txt48
-rw-r--r--test/1929-exception-catch-exception/src/art/StackTrace.java3
-rw-r--r--test/1937-transform-soft-fail/src/art/Test1937.java7
-rw-r--r--test/1939-proxy-frames/expected.txt2
-rw-r--r--test/1939-proxy-frames/src/art/Test1939.java12
-rwxr-xr-xtest/1944-sudden-exit/check25
-rw-r--r--test/1944-sudden-exit/expected.txt3
-rw-r--r--test/1944-sudden-exit/info.txt5
-rwxr-xr-xtest/1944-sudden-exit/run19
-rw-r--r--test/1944-sudden-exit/src/Main.java (renamed from runtime/native/java_lang_Void.h)17
-rw-r--r--test/1944-sudden-exit/src/art/Test1944.java69
-rw-r--r--test/1944-sudden-exit/src/art/Trace.java68
-rw-r--r--test/1944-sudden-exit/sudden_exit.cc (renamed from test/983-source-transform-verify/source_transform.h)20
-rw-r--r--test/670-bitstring-type-check/build216
-rw-r--r--test/670-bitstring-type-check/expected.txt0
-rw-r--r--test/670-bitstring-type-check/info.txt1
-rwxr-xr-xtest/712-varhandle-invocations/build39
-rw-r--r--test/712-varhandle-invocations/expected.txt3183
-rw-r--r--test/712-varhandle-invocations/info.txt1
-rw-r--r--test/712-varhandle-invocations/src/SimpleTests.java61
-rw-r--r--test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java232
-rw-r--r--test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java948
-rw-r--r--test/712-varhandle-invocations/src/VarHandleReflectiveTest.java58
-rw-r--r--test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java1343
-rw-r--r--test/712-varhandle-invocations/src/VarHandleUnitTest.java190
-rw-r--r--test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java61
-rw-r--r--test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java281
-rw-r--r--test/712-varhandle-invocations/src/Widget.java39
-rw-r--r--test/712-varhandle-invocations/util-src/generate_java.py876
-rw-r--r--test/714-invoke-custom-lambda-metafactory/expected.txt1
-rwxr-xr-xtest/714-invoke-custom-lambda-metafactory/run19
-rw-r--r--test/800-smali/smali/b_22045582.smali2
-rw-r--r--test/805-TooDeepClassInstanceOf/expected.txt (renamed from test/988-TooDeepClassInstanceOf/expected.txt)0
-rw-r--r--test/805-TooDeepClassInstanceOf/info.txt (renamed from test/988-TooDeepClassInstanceOf/info.txt)0
-rw-r--r--test/805-TooDeepClassInstanceOf/src/Main.java (renamed from test/988-TooDeepClassInstanceOf/src/Main.java)0
-rw-r--r--test/806-TooWideClassInstanceOf/expected.txt (renamed from test/988-TooWideClassInstanceOf/expected.txt)0
-rw-r--r--test/806-TooWideClassInstanceOf/info.txt (renamed from test/988-TooWideClassInstanceOf/info.txt)0
-rw-r--r--test/806-TooWideClassInstanceOf/src/Main.java (renamed from test/988-TooWideClassInstanceOf/src/Main.java)0
-rw-r--r--test/911-get-stack-trace/expected_d8.diff8
-rw-r--r--test/952-invoke-custom-lookup/build27
-rw-r--r--test/952-invoke-custom-lookup/classes.dexbin0 -> 2700 bytes
-rw-r--r--test/952-invoke-custom-lookup/classes.jarbin0 -> 3005 bytes
-rw-r--r--test/952-invoke-custom-lookup/expected.txt10
-rw-r--r--test/952-invoke-custom-lookup/info.txt1
-rw-r--r--test/965-default-verify/src/Iface.java2
-rw-r--r--test/965-default-verify/src/Statics.java3
-rw-r--r--test/965-default-verify/src2/Statics.java2
-rw-r--r--test/983-source-transform-verify/source_transform.cc56
-rw-r--r--test/983-source-transform-verify/src/art/Test983.java8
-rw-r--r--test/993-breakpoints/src/art/Breakpoint.java2
-rw-r--r--test/Android.bp71
-rw-r--r--test/Android.run-test.mk12
-rwxr-xr-xtest/etc/default-build6
-rwxr-xr-xtest/etc/run-test-jar15
-rw-r--r--test/knownfailures.json24
-rw-r--r--test/ti-agent/common_load.cc2
-rw-r--r--tools/cpp-define-generator/Android.bp5
-rw-r--r--tools/external_oj_libjdwp_art_failures.txt19
-rw-r--r--tools/hiddenapi/Android.bp3
-rw-r--r--tools/prebuilt_libjdwp_art_failures.txt19
-rw-r--r--tools/public.libraries.buildbot.txt1
-rw-r--r--tools/titrace/Android.bp3
278 files changed, 12788 insertions, 1854 deletions
diff --git a/Android.bp b/Android.bp
index 4bcceffcd1..bb92e5f2f8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,6 @@
// TODO: These should be handled with transitive static library dependencies
art_static_dependencies = [
// Note: the order is important because of static linking resolution.
- "libdexfile",
"libziparchive",
"libnativehelper",
"libnativebridge",
@@ -36,6 +35,7 @@ subdirs = [
"dt_fd_forward",
"dt_fd_forward/export",
"imgdiag",
+ "libdexfile",
"oatdump",
"openjdkjvm",
"openjdkjvmti",
diff --git a/Android.mk b/Android.mk
index 3267483f2d..2489308c02 100644
--- a/Android.mk
+++ b/Android.mk
@@ -487,8 +487,10 @@ build-art-target-golem: dex2oat dalvikvm patchoat linker libstdc++ \
$(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
$(TARGET_CORE_IMG_OUT_BASE).art \
$(TARGET_CORE_IMG_OUT_BASE)-interpreter.art
+ # remove libartd.so and libdexfiled.so from public.libraries.txt because golem builds
+ # won't have it.
sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
- # remove libartd.so from public.libraries.txt because golem builds won't have it.
+ sed -i '/libdexfiled.so/d' $(TARGET_OUT)/etc/public.libraries.txt
########################################################################
# Phony target for building what go/lem requires on host.
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index a0c99663b4..06ded26a2d 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -488,7 +488,6 @@ android::base::unique_fd AdbConnectionState::ReadFdFromAdb() {
bool AdbConnectionState::SetupAdbConnection() {
int sleep_ms = 500;
const int sleep_max_ms = 2*1000;
- char buff[sizeof(pid_t) + 1];
android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET, 0));
if (sock < 0) {
@@ -499,8 +498,7 @@ bool AdbConnectionState::SetupAdbConnection() {
timeout.tv_sec = kControlSockSendTimeout;
timeout.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
- snprintf(buff, sizeof(buff), "%04x", getpid());
- buff[sizeof(pid_t)] = 0;
+ int32_t pid = getpid();
while (!shutting_down_) {
// If adbd isn't running, because USB debugging was disabled or
@@ -529,9 +527,9 @@ bool AdbConnectionState::SetupAdbConnection() {
return false;
}
/* now try to send our pid to the ADB daemon */
- ret = TEMP_FAILURE_RETRY(send(sock, buff, sizeof(pid_t), 0));
- if (ret == sizeof(pid_t)) {
- VLOG(jdwp) << "PID " << getpid() << " send to adb";
+ ret = TEMP_FAILURE_RETRY(send(sock, &pid, sizeof(pid), 0));
+ if (ret == sizeof(pid)) {
+ VLOG(jdwp) << "PID " << pid << " sent to adb";
control_sock_ = std::move(sock);
return true;
} else {
@@ -539,7 +537,9 @@ bool AdbConnectionState::SetupAdbConnection() {
return false;
}
} else {
- PLOG(ERROR) << "Can't connect to ADB control socket. Will retry.";
+ if (VLOG_IS_ON(jdwp)) {
+ PLOG(ERROR) << "Can't connect to ADB control socket. Will retry.";
+ }
usleep(sleep_ms * 1000);
diff --git a/benchmark/type-check/info.txt b/benchmark/type-check/info.txt
new file mode 100644
index 0000000000..d14fb9685b
--- /dev/null
+++ b/benchmark/type-check/info.txt
@@ -0,0 +1 @@
+Benchmarks for repeating check-cast and instance-of instructions in a loop.
diff --git a/benchmark/type-check/src/TypeCheckBenchmark.java b/benchmark/type-check/src/TypeCheckBenchmark.java
new file mode 100644
index 0000000000..96904d99b6
--- /dev/null
+++ b/benchmark/type-check/src/TypeCheckBenchmark.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+public class TypeCheckBenchmark {
+ public void timeCheckCastLevel1ToLevel1(int count) {
+ Object[] arr = arr1;
+ for (int i = 0; i < count; ++i) {
+ Level1 l1 = (Level1) arr[i & 1023];
+ }
+ }
+
+ public void timeCheckCastLevel2ToLevel1(int count) {
+ Object[] arr = arr2;
+ for (int i = 0; i < count; ++i) {
+ Level1 l1 = (Level1) arr[i & 1023];
+ }
+ }
+
+ public void timeCheckCastLevel3ToLevel1(int count) {
+ Object[] arr = arr3;
+ for (int i = 0; i < count; ++i) {
+ Level1 l1 = (Level1) arr[i & 1023];
+ }
+ }
+
+ public void timeCheckCastLevel9ToLevel1(int count) {
+ Object[] arr = arr9;
+ for (int i = 0; i < count; ++i) {
+ Level1 l1 = (Level1) arr[i & 1023];
+ }
+ }
+
+ public void timeCheckCastLevel9ToLevel2(int count) {
+ Object[] arr = arr9;
+ for (int i = 0; i < count; ++i) {
+ Level2 l2 = (Level2) arr[i & 1023];
+ }
+ }
+
+ public void timeInstanceOfLevel1ToLevel1(int count) {
+ int sum = 0;
+ Object[] arr = arr1;
+ for (int i = 0; i < count; ++i) {
+ if (arr[i & 1023] instanceof Level1) {
+ ++sum;
+ }
+ }
+ result = sum;
+ }
+
+ public void timeInstanceOfLevel2ToLevel1(int count) {
+ int sum = 0;
+ Object[] arr = arr2;
+ for (int i = 0; i < count; ++i) {
+ if (arr[i & 1023] instanceof Level1) {
+ ++sum;
+ }
+ }
+ result = sum;
+ }
+
+ public void timeInstanceOfLevel3ToLevel1(int count) {
+ int sum = 0;
+ Object[] arr = arr3;
+ for (int i = 0; i < count; ++i) {
+ if (arr[i & 1023] instanceof Level1) {
+ ++sum;
+ }
+ }
+ result = sum;
+ }
+
+ public void timeInstanceOfLevel9ToLevel1(int count) {
+ int sum = 0;
+ Object[] arr = arr9;
+ for (int i = 0; i < count; ++i) {
+ if (arr[i & 1023] instanceof Level1) {
+ ++sum;
+ }
+ }
+ result = sum;
+ }
+
+ public void timeInstanceOfLevel9ToLevel2(int count) {
+ int sum = 0;
+ Object[] arr = arr9;
+ for (int i = 0; i < count; ++i) {
+ if (arr[i & 1023] instanceof Level2) {
+ ++sum;
+ }
+ }
+ result = sum;
+ }
+
+ public static Object[] createArray(int level) {
+ try {
+ Class<?>[] ls = {
+ null,
+ Level1.class,
+ Level2.class,
+ Level3.class,
+ Level4.class,
+ Level5.class,
+ Level6.class,
+ Level7.class,
+ Level8.class,
+ Level9.class,
+ };
+ Class<?> l = ls[level];
+ Object[] array = new Object[1024];
+ for (int i = 0; i < array.length; ++i) {
+ array[i] = l.newInstance();
+ }
+ return array;
+ } catch (Exception unexpected) {
+ throw new Error("Initialization failure!");
+ }
+ }
+ Object[] arr1 = createArray(1);
+ Object[] arr2 = createArray(2);
+ Object[] arr3 = createArray(3);
+ Object[] arr9 = createArray(9);
+ int result;
+}
+
+class Level1 { }
+class Level2 extends Level1 { }
+class Level3 extends Level2 { }
+class Level4 extends Level3 { }
+class Level5 extends Level4 { }
+class Level6 extends Level5 { }
+class Level7 extends Level6 { }
+class Level8 extends Level7 { }
+class Level9 extends Level8 { }
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 894b33b00a..4a35ccfa13 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -83,6 +83,11 @@ ART_TEST_TARGET_GTEST_MainUncompressed_DEX := $(basename $(ART_TEST_TARGET_GTEST
ART_TEST_HOST_GTEST_EmptyUncompressed_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))EmptyUncompressed$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
ART_TEST_TARGET_GTEST_EmptyUncompressed_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))EmptyUncompressed$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
+# Create rules for MultiDexUncompressed, a copy of MultiDex with the classes.dex uncompressed
+# for the OatFile tests.
+ART_TEST_HOST_GTEST_MultiDexUncompressed_DEX := $(basename $(ART_TEST_HOST_GTEST_MultiDex_DEX))Uncompressed$(suffix $(ART_TEST_HOST_GTEST_MultiDex_DEX))
+ART_TEST_TARGET_GTEST_MultiDexUncompressed_DEX := $(basename $(ART_TEST_TARGET_GTEST_MultiDex_DEX))Uncompressed$(suffix $(ART_TEST_TARGET_GTEST_MultiDex_DEX))
+
$(ART_TEST_HOST_GTEST_MainStripped_DEX): $(ART_TEST_HOST_GTEST_Main_DEX)
cp $< $@
$(call dexpreopt-remove-classes.dex,$@)
@@ -111,6 +116,16 @@ $(ART_TEST_TARGET_GTEST_EmptyUncompressed_DEX): $(ZIPALIGN)
zip -j -qD -X -0 $@ $(dir $@)classes.dex
rm $(dir $@)classes.dex
+$(ART_TEST_HOST_GTEST_MultiDexUncompressed_DEX): $(ART_TEST_HOST_GTEST_MultiDex_DEX) $(ZIPALIGN)
+ cp $< $@
+ $(call uncompress-dexs, $@)
+ $(call align-package, $@)
+
+$(ART_TEST_TARGET_GTEST_MultiDexUncompressed_DEX): $(ART_TEST_TARGET_GTEST_MultiDex_DEX) $(ZIPALIGN)
+ cp $< $@
+ $(call uncompress-dexs, $@)
+ $(call align-package, $@)
+
ART_TEST_GTEST_VerifierDeps_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDeps/*.smali))
ART_TEST_GTEST_VerifierDepsMulti_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDepsMulti/*.smali))
ART_TEST_HOST_GTEST_VerifierDeps_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,VerifierDeps,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
@@ -131,6 +146,7 @@ $(ART_TEST_TARGET_GTEST_VerifierDepsMulti_DEX): $(ART_TEST_GTEST_VerifierDepsMul
$(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
# Dex file dependencies for each gtest.
+ART_GTEST_art_dex_file_loader_test_DEX_DEPS := GetMethodSignature Main Nested MultiDex
ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary MyClassNatives Nested VerifierDeps VerifierDepsMulti
ART_GTEST_atomic_dex_ref_map_test_DEX_DEPS := Interfaces
@@ -139,7 +155,6 @@ ART_GTEST_class_loader_context_test_DEX_DEPS := Main MultiDex MyClass ForClassLo
ART_GTEST_class_table_test_DEX_DEPS := XandY
ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex
ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages MethodTypes
-ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested MultiDex
ART_GTEST_dexlayout_test_DEX_DEPS := ManyMethods
ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) ManyMethods Statics VerifierDeps MainUncompressed EmptyUncompressed
ART_GTEST_dex2oat_image_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics VerifierDeps
@@ -153,7 +168,7 @@ ART_GTEST_jni_internal_test_DEX_DEPS := AllFields StaticLeafMethods
ART_GTEST_oat_file_assistant_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
ART_GTEST_dexoptanalyzer_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
ART_GTEST_image_space_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
-ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex
+ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex MainUncompressed MultiDexUncompressed
ART_GTEST_oat_test_DEX_DEPS := Main
ART_GTEST_object_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
ART_GTEST_patchoat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
@@ -318,6 +333,7 @@ ART_TEST_MODULES := \
art_dexoptanalyzer_tests \
art_hiddenapi_tests \
art_imgdiag_tests \
+ art_libdexfile_tests \
art_oatdump_tests \
art_patchoat_tests \
art_profman_tests \
@@ -360,19 +376,31 @@ ifneq ($(ART_TEST_ANDROID_ROOT),)
ART_GTEST_TARGET_ANDROID_ROOT := $(ART_TEST_ANDROID_ROOT)
endif
-ART_VALGRIND_TARGET_DEPENDENCIES := \
+ART_VALGRIND_TARGET_DEPENDENCIES :=
+
+# Has to match list in external/valgrind/Android.build_one.mk
+ART_VALGRIND_SUPPORTED_ARCH := arm arm64 x86_64
+
+# Valgrind is not supported for x86
+ifneq (,$(filter $(ART_VALGRIND_SUPPORTED_ARCH),$(TARGET_ARCH)))
+art_vg_arch := $(if $(filter x86_64,$(TARGET_ARCH)),amd64,$(TARGET_ARCH))
+ART_VALGRIND_TARGET_DEPENDENCIES += \
$(TARGET_OUT_EXECUTABLES)/valgrind \
- $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/memcheck-$(TARGET_ARCH)-linux \
- $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_core-$(TARGET_ARCH)-linux.so \
- $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_memcheck-$(TARGET_ARCH)-linux.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/memcheck-$(art_vg_arch)-linux \
+ $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_core-$(art_vg_arch)-linux.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_memcheck-$(art_vg_arch)-linux.so \
$(TARGET_OUT_SHARED_LIBRARIES)/valgrind/default.supp
+art_vg_arch :=
+endif
ifdef TARGET_2ND_ARCH
+ifneq (,$(filter $(ART_VALGRIND_SUPPORTED_ARCH),$(TARGET_2ND_ARCH)))
ART_VALGRIND_TARGET_DEPENDENCIES += \
$(TARGET_OUT_SHARED_LIBRARIES)/valgrind/memcheck-$(TARGET_2ND_ARCH)-linux \
$(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_core-$(TARGET_2ND_ARCH)-linux.so \
$(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_memcheck-$(TARGET_2ND_ARCH)-linux.so
endif
+endif
include $(CLEAR_VARS)
LOCAL_MODULE := valgrind-target-suppressions.txt
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 453965947d..ba08d7975b 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -184,7 +184,6 @@ art_cc_defaults {
},
generated_sources: ["art_compiler_operator_srcs"],
shared_libs: [
- "libdexfile",
"libbase",
"libcutils", // for atrace.
"liblzma",
@@ -250,6 +249,7 @@ art_cc_library {
},
shared_libs: [
"libart",
+ "libdexfile",
],
pgo: {
@@ -295,6 +295,7 @@ art_cc_library {
},
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index f34e9b844b..451a909965 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -76,7 +76,7 @@ static bool IsCurrentJniNormal() {
return gCurrentJni == static_cast<uint32_t>(JniKind::kNormal);
}
-// Signifify that a different kind of JNI is about to be tested.
+// Signify that a different kind of JNI is about to be tested.
static void UpdateCurrentJni(JniKind kind) {
gCurrentJni = static_cast<uint32_t>(kind);
}
@@ -523,7 +523,8 @@ struct ScopedDisableCheckNumStackReferences {
bool ScopedDisableCheckNumStackReferences::sCheckNumStackReferences = true;
-// Check that the handle scope at the start of this block is the same as the handle scope at the end of the block.
+// Check that the handle scope at the start of this block is the same
+// as the handle scope at the end of the block.
struct ScopedCheckHandleScope {
ScopedCheckHandleScope() : handle_scope_(Thread::Current()->GetTopHandleScope()) {
}
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index eb122b7781..97604b38a1 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -3702,77 +3702,251 @@ void InstructionCodeGeneratorMIPS::HandleCondition(HCondition* instruction) {
void InstructionCodeGeneratorMIPS::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
DCHECK(instruction->IsDiv() || instruction->IsRem());
- DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32);
LocationSummary* locations = instruction->GetLocations();
Location second = locations->InAt(1);
DCHECK(second.IsConstant());
-
- Register out = locations->Out().AsRegister<Register>();
- Register dividend = locations->InAt(0).AsRegister<Register>();
- int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+ int64_t imm = Int64FromConstant(second.GetConstant());
DCHECK(imm == 1 || imm == -1);
- if (instruction->IsRem()) {
- __ Move(out, ZERO);
+ if (instruction->GetResultType() == DataType::Type::kInt32) {
+ Register out = locations->Out().AsRegister<Register>();
+ Register dividend = locations->InAt(0).AsRegister<Register>();
+
+ if (instruction->IsRem()) {
+ __ Move(out, ZERO);
+ } else {
+ if (imm == -1) {
+ __ Subu(out, ZERO, dividend);
+ } else if (out != dividend) {
+ __ Move(out, dividend);
+ }
+ }
} else {
- if (imm == -1) {
- __ Subu(out, ZERO, dividend);
- } else if (out != dividend) {
- __ Move(out, dividend);
+ DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64);
+ Register out_high = locations->Out().AsRegisterPairHigh<Register>();
+ Register out_low = locations->Out().AsRegisterPairLow<Register>();
+ Register in_high = locations->InAt(0).AsRegisterPairHigh<Register>();
+ Register in_low = locations->InAt(0).AsRegisterPairLow<Register>();
+
+ if (instruction->IsRem()) {
+ __ Move(out_high, ZERO);
+ __ Move(out_low, ZERO);
+ } else {
+ if (imm == -1) {
+ __ Subu(out_low, ZERO, in_low);
+ __ Sltu(AT, ZERO, out_low);
+ __ Subu(out_high, ZERO, in_high);
+ __ Subu(out_high, out_high, AT);
+ } else {
+ __ Move(out_low, in_low);
+ __ Move(out_high, in_high);
+ }
}
}
}
void InstructionCodeGeneratorMIPS::DivRemByPowerOfTwo(HBinaryOperation* instruction) {
DCHECK(instruction->IsDiv() || instruction->IsRem());
- DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32);
LocationSummary* locations = instruction->GetLocations();
Location second = locations->InAt(1);
+ const bool is_r2_or_newer = codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2();
+ const bool is_r6 = codegen_->GetInstructionSetFeatures().IsR6();
DCHECK(second.IsConstant());
- Register out = locations->Out().AsRegister<Register>();
- Register dividend = locations->InAt(0).AsRegister<Register>();
- int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
- uint32_t abs_imm = static_cast<uint32_t>(AbsOrMin(imm));
- int ctz_imm = CTZ(abs_imm);
+ if (instruction->GetResultType() == DataType::Type::kInt32) {
+ Register out = locations->Out().AsRegister<Register>();
+ Register dividend = locations->InAt(0).AsRegister<Register>();
+ int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+ uint32_t abs_imm = static_cast<uint32_t>(AbsOrMin(imm));
+ int ctz_imm = CTZ(abs_imm);
- if (instruction->IsDiv()) {
- if (ctz_imm == 1) {
- // Fast path for division by +/-2, which is very common.
- __ Srl(TMP, dividend, 31);
+ if (instruction->IsDiv()) {
+ if (ctz_imm == 1) {
+ // Fast path for division by +/-2, which is very common.
+ __ Srl(TMP, dividend, 31);
+ } else {
+ __ Sra(TMP, dividend, 31);
+ __ Srl(TMP, TMP, 32 - ctz_imm);
+ }
+ __ Addu(out, dividend, TMP);
+ __ Sra(out, out, ctz_imm);
+ if (imm < 0) {
+ __ Subu(out, ZERO, out);
+ }
} else {
- __ Sra(TMP, dividend, 31);
- __ Srl(TMP, TMP, 32 - ctz_imm);
- }
- __ Addu(out, dividend, TMP);
- __ Sra(out, out, ctz_imm);
- if (imm < 0) {
- __ Subu(out, ZERO, out);
+ if (ctz_imm == 1) {
+ // Fast path for modulo +/-2, which is very common.
+ __ Sra(TMP, dividend, 31);
+ __ Subu(out, dividend, TMP);
+ __ Andi(out, out, 1);
+ __ Addu(out, out, TMP);
+ } else {
+ __ Sra(TMP, dividend, 31);
+ __ Srl(TMP, TMP, 32 - ctz_imm);
+ __ Addu(out, dividend, TMP);
+ if (IsUint<16>(abs_imm - 1)) {
+ __ Andi(out, out, abs_imm - 1);
+ } else {
+ if (is_r2_or_newer) {
+ __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
+ } else {
+ __ Sll(out, out, 32 - ctz_imm);
+ __ Srl(out, out, 32 - ctz_imm);
+ }
+ }
+ __ Subu(out, out, TMP);
+ }
}
} else {
- if (ctz_imm == 1) {
- // Fast path for modulo +/-2, which is very common.
- __ Sra(TMP, dividend, 31);
- __ Subu(out, dividend, TMP);
- __ Andi(out, out, 1);
- __ Addu(out, out, TMP);
+ DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64);
+ Register out_high = locations->Out().AsRegisterPairHigh<Register>();
+ Register out_low = locations->Out().AsRegisterPairLow<Register>();
+ Register in_high = locations->InAt(0).AsRegisterPairHigh<Register>();
+ Register in_low = locations->InAt(0).AsRegisterPairLow<Register>();
+ int64_t imm = Int64FromConstant(second.GetConstant());
+ uint64_t abs_imm = static_cast<uint64_t>(AbsOrMin(imm));
+ int ctz_imm = CTZ(abs_imm);
+
+ if (instruction->IsDiv()) {
+ if (ctz_imm < 32) {
+ if (ctz_imm == 1) {
+ __ Srl(AT, in_high, 31);
+ } else {
+ __ Sra(AT, in_high, 31);
+ __ Srl(AT, AT, 32 - ctz_imm);
+ }
+ __ Addu(AT, AT, in_low);
+ __ Sltu(TMP, AT, in_low);
+ __ Addu(out_high, in_high, TMP);
+ __ Srl(out_low, AT, ctz_imm);
+ if (is_r2_or_newer) {
+ __ Ins(out_low, out_high, 32 - ctz_imm, ctz_imm);
+ __ Sra(out_high, out_high, ctz_imm);
+ } else {
+ __ Sll(AT, out_high, 32 - ctz_imm);
+ __ Sra(out_high, out_high, ctz_imm);
+ __ Or(out_low, out_low, AT);
+ }
+ if (imm < 0) {
+ __ Subu(out_low, ZERO, out_low);
+ __ Sltu(AT, ZERO, out_low);
+ __ Subu(out_high, ZERO, out_high);
+ __ Subu(out_high, out_high, AT);
+ }
+ } else if (ctz_imm == 32) {
+ __ Sra(AT, in_high, 31);
+ __ Addu(AT, AT, in_low);
+ __ Sltu(AT, AT, in_low);
+ __ Addu(out_low, in_high, AT);
+ if (imm < 0) {
+ __ Srl(TMP, out_low, 31);
+ __ Subu(out_low, ZERO, out_low);
+ __ Sltu(AT, ZERO, out_low);
+ __ Subu(out_high, TMP, AT);
+ } else {
+ __ Sra(out_high, out_low, 31);
+ }
+ } else if (ctz_imm < 63) {
+ __ Sra(AT, in_high, 31);
+ __ Srl(TMP, AT, 64 - ctz_imm);
+ __ Addu(AT, AT, in_low);
+ __ Sltu(AT, AT, in_low);
+ __ Addu(out_low, in_high, AT);
+ __ Addu(out_low, out_low, TMP);
+ __ Sra(out_low, out_low, ctz_imm - 32);
+ if (imm < 0) {
+ __ Subu(out_low, ZERO, out_low);
+ }
+ __ Sra(out_high, out_low, 31);
+ } else {
+ DCHECK_LT(imm, 0);
+ if (is_r6) {
+ __ Aui(AT, in_high, 0x8000);
+ } else {
+ __ Lui(AT, 0x8000);
+ __ Xor(AT, AT, in_high);
+ }
+ __ Or(AT, AT, in_low);
+ __ Sltiu(out_low, AT, 1);
+ __ Move(out_high, ZERO);
+ }
} else {
- __ Sra(TMP, dividend, 31);
- __ Srl(TMP, TMP, 32 - ctz_imm);
- __ Addu(out, dividend, TMP);
- if (IsUint<16>(abs_imm - 1)) {
- __ Andi(out, out, abs_imm - 1);
+ if ((ctz_imm == 1) && !is_r6) {
+ __ Andi(AT, in_low, 1);
+ __ Sll(TMP, in_low, 31);
+ __ And(TMP, in_high, TMP);
+ __ Sra(out_high, TMP, 31);
+ __ Or(out_low, out_high, AT);
+ } else if (ctz_imm < 32) {
+ __ Sra(AT, in_high, 31);
+ if (ctz_imm <= 16) {
+ __ Andi(out_low, in_low, abs_imm - 1);
+ } else if (is_r2_or_newer) {
+ __ Ext(out_low, in_low, 0, ctz_imm);
+ } else {
+ __ Sll(out_low, in_low, 32 - ctz_imm);
+ __ Srl(out_low, out_low, 32 - ctz_imm);
+ }
+ if (is_r6) {
+ __ Selnez(out_high, AT, out_low);
+ } else {
+ __ Movz(AT, ZERO, out_low);
+ __ Move(out_high, AT);
+ }
+ if (is_r2_or_newer) {
+ __ Ins(out_low, out_high, ctz_imm, 32 - ctz_imm);
+ } else {
+ __ Sll(AT, out_high, ctz_imm);
+ __ Or(out_low, out_low, AT);
+ }
+ } else if (ctz_imm == 32) {
+ __ Sra(AT, in_high, 31);
+ __ Move(out_low, in_low);
+ if (is_r6) {
+ __ Selnez(out_high, AT, out_low);
+ } else {
+ __ Movz(AT, ZERO, out_low);
+ __ Move(out_high, AT);
+ }
+ } else if (ctz_imm < 63) {
+ __ Sra(AT, in_high, 31);
+ __ Move(TMP, in_low);
+ if (ctz_imm - 32 <= 16) {
+ __ Andi(out_high, in_high, (1 << (ctz_imm - 32)) - 1);
+ } else if (is_r2_or_newer) {
+ __ Ext(out_high, in_high, 0, ctz_imm - 32);
+ } else {
+ __ Sll(out_high, in_high, 64 - ctz_imm);
+ __ Srl(out_high, out_high, 64 - ctz_imm);
+ }
+ __ Move(out_low, TMP);
+ __ Or(TMP, TMP, out_high);
+ if (is_r6) {
+ __ Selnez(AT, AT, TMP);
+ } else {
+ __ Movz(AT, ZERO, TMP);
+ }
+ if (is_r2_or_newer) {
+ __ Ins(out_high, AT, ctz_imm - 32, 64 - ctz_imm);
+ } else {
+ __ Sll(AT, AT, ctz_imm - 32);
+ __ Or(out_high, out_high, AT);
+ }
} else {
- if (codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()) {
- __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
+ if (is_r6) {
+ __ Aui(AT, in_high, 0x8000);
} else {
- __ Sll(out, out, 32 - ctz_imm);
- __ Srl(out, out, 32 - ctz_imm);
+ __ Lui(AT, 0x8000);
+ __ Xor(AT, AT, in_high);
}
+ __ Or(AT, AT, in_low);
+ __ Sltiu(AT, AT, 1);
+ __ Sll(AT, AT, 31);
+ __ Move(out_low, in_low);
+ __ Xor(out_high, in_high, AT);
}
- __ Subu(out, out, TMP);
}
}
}
@@ -3870,7 +4044,16 @@ void InstructionCodeGeneratorMIPS::GenerateDivRemIntegral(HBinaryOperation* inst
void LocationsBuilderMIPS::VisitDiv(HDiv* div) {
DataType::Type type = div->GetResultType();
- LocationSummary::CallKind call_kind = (type == DataType::Type::kInt64)
+ bool call_long_div = false;
+ if (type == DataType::Type::kInt64) {
+ if (div->InputAt(1)->IsConstant()) {
+ int64_t imm = CodeGenerator::GetInt64ValueOf(div->InputAt(1)->AsConstant());
+ call_long_div = (imm != 0) && !IsPowerOfTwo(static_cast<uint64_t>(AbsOrMin(imm)));
+ } else {
+ call_long_div = true;
+ }
+ }
+ LocationSummary::CallKind call_kind = call_long_div
? LocationSummary::kCallOnMainOnly
: LocationSummary::kNoCall;
@@ -3884,12 +4067,18 @@ void LocationsBuilderMIPS::VisitDiv(HDiv* div) {
break;
case DataType::Type::kInt64: {
- InvokeRuntimeCallingConvention calling_convention;
- locations->SetInAt(0, Location::RegisterPairLocation(
- calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
- locations->SetInAt(1, Location::RegisterPairLocation(
- calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
- locations->SetOut(calling_convention.GetReturnLocation(type));
+ if (call_long_div) {
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
+ locations->SetInAt(1, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
+ locations->SetOut(calling_convention.GetReturnLocation(type));
+ } else {
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::ConstantLocation(div->InputAt(1)->AsConstant()));
+ locations->SetOut(Location::RequiresRegister());
+ }
break;
}
@@ -3914,8 +4103,20 @@ void InstructionCodeGeneratorMIPS::VisitDiv(HDiv* instruction) {
GenerateDivRemIntegral(instruction);
break;
case DataType::Type::kInt64: {
- codegen_->InvokeRuntime(kQuickLdiv, instruction, instruction->GetDexPc());
- CheckEntrypointTypes<kQuickLdiv, int64_t, int64_t, int64_t>();
+ if (locations->InAt(1).IsConstant()) {
+ int64_t imm = locations->InAt(1).GetConstant()->AsLongConstant()->GetValue();
+ if (imm == 0) {
+ // Do not generate anything. DivZeroCheck would prevent any code to be executed.
+ } else if (imm == 1 || imm == -1) {
+ DivRemOneOrMinusOne(instruction);
+ } else {
+ DCHECK(IsPowerOfTwo(static_cast<uint64_t>(AbsOrMin(imm))));
+ DivRemByPowerOfTwo(instruction);
+ }
+ } else {
+ codegen_->InvokeRuntime(kQuickLdiv, instruction, instruction->GetDexPc());
+ CheckEntrypointTypes<kQuickLdiv, int64_t, int64_t, int64_t>();
+ }
break;
}
case DataType::Type::kFloat32:
@@ -8493,9 +8694,16 @@ void InstructionCodeGeneratorMIPS::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED)
void LocationsBuilderMIPS::VisitRem(HRem* rem) {
DataType::Type type = rem->GetResultType();
- LocationSummary::CallKind call_kind = (type == DataType::Type::kInt32)
- ? LocationSummary::kNoCall
- : LocationSummary::kCallOnMainOnly;
+ bool call_rem;
+ if ((type == DataType::Type::kInt64) && rem->InputAt(1)->IsConstant()) {
+ int64_t imm = CodeGenerator::GetInt64ValueOf(rem->InputAt(1)->AsConstant());
+ call_rem = (imm != 0) && !IsPowerOfTwo(static_cast<uint64_t>(AbsOrMin(imm)));
+ } else {
+ call_rem = (type != DataType::Type::kInt32);
+ }
+ LocationSummary::CallKind call_kind = call_rem
+ ? LocationSummary::kCallOnMainOnly
+ : LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(rem, call_kind);
switch (type) {
@@ -8506,12 +8714,18 @@ void LocationsBuilderMIPS::VisitRem(HRem* rem) {
break;
case DataType::Type::kInt64: {
- InvokeRuntimeCallingConvention calling_convention;
- locations->SetInAt(0, Location::RegisterPairLocation(
- calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
- locations->SetInAt(1, Location::RegisterPairLocation(
- calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
- locations->SetOut(calling_convention.GetReturnLocation(type));
+ if (call_rem) {
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
+ locations->SetInAt(1, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
+ locations->SetOut(calling_convention.GetReturnLocation(type));
+ } else {
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::ConstantLocation(rem->InputAt(1)->AsConstant()));
+ locations->SetOut(Location::RequiresRegister());
+ }
break;
}
@@ -8531,14 +8745,27 @@ void LocationsBuilderMIPS::VisitRem(HRem* rem) {
void InstructionCodeGeneratorMIPS::VisitRem(HRem* instruction) {
DataType::Type type = instruction->GetType();
+ LocationSummary* locations = instruction->GetLocations();
switch (type) {
case DataType::Type::kInt32:
GenerateDivRemIntegral(instruction);
break;
case DataType::Type::kInt64: {
- codegen_->InvokeRuntime(kQuickLmod, instruction, instruction->GetDexPc());
- CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>();
+ if (locations->InAt(1).IsConstant()) {
+ int64_t imm = locations->InAt(1).GetConstant()->AsLongConstant()->GetValue();
+ if (imm == 0) {
+ // Do not generate anything. DivZeroCheck would prevent any code to be executed.
+ } else if (imm == 1 || imm == -1) {
+ DivRemOneOrMinusOne(instruction);
+ } else {
+ DCHECK(IsPowerOfTwo(static_cast<uint64_t>(AbsOrMin(imm))));
+ DivRemByPowerOfTwo(instruction);
+ }
+ } else {
+ codegen_->InvokeRuntime(kQuickLmod, instruction, instruction->GetDexPc());
+ CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>();
+ }
break;
}
case DataType::Type::kFloat32: {
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 64a1eccf60..a38e2717cf 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -960,14 +960,18 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
dchecked_integral_cast<uint64_t>(string_init_entry_point)
};
- MethodReference target_method(dex_file_, method_idx);
+ ScopedObjectAccess soa(Thread::Current());
+ MethodReference target_method(resolved_method->GetDexFile(),
+ resolved_method->GetDexMethodIndex());
+ // We pass null for the resolved_method to ensure optimizations
+ // don't rely on it.
HInvoke* invoke = new (allocator_) HInvokeStaticOrDirect(
allocator_,
number_of_arguments - 1,
DataType::Type::kReference /*return_type */,
dex_pc,
method_idx,
- nullptr,
+ nullptr /* resolved_method */,
dispatch_info,
invoke_type,
target_method,
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 43ca2cf874..f91d37b3ac 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4567,7 +4567,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
kFieldClinitCheckRequirementSize>;
// Cached values of the resolved method, to avoid needing the mutator lock.
- MethodReference target_method_;
+ const MethodReference target_method_;
DispatchInfo dispatch_info_;
};
std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 8bb124e066..67a61fc01d 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -537,14 +537,13 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst
Thread* self = Thread::Current();
StackHandleScope<2> hs(self);
const DexFile& dex_file = *invoke->GetTargetMethod().dex_file;
+ uint32_t dex_method_index = invoke->GetTargetMethod().index;
Handle<mirror::DexCache> dex_cache(
hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_)));
- // Use a null loader. We should probably use the compiling method's class loader,
- // but then we would need to pass it to RTPVisitor just for this debug check. Since
- // the method is from the String class, the null loader is good enough.
+ // Use a null loader, the target method is in a boot classpath dex file.
Handle<mirror::ClassLoader> loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
ArtMethod* method = cl->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
- invoke->GetDexMethodIndex(), dex_cache, loader, /* referrer */ nullptr, kDirect);
+ dex_method_index, dex_cache, loader, /* referrer */ nullptr, kDirect);
DCHECK(method != nullptr);
mirror::Class* declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class != nullptr);
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 8640e2db0e..ea160c8993 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1914,7 +1914,7 @@ void X86Assembler::cmpb(const Address& address, const Immediate& imm) {
void X86Assembler::cmpw(const Address& address, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
- EmitComplex(7, address, imm);
+ EmitComplex(7, address, imm, /* is_16_op */ true);
}
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index 937dd80c4e..2fd1b27182 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -921,9 +921,7 @@ TEST_F(AssemblerX86Test, Cmpb) {
}
TEST_F(AssemblerX86Test, Cmpw) {
- DriverStr(RepeatAI(&x86::X86Assembler::cmpw,
- /*imm_bytes*/ 1U,
- "cmpw ${imm}, {mem}"), "cmpw"); // TODO: only imm8?
+ DriverStr(RepeatAI(&x86::X86Assembler::cmpw, /*imm_bytes*/ 2U, "cmpw ${imm}, {mem}"), "cmpw");
}
} // namespace art
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index feabf260af..ff5a357c5e 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -2199,7 +2199,7 @@ void X86_64Assembler::cmpw(const Address& address, const Immediate& imm) {
CHECK(imm.is_int32());
EmitOperandSizeOverride();
EmitOptionalRex32(address);
- EmitComplex(7, address, imm);
+ EmitComplex(7, address, imm, /* is_16_op */ true);
}
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 5e6c83396a..6b1e53c35a 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -967,9 +967,8 @@ TEST_F(AssemblerX86_64Test, MovbStore) {
}
TEST_F(AssemblerX86_64Test, Cmpw) {
- DriverStr(RepeatAI(&x86_64::X86_64Assembler::cmpw,
- /*imm_bytes*/ 1U,
- "cmpw ${imm}, {mem}"), "cmpw"); // TODO: only imm8?
+ DriverStr(
+ RepeatAI(&x86_64::X86_64Assembler::cmpw, /*imm_bytes*/ 2U, "cmpw ${imm}, {mem}"), "cmpw");
}
TEST_F(AssemblerX86_64Test, MovqAddrImm) {
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index ab06ddda2d..dd16ba4909 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -152,7 +152,7 @@ art_cc_binary {
"libartd-compiler",
"libartd-dexlayout",
"libartd",
- "libdexfile",
+ "libdexfiled",
"libbase",
"liblz4",
"libsigchain",
@@ -185,6 +185,7 @@ art_cc_binary {
"libart-compiler",
"libart-dexlayout",
"libart",
+ "libdexfile",
"libvixl-arm",
"libvixl-arm64",
] + art_static_dependencies,
@@ -216,6 +217,7 @@ art_cc_binary {
"libartd-compiler",
"libartd-dexlayout",
"libartd",
+ "libdexfiled",
"libvixld-arm",
"libvixld-arm64",
] + art_static_dependencies,
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index c4e53987eb..64db7be79c 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -456,6 +456,12 @@ NO_RETURN static void Usage(const char* fmt, ...) {
UsageError(" --deduplicate-code=true|false: enable|disable code deduplication. Deduplicated");
UsageError(" code will have an arbitrary symbol tagged with [DEDUPED].");
UsageError("");
+ UsageError(" --compilation-reason=<string>: optional metadata specifying the reason for");
+ UsageError(" compiling the apk. If specified, the string will be embedded verbatim in");
+ UsageError(" the key value store of the oat file.");
+ UsageError("");
+ UsageError(" Example: --compilation-reason=install");
+ UsageError("");
std::cerr << "See log for usage error information\n";
exit(EXIT_FAILURE);
}
@@ -1212,6 +1218,7 @@ class Dex2Oat FINAL {
AssignIfExists(args, M::ClasspathDir, &classpath_dir_);
AssignIfExists(args, M::DirtyImageObjects, &dirty_image_objects_filename_);
AssignIfExists(args, M::ImageFormat, &image_storage_mode_);
+ AssignIfExists(args, M::CompilationReason, &compilation_reason_);
AssignIfExists(args, M::Backend, &compiler_kind_);
parser_options->requested_specific_compiler = args.Exists(M::Backend);
@@ -1512,6 +1519,10 @@ class Dex2Oat FINAL {
return dex2oat::ReturnCode::kOther;
}
+ if (!compilation_reason_.empty()) {
+ key_value_store_->Put(OatHeader::kCompilationReasonKey, compilation_reason_);
+ }
+
if (IsBootImage() && image_filenames_.size() > 1) {
// If we're compiling the boot image, store the boot classpath into the Key-Value store.
// We need this for the multi-image case.
@@ -2907,6 +2918,9 @@ class Dex2Oat FINAL {
// Whether the given input vdex is also the output.
bool update_input_vdex_ = false;
+ // The reason for invoking the compiler.
+ std::string compilation_reason_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
};
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 0eecc84605..4b6f8a4a54 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -246,7 +246,10 @@ static Parser CreateArgumentParser() {
.IntoKey(M::CompactDexLevel)
.Define("--runtime-arg _")
.WithType<std::vector<std::string>>().AppendValues()
- .IntoKey(M::RuntimeOptions);
+ .IntoKey(M::RuntimeOptions)
+ .Define("--compilation-reason=_")
+ .WithType<std::string>()
+ .IntoKey(M::CompilationReason);
AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder);
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index 9a8bdf4aee..a1646aafe3 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -89,5 +89,6 @@ DEX2OAT_OPTIONS_KEY (std::string, ClasspathDir)
DEX2OAT_OPTIONS_KEY (std::string, ClassLoaderContext)
DEX2OAT_OPTIONS_KEY (std::string, DirtyImageObjects)
DEX2OAT_OPTIONS_KEY (std::vector<std::string>, RuntimeOptions)
+DEX2OAT_OPTIONS_KEY (std::string, CompilationReason)
#undef DEX2OAT_OPTIONS_KEY
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index d0b0d49a39..4ac8e6a3eb 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -796,7 +796,7 @@ class Dex2oatLayoutTest : public Dex2oatTest {
app_image_file_name,
/* use_fd */ true,
/* num_profile_classes */ 1,
- { input_vdex, output_vdex, kDisableCompactDex },
+ { input_vdex, output_vdex },
/* expect_success */ true);
EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
}
@@ -926,6 +926,49 @@ class Dex2oatUnquickenTest : public Dex2oatTest {
ASSERT_TRUE(success_);
}
+ void RunUnquickenMultiDexCDex() {
+ std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
+ std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
+ std::string odex_location2 = GetOdexDir() + "/UnquickenMultiDex2.odex";
+ std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
+ std::string vdex_location2 = GetOdexDir() + "/UnquickenMultiDex2.vdex";
+ Copy(GetTestDexFileName("MultiDex"), dex_location);
+
+ std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
+ std::unique_ptr<File> vdex_file2(OS::CreateEmptyFile(vdex_location2.c_str()));
+ CHECK(vdex_file1 != nullptr) << vdex_location;
+ CHECK(vdex_file2 != nullptr) << vdex_location2;
+
+ // Quicken the dex file into a vdex file.
+ {
+ std::string input_vdex = "--input-vdex-fd=-1";
+ std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kQuicken,
+ { input_vdex, output_vdex, "--compact-dex-level=fast"},
+ /* expect_success */ true,
+ /* use_fd */ true);
+ EXPECT_GT(vdex_file1->GetLength(), 0u);
+ }
+
+ // Unquicken by running the verify compiler filter on the vdex file.
+ {
+ std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
+ std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2->Fd());
+ GenerateOdexForTest(dex_location,
+ odex_location2,
+ CompilerFilter::kVerify,
+ { input_vdex, output_vdex, "--compact-dex-level=none"},
+ /* expect_success */ true,
+ /* use_fd */ true);
+ }
+ ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
+ ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
+ CheckResult(dex_location, odex_location2);
+ ASSERT_TRUE(success_);
+ }
+
void CheckResult(const std::string& dex_location, const std::string& odex_location) {
std::string error_msg;
std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
@@ -966,6 +1009,10 @@ TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
RunUnquickenMultiDex();
}
+TEST_F(Dex2oatUnquickenTest, UnquickenMultiDexCDex) {
+ RunUnquickenMultiDexCDex();
+}
+
class Dex2oatWatchdogTest : public Dex2oatTest {
protected:
void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
@@ -1667,4 +1714,71 @@ TEST_F(Dex2oatTest, CompactDexGenerationFailure) {
}
}
+TEST_F(Dex2oatTest, StderrLoggerOutput) {
+ std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
+ std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
+
+ // Test file doesn't matter.
+ Copy(GetDexSrc1(), dex_location);
+
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kQuicken,
+ { "--runtime-arg", "-Xuse-stderr-logger" },
+ true);
+ // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
+ // even on device.
+ EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
+}
+
+TEST_F(Dex2oatTest, VerifyCompilationReason) {
+ std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
+ std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
+
+ // Test file doesn't matter.
+ Copy(GetDexSrc1(), dex_location);
+
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kVerify,
+ { "--compilation-reason=install" },
+ true);
+ std::string error_msg;
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
+ ASSERT_TRUE(odex_file != nullptr);
+ ASSERT_STREQ("install", odex_file->GetCompilationReason());
+}
+
+TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
+ std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
+ std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
+
+ // Test file doesn't matter.
+ Copy(GetDexSrc1(), dex_location);
+
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kVerify,
+ {},
+ true);
+ std::string error_msg;
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
+ ASSERT_TRUE(odex_file != nullptr);
+ ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
+}
+
} // namespace art
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 73eaad47a1..42d228078c 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -2364,7 +2364,7 @@ void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
FixupClassVisitor visitor(this, copy);
ObjPtr<mirror::Object>(orig)->VisitReferences(visitor, visitor);
- if (compile_app_image_) {
+ if (kBitstringSubtypeCheckEnabled && compile_app_image_) {
// When we call SubtypeCheck::EnsureInitialize, it Assigns new bitstring
// values to the parent of that class.
//
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 01125a178e..7d8065e926 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -3373,15 +3373,19 @@ bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_v
CHECK(!update_input_vdex) << "Update input vdex should have empty dex container";
DexContainer::Section* const section = dex_container_->GetDataSection();
if (section->Size() > 0) {
- const uint32_t shared_data_offset = vdex_size_;
const off_t existing_offset = out->Seek(0, kSeekCurrent);
- if (static_cast<uint32_t>(existing_offset) != shared_data_offset) {
- LOG(ERROR) << "Expected offset " << shared_data_offset << " but got " << existing_offset;
+ if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
+ PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
+ << existing_offset;
return false;
}
shared_data_size = section->Size();
if (!out->WriteFully(section->Begin(), shared_data_size)) {
- LOG(ERROR) << "Failed to write shared data!";
+ PLOG(ERROR) << "Failed to write shared data!";
+ return false;
+ }
+ if (!out->Flush()) {
+ PLOG(ERROR) << "Failed to flush after writing shared dex section.";
return false;
}
// Fix up the dex headers to have correct offsets to the data section.
@@ -3389,49 +3393,69 @@ bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_v
// Overwrite the header by reading it, updating the offset, and writing it back out.
DexFile::Header header;
if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
- LOG(ERROR) << "Failed to read dex header for updating";
+ PLOG(ERROR) << "Failed to read dex header for updating";
return false;
}
CHECK(CompactDexFile::IsMagicValid(header.magic_)) << "Must be compact dex";
- CHECK_GT(shared_data_offset, oat_dex_file.dex_file_offset_);
+ CHECK_GT(vdex_dex_shared_data_offset_, oat_dex_file.dex_file_offset_);
// Offset is from the dex file base.
- header.data_off_ = shared_data_offset - oat_dex_file.dex_file_offset_;
+ header.data_off_ = vdex_dex_shared_data_offset_ - oat_dex_file.dex_file_offset_;
// The size should already be what part of the data buffer may be used by the dex.
CHECK_LE(header.data_size_, shared_data_size);
if (!file->PwriteFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
- LOG(ERROR) << "Failed to write dex header for updating";
+ PLOG(ERROR) << "Failed to write dex header for updating";
return false;
}
}
section->Clear();
- if (!out->Flush()) {
- PLOG(ERROR) << "Failed to flush after writing shared dex section.";
- return false;
- }
}
dex_container_.reset();
} else {
- if (update_input_vdex) {
- for (OatDexFile& oat_dex_file : oat_dex_files_) {
- DexFile::Header header;
- if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
- PLOG(ERROR) << "Failed to read dex header";
- return false;
- }
- if (!CompactDexFile::IsMagicValid(header.magic_)) {
- // Non compact dex does not have shared data section.
- continue;
- }
- const uint32_t expected_data_off = vdex_dex_shared_data_offset_ -
- oat_dex_file.dex_file_offset_;
- if (header.data_off_ != expected_data_off) {
- PLOG(ERROR) << "Shared data section offset " << header.data_off_
- << " does not match expected value " << expected_data_off;
- return false;
+ const uint8_t* data_begin = nullptr;
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ DexFile::Header header;
+ if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
+ PLOG(ERROR) << "Failed to read dex header";
+ return false;
+ }
+ if (!CompactDexFile::IsMagicValid(header.magic_)) {
+ // Non compact dex does not have shared data section.
+ continue;
+ }
+ const uint32_t expected_data_off = vdex_dex_shared_data_offset_ -
+ oat_dex_file.dex_file_offset_;
+ if (header.data_off_ != expected_data_off) {
+ PLOG(ERROR) << "Shared data section offset " << header.data_off_
+ << " does not match expected value " << expected_data_off;
+ return false;
+ }
+ if (oat_dex_file.source_.IsRawData()) {
+ // Figure out the start of the shared data section so we can copy it below.
+ const uint8_t* cur_data_begin = oat_dex_file.source_.GetRawData() + header.data_off_;
+ if (data_begin != nullptr) {
+ CHECK_EQ(data_begin, cur_data_begin);
}
- // The different dex files currently can have different data sizes since
- // the dex writer writes them one at a time into the shared section.:w
- shared_data_size = std::max(shared_data_size, header.data_size_);
+ data_begin = cur_data_begin;
+ }
+ // The different dex files currently can have different data sizes since
+ // the dex writer writes them one at a time into the shared section.:w
+ shared_data_size = std::max(shared_data_size, header.data_size_);
+ }
+ // If we are not updating the input vdex, write out the shared data section.
+ if (!update_input_vdex) {
+ const off_t existing_offset = out->Seek(0, kSeekCurrent);
+ if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
+ PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
+ << existing_offset;
+ return false;
+ }
+ if (!out->WriteFully(data_begin, shared_data_size)) {
+ PLOG(ERROR) << "Failed to write shared data!";
+ return false;
+ }
+ if (!out->Flush()) {
+ PLOG(ERROR) << "Failed to flush after writing shared dex section.";
+ return false;
}
}
}
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index f6b7a6b68a..eca08448bc 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -45,6 +45,7 @@ art_cc_binary {
host_supported: true,
device_supported: false,
static_libs: [
+ "libdexfile",
"libbase",
] + art_static_dependencies,
target: {
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 3ea7f4ba82..bea61d0c71 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -27,7 +27,6 @@ art_cc_defaults {
],
export_include_dirs: ["."],
shared_libs: [
- "libdexfile",
"libbase",
],
static_libs: ["libz"],
@@ -36,7 +35,10 @@ art_cc_defaults {
art_cc_library {
name: "libart-dexlayout",
defaults: ["libart-dexlayout-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
pgo: {
instrumentation: true,
@@ -51,7 +53,10 @@ art_cc_library {
"libart-dexlayout-defaults",
"art_debug_defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
cc_defaults {
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
new file mode 100644
index 0000000000..90c603f290
--- /dev/null
+++ b/libdexfile/Android.bp
@@ -0,0 +1,125 @@
+//
+// Copyright (C) 2011 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.
+//
+
+cc_defaults {
+ name: "libdexfile_defaults",
+ defaults: ["art_defaults"],
+ host_supported: true,
+ srcs: [
+ "dex/compact_dex_debug_info.cc",
+ "dex/compact_dex_file.cc",
+ "dex/descriptors_names.cc",
+ "dex/dex_file.cc",
+ "dex/dex_file_exception_helpers.cc",
+ "dex/dex_file_loader.cc",
+ "dex/dex_file_tracking_registrar.cc",
+ "dex/dex_file_verifier.cc",
+ "dex/dex_instruction.cc",
+ "dex/modifiers.cc",
+ "dex/standard_dex_file.cc",
+ "dex/utf.cc",
+ ],
+
+ target: {
+ android: {
+ static_libs: [
+ "libziparchive",
+ "libz",
+ "libbase",
+ ],
+ shared_libs: [
+ "libutils",
+ ],
+ },
+ host: {
+ shared_libs: [
+ "libziparchive",
+ "libz",
+ ],
+ },
+ },
+ generated_sources: ["dexfile_operator_srcs"],
+ shared_libs: [
+ "liblog",
+ // For common macros.
+ "libbase",
+ "libz",
+ ],
+ header_libs: [
+ // This is needed to resolve the base/ header file inclusions here.
+ // TODO: move those headers to art/ rather than under runtime.
+ "libart_runtime_headers",
+ ],
+ export_include_dirs: ["."],
+ export_shared_lib_headers: [
+ "libbase",
+ ],
+}
+
+gensrcs {
+ name: "dexfile_operator_srcs",
+ cmd: "$(location generate-operator-out.py) art/libdexfile $(in) > $(out)",
+ tool_files: ["generate-operator-out.py"],
+ srcs: [
+ "dex/dex_file.h",
+ "dex/dex_instruction.h",
+ "dex/dex_instruction_utils.h",
+ "dex/invoke_type.h",
+ ],
+ output_extension: "operator_out.cc",
+}
+
+// TODO: add build support for libdexfiled, as we use DCHECK, etc.
+art_cc_library {
+ name: "libdexfile",
+ defaults: ["libdexfile_defaults"],
+ // Leave the symbols in the shared library so that stack unwinders can
+ // produce meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
+}
+
+art_cc_library {
+ name: "libdexfiled",
+ defaults: [
+ "art_debug_defaults",
+ "libdexfile_defaults",
+ ],
+}
+
+art_cc_test {
+ name: "art_libdexfile_tests",
+ defaults: [
+ "art_gtest_defaults",
+ ],
+ srcs: [
+ "dex/code_item_accessors_test.cc",
+ "dex/compact_dex_debug_info_test.cc",
+ "dex/compact_dex_file_test.cc",
+ "dex/dex_file_loader_test.cc",
+ "dex/dex_file_verifier_test.cc",
+ "dex/dex_instruction_test.cc",
+ "dex/utf_test.cc",
+ ],
+ shared_libs: [
+ "libbacktrace",
+ "libziparchive",
+ ],
+ include_dirs: [
+ "external/zlib",
+ ],
+}
diff --git a/runtime/dex/base64_test_util.h b/libdexfile/dex/base64_test_util.h
index 0657f9fd01..683e429e11 100644
--- a/runtime/dex/base64_test_util.h
+++ b/libdexfile/dex/base64_test_util.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
-#define ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
+#ifndef ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_
+#define ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_
#include <base/logging.h>
#include <stdint.h>
@@ -96,4 +96,4 @@ static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
} // namespace art
-#endif // ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
+#endif // ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_
diff --git a/runtime/dex/code_item_accessors-inl.h b/libdexfile/dex/code_item_accessors-inl.h
index 9c39935d3b..c166f5f19e 100644
--- a/runtime/dex/code_item_accessors-inl.h
+++ b/libdexfile/dex/code_item_accessors-inl.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_
-#define ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_
+#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
+#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
#include "code_item_accessors.h"
@@ -201,4 +201,4 @@ inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(bool is_static,
} // namespace art
-#endif // ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_
+#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_
diff --git a/runtime/dex/code_item_accessors.h b/libdexfile/dex/code_item_accessors.h
index beb78f6e4f..ba7c126ed8 100644
--- a/runtime/dex/code_item_accessors.h
+++ b/libdexfile/dex/code_item_accessors.h
@@ -16,10 +16,9 @@
// TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump.
-#ifndef ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_
-#define ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_
+#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
+#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
-#include "base/mutex.h"
#include "compact_dex_file.h"
#include "dex_file.h"
#include "dex_instruction_iterator.h"
@@ -164,4 +163,4 @@ class CodeItemDebugInfoAccessor : public CodeItemDataAccessor {
} // namespace art
-#endif // ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_
+#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
diff --git a/runtime/dex/code_item_accessors_test.cc b/libdexfile/dex/code_item_accessors_test.cc
index 2bb4dde649..2bb4dde649 100644
--- a/runtime/dex/code_item_accessors_test.cc
+++ b/libdexfile/dex/code_item_accessors_test.cc
diff --git a/runtime/dex/compact_dex_debug_info.cc b/libdexfile/dex/compact_dex_debug_info.cc
index 19495ca92c..19495ca92c 100644
--- a/runtime/dex/compact_dex_debug_info.cc
+++ b/libdexfile/dex/compact_dex_debug_info.cc
diff --git a/runtime/dex/compact_dex_debug_info.h b/libdexfile/dex/compact_dex_debug_info.h
index 1aff75879e..bfd0bbe65c 100644
--- a/runtime/dex/compact_dex_debug_info.h
+++ b/libdexfile/dex/compact_dex_debug_info.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_
-#define ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_
+#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_
+#define ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_
#include <cstdint>
#include <vector>
@@ -62,4 +62,4 @@ class CompactDexDebugInfoOffsetTable {
} // namespace art
-#endif // ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_
+#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_
diff --git a/runtime/dex/compact_dex_debug_info_test.cc b/libdexfile/dex/compact_dex_debug_info_test.cc
index 3267612443..3267612443 100644
--- a/runtime/dex/compact_dex_debug_info_test.cc
+++ b/libdexfile/dex/compact_dex_debug_info_test.cc
diff --git a/runtime/dex/compact_dex_file.cc b/libdexfile/dex/compact_dex_file.cc
index ce289d4d7b..ce289d4d7b 100644
--- a/runtime/dex/compact_dex_file.cc
+++ b/libdexfile/dex/compact_dex_file.cc
diff --git a/runtime/dex/compact_dex_file.h b/libdexfile/dex/compact_dex_file.h
index 31aeb27872..47b170c4a8 100644
--- a/runtime/dex/compact_dex_file.h
+++ b/libdexfile/dex/compact_dex_file.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_
-#define ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_
+#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
+#define ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
#include "base/casts.h"
#include "dex_file.h"
@@ -288,4 +288,4 @@ class CompactDexFile : public DexFile {
} // namespace art
-#endif // ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_
+#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
diff --git a/runtime/dex/compact_dex_file_test.cc b/libdexfile/dex/compact_dex_file_test.cc
index 517c5873ed..517c5873ed 100644
--- a/runtime/dex/compact_dex_file_test.cc
+++ b/libdexfile/dex/compact_dex_file_test.cc
diff --git a/runtime/dex/compact_dex_level.h b/libdexfile/dex/compact_dex_level.h
index de9ca3c783..2325ac2cae 100644
--- a/runtime/dex/compact_dex_level.h
+++ b/libdexfile/dex/compact_dex_level.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_
-#define ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_
+#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_
+#define ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_
#include <string>
@@ -47,4 +47,4 @@ static constexpr CompactDexLevel kDefaultCompactDexLevel = ART_DEFAULT_COMPACT_D
} // namespace art
-#endif // ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_
+#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_
diff --git a/runtime/dex/compact_dex_utils.h b/libdexfile/dex/compact_dex_utils.h
index 1c7e9514fd..c88b799e1f 100644
--- a/runtime/dex/compact_dex_utils.h
+++ b/libdexfile/dex/compact_dex_utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_
-#define ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_
+#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_
+#define ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_
#include <vector>
@@ -34,4 +34,4 @@ static inline void AlignmentPadVector(std::vector<T, Allocator<T>>* dest,
} // namespace art
-#endif // ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_
+#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_
diff --git a/runtime/dex/descriptors_names.cc b/libdexfile/dex/descriptors_names.cc
index 8124e7256f..8124e7256f 100644
--- a/runtime/dex/descriptors_names.cc
+++ b/libdexfile/dex/descriptors_names.cc
diff --git a/runtime/dex/descriptors_names.h b/libdexfile/dex/descriptors_names.h
index 22e9573556..10738eead0 100644
--- a/runtime/dex/descriptors_names.h
+++ b/libdexfile/dex/descriptors_names.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_
-#define ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_
+#ifndef ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_
+#define ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_
#include <string>
@@ -60,4 +60,4 @@ bool IsValidMemberName(const char* s);
} // namespace art
-#endif // ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_
+#endif // ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_
diff --git a/runtime/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index aa53daac35..b424b50f21 100644
--- a/runtime/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_INL_H_
-#define ART_RUNTIME_DEX_DEX_FILE_INL_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
#include "base/bit_utils.h"
#include "base/casts.h"
@@ -518,4 +518,4 @@ inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator&
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_INL_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
diff --git a/runtime/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 18eb903551..18eb903551 100644
--- a/runtime/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
diff --git a/runtime/dex/dex_file.h b/libdexfile/dex/dex_file.h
index cf8c840b59..a38e76cfd0 100644
--- a/runtime/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_H_
-#define ART_RUNTIME_DEX_DEX_FILE_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_H_
#include <memory>
#include <string>
@@ -1440,4 +1440,4 @@ std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::Val
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_H_
diff --git a/runtime/dex/dex_file_exception_helpers.cc b/libdexfile/dex/dex_file_exception_helpers.cc
index 8e597fd3dd..8e597fd3dd 100644
--- a/runtime/dex/dex_file_exception_helpers.cc
+++ b/libdexfile/dex/dex_file_exception_helpers.cc
diff --git a/runtime/dex/dex_file_exception_helpers.h b/libdexfile/dex/dex_file_exception_helpers.h
index bd6cb7e747..a05fd68e86 100644
--- a/runtime/dex/dex_file_exception_helpers.h
+++ b/libdexfile/dex/dex_file_exception_helpers.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
-#define ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
#include "dex_file.h"
@@ -65,4 +65,4 @@ class CatchHandlerIterator {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_
diff --git a/runtime/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 2c75c5b5d9..2c75c5b5d9 100644
--- a/runtime/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
diff --git a/runtime/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 508397cb00..41d9b1691b 100644
--- a/runtime/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_LOADER_H_
-#define ART_RUNTIME_DEX_DEX_FILE_LOADER_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
#include <cstdint>
#include <memory>
@@ -195,4 +195,4 @@ class DexFileLoader {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_LOADER_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
diff --git a/runtime/dex/dex_file_test.cc b/libdexfile/dex/dex_file_loader_test.cc
index 2bb86672dc..ab5c3f9a26 100644
--- a/runtime/dex/dex_file_test.cc
+++ b/libdexfile/dex/dex_file_loader_test.cc
@@ -16,33 +16,20 @@
#include "dex_file.h"
-#include <sys/mman.h>
-
#include <memory>
-#include "art_dex_file_loader.h"
-#include "base/stl_util.h"
-#include "base/unix_file/fd_file.h"
#include "base64_test_util.h"
#include "code_item_accessors-inl.h"
-#include "common_runtime_test.h"
#include "descriptors_names.h"
#include "dex_file-inl.h"
#include "dex_file_loader.h"
-#include "mem_map.h"
-#include "os.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
+#include "gtest/gtest.h"
namespace art {
-class DexFileTest : public CommonRuntimeTest {};
+class DexFileLoaderTest : public testing::Test {};
-TEST_F(DexFileTest, Open) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
- ASSERT_TRUE(dex.get() != nullptr);
-}
+static constexpr char kLocationString[] = "/a/dex/file/location";
static inline std::vector<uint8_t> DecodeBase64Vec(const char* src) {
std::vector<uint8_t> res;
@@ -212,52 +199,41 @@ static const char kRawDexDebugInfoLocalNullType[] =
"AAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAAuAAAAAYAAAABAAAA0AAAAAEgAAACAAAA"
"8AAAAAIgAAAIAAAAHAEAAAMgAAACAAAAVAEAAAAgAAABAAAAYwEAAAAQAAABAAAAdAEAAA==";
-static void DecodeAndWriteDexFile(const char* base64, const char* location) {
+static void DecodeDexFile(const char* base64, std::vector<uint8_t>* dex_bytes) {
// decode base64
CHECK(base64 != nullptr);
- std::vector<uint8_t> dex_bytes = DecodeBase64Vec(base64);
- CHECK_NE(dex_bytes.size(), 0u);
-
- // write to provided file
- std::unique_ptr<File> file(OS::CreateEmptyFile(location));
- CHECK(file.get() != nullptr);
- if (!file->WriteFully(dex_bytes.data(), dex_bytes.size())) {
- PLOG(FATAL) << "Failed to write base64 as dex file";
- }
- if (file->FlushCloseOrErase() != 0) {
- PLOG(FATAL) << "Could not flush and close test file.";
- }
+ *dex_bytes = DecodeBase64Vec(base64);
+ CHECK_NE(dex_bytes->size(), 0u);
}
static bool OpenDexFilesBase64(const char* base64,
const char* location,
+ std::vector<uint8_t>* dex_bytes,
std::vector<std::unique_ptr<const DexFile>>* dex_files,
std::string* error_msg) {
- DecodeAndWriteDexFile(base64, location);
+ DecodeDexFile(base64, dex_bytes);
// read dex file(s)
- ScopedObjectAccess soa(Thread::Current());
static constexpr bool kVerifyChecksum = true;
std::vector<std::unique_ptr<const DexFile>> tmp;
- const ArtDexFileLoader dex_file_loader;
- bool success = dex_file_loader.Open(
- location, location, /* verify */ true, kVerifyChecksum, error_msg, &tmp);
- if (success) {
- for (std::unique_ptr<const DexFile>& dex_file : tmp) {
- EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
- EXPECT_TRUE(dex_file->IsReadOnly());
- }
- *dex_files = std::move(tmp);
- }
+ const DexFileLoader dex_file_loader;
+ bool success = dex_file_loader.OpenAll(dex_bytes->data(),
+ dex_bytes->size(),
+ location,
+ /* verify */ true,
+ kVerifyChecksum,
+ error_msg,
+ dex_files);
return success;
}
static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
- const char* location) {
+ const char* location,
+ std::vector<uint8_t>* dex_bytes) {
// read dex files.
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- bool success = OpenDexFilesBase64(base64, location, &dex_files, &error_msg);
+ bool success = OpenDexFilesBase64(base64, location, dex_bytes, &dex_files, &error_msg);
CHECK(success) << error_msg;
EXPECT_EQ(1U, dex_files.size());
return std::move(dex_files[0]);
@@ -266,24 +242,17 @@ static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
static std::unique_ptr<const DexFile> OpenDexFileInMemoryBase64(const char* base64,
const char* location,
uint32_t location_checksum,
- bool expect_success) {
- CHECK(base64 != nullptr);
- std::vector<uint8_t> dex_bytes = DecodeBase64Vec(base64);
- CHECK_NE(dex_bytes.size(), 0u);
+ bool expect_success,
+ std::vector<uint8_t>* dex_bytes) {
+ DecodeDexFile(base64, dex_bytes);
std::string error_message;
- std::unique_ptr<MemMap> region(MemMap::MapAnonymous("test-region",
- nullptr,
- dex_bytes.size(),
- PROT_READ | PROT_WRITE,
- /* low_4gb */ false,
- /* reuse */ false,
- &error_message));
- memcpy(region->Begin(), dex_bytes.data(), dex_bytes.size());
- const ArtDexFileLoader dex_file_loader;
- std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(location,
+ const DexFileLoader dex_file_loader;
+ std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(dex_bytes->data(),
+ dex_bytes->size(),
+ location,
location_checksum,
- std::move(region),
+ /* oat_dex_file */ nullptr,
/* verify */ true,
/* verify_checksum */ true,
&error_message));
@@ -332,323 +301,96 @@ static void ValidateDexFileHeader(std::unique_ptr<const DexFile> dex_file) {
EXPECT_EQ(header.checksum_, dex_file->GetLocationChecksum());
}
-TEST_F(DexFileTest, Header) {
- ScratchFile tmp;
- std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
+TEST_F(DexFileLoaderTest, Header) {
+ std::vector<uint8_t> dex_bytes;
+ std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, kLocationString, &dex_bytes));
ValidateDexFileHeader(std::move(raw));
}
-TEST_F(DexFileTest, HeaderInMemory) {
- ScratchFile tmp;
+TEST_F(DexFileLoaderTest, HeaderInMemory) {
+ std::vector<uint8_t> dex_bytes;
std::unique_ptr<const DexFile> raw =
- OpenDexFileInMemoryBase64(kRawDex, tmp.GetFilename().c_str(), 0x00d87910U, true);
+ OpenDexFileInMemoryBase64(kRawDex, kLocationString, 0x00d87910U, true, &dex_bytes);
ValidateDexFileHeader(std::move(raw));
}
-TEST_F(DexFileTest, Version38Accepted) {
- ScratchFile tmp;
- std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex38, tmp.GetFilename().c_str()));
+TEST_F(DexFileLoaderTest, Version38Accepted) {
+ std::vector<uint8_t> dex_bytes;
+ std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex38, kLocationString, &dex_bytes));
ASSERT_TRUE(raw.get() != nullptr);
const DexFile::Header& header = raw->GetHeader();
EXPECT_EQ(38u, header.GetVersion());
}
-TEST_F(DexFileTest, Version39Accepted) {
- ScratchFile tmp;
- std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex39, tmp.GetFilename().c_str()));
+TEST_F(DexFileLoaderTest, Version39Accepted) {
+ std::vector<uint8_t> dex_bytes;
+ std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex39, kLocationString, &dex_bytes));
ASSERT_TRUE(raw.get() != nullptr);
const DexFile::Header& header = raw->GetHeader();
EXPECT_EQ(39u, header.GetVersion());
}
-TEST_F(DexFileTest, Version40Rejected) {
- ScratchFile tmp;
- const char* location = tmp.GetFilename().c_str();
- DecodeAndWriteDexFile(kRawDex40, location);
+TEST_F(DexFileLoaderTest, Version40Rejected) {
+ std::vector<uint8_t> dex_bytes;
+ DecodeDexFile(kRawDex40, &dex_bytes);
- ScopedObjectAccess soa(Thread::Current());
static constexpr bool kVerifyChecksum = true;
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- const ArtDexFileLoader dex_file_loader;
- ASSERT_FALSE(dex_file_loader.Open(
- location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
+ const DexFileLoader dex_file_loader;
+ ASSERT_FALSE(dex_file_loader.OpenAll(dex_bytes.data(),
+ dex_bytes.size(),
+ kLocationString,
+ /* verify */ true,
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files));
}
-TEST_F(DexFileTest, Version41Rejected) {
- ScratchFile tmp;
- const char* location = tmp.GetFilename().c_str();
- DecodeAndWriteDexFile(kRawDex41, location);
+TEST_F(DexFileLoaderTest, Version41Rejected) {
+ std::vector<uint8_t> dex_bytes;
+ DecodeDexFile(kRawDex41, &dex_bytes);
- ScopedObjectAccess soa(Thread::Current());
static constexpr bool kVerifyChecksum = true;
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- const ArtDexFileLoader dex_file_loader;
- ASSERT_FALSE(dex_file_loader.Open(
- location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
+ const DexFileLoader dex_file_loader;
+ ASSERT_FALSE(dex_file_loader.OpenAll(dex_bytes.data(),
+ dex_bytes.size(),
+ kLocationString,
+ /* verify */ true,
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files));
}
-TEST_F(DexFileTest, ZeroLengthDexRejected) {
- ScratchFile tmp;
- const char* location = tmp.GetFilename().c_str();
- DecodeAndWriteDexFile(kRawDexZeroLength, location);
+TEST_F(DexFileLoaderTest, ZeroLengthDexRejected) {
+ std::vector<uint8_t> dex_bytes;
+ DecodeDexFile(kRawDexZeroLength, &dex_bytes);
- ScopedObjectAccess soa(Thread::Current());
static constexpr bool kVerifyChecksum = true;
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- const ArtDexFileLoader dex_file_loader;
- ASSERT_FALSE(dex_file_loader.Open(
- location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files));
-}
-
-TEST_F(DexFileTest, GetLocationChecksum) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
- EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
-}
-
-TEST_F(DexFileTest, GetChecksum) {
- std::vector<uint32_t> checksums;
- ScopedObjectAccess soa(Thread::Current());
- std::string error_msg;
- const ArtDexFileLoader dex_file_loader;
- EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
- &checksums,
- &error_msg))
- << error_msg;
- ASSERT_EQ(1U, checksums.size());
- EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
-}
-
-TEST_F(DexFileTest, GetMultiDexChecksums) {
- std::string error_msg;
- std::vector<uint32_t> checksums;
- std::string multidex_file = GetTestDexFileName("MultiDex");
- const ArtDexFileLoader dex_file_loader;
- EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(),
- &checksums,
- &error_msg)) << error_msg;
-
- std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
- ASSERT_EQ(2U, dexes.size());
- ASSERT_EQ(2U, checksums.size());
-
- EXPECT_EQ(dexes[0]->GetLocation(), DexFileLoader::GetMultiDexLocation(0, multidex_file.c_str()));
- EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
-
- EXPECT_EQ(dexes[1]->GetLocation(), DexFileLoader::GetMultiDexLocation(1, multidex_file.c_str()));
- EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
-}
-
-TEST_F(DexFileTest, ClassDefs) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
- ASSERT_TRUE(raw.get() != nullptr);
- EXPECT_EQ(3U, raw->NumClassDefs());
-
- const DexFile::ClassDef& c0 = raw->GetClassDef(0);
- EXPECT_STREQ("LNested$1;", raw->GetClassDescriptor(c0));
-
- const DexFile::ClassDef& c1 = raw->GetClassDef(1);
- EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c1));
-
- const DexFile::ClassDef& c2 = raw->GetClassDef(2);
- EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c2));
-}
-
-TEST_F(DexFileTest, GetMethodSignature) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
- ASSERT_TRUE(raw.get() != nullptr);
- EXPECT_EQ(1U, raw->NumClassDefs());
-
- const DexFile::ClassDef& class_def = raw->GetClassDef(0);
- ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
-
- const uint8_t* class_data = raw->GetClassData(class_def);
- ASSERT_TRUE(class_data != nullptr);
- ClassDataItemIterator it(*raw, class_data);
-
- EXPECT_EQ(1u, it.NumDirectMethods());
-
- // Check the signature for the static initializer.
- {
- ASSERT_EQ(1U, it.NumDirectMethods());
- const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
- const char* name = raw->StringDataByIdx(method_id.name_idx_);
- ASSERT_STREQ("<init>", name);
- std::string signature(raw->GetMethodSignature(method_id).ToString());
- ASSERT_EQ("()V", signature);
- }
-
- // Check all virtual methods.
- struct Result {
- const char* name;
- const char* signature;
- const char* pretty_method;
- };
- static const Result results[] = {
- {
- "m1",
- "(IDJLjava/lang/Object;)Ljava/lang/Float;",
- "java.lang.Float GetMethodSignature.m1(int, double, long, java.lang.Object)"
- },
- {
- "m2",
- "(ZSC)LGetMethodSignature;",
- "GetMethodSignature GetMethodSignature.m2(boolean, short, char)"
- },
- {
- "m3",
- "()V",
- "void GetMethodSignature.m3()"
- },
- {
- "m4",
- "(I)V",
- "void GetMethodSignature.m4(int)"
- },
- {
- "m5",
- "(II)V",
- "void GetMethodSignature.m5(int, int)"
- },
- {
- "m6",
- "(II[[I)V",
- "void GetMethodSignature.m6(int, int, int[][])"
- },
- {
- "m7",
- "(II[[ILjava/lang/Object;)V",
- "void GetMethodSignature.m7(int, int, int[][], java.lang.Object)"
- },
- {
- "m8",
- "(II[[ILjava/lang/Object;[[Ljava/lang/Object;)V",
- "void GetMethodSignature.m8(int, int, int[][], java.lang.Object, java.lang.Object[][])"
- },
- {
- "m9",
- "()I",
- "int GetMethodSignature.m9()"
- },
- {
- "mA",
- "()[[I",
- "int[][] GetMethodSignature.mA()"
- },
- {
- "mB",
- "()[[Ljava/lang/Object;",
- "java.lang.Object[][] GetMethodSignature.mB()"
- },
- };
- ASSERT_EQ(arraysize(results), it.NumVirtualMethods());
- for (const Result& r : results) {
- it.Next();
- const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
-
- const char* name = raw->StringDataByIdx(method_id.name_idx_);
- ASSERT_STREQ(r.name, name);
-
- std::string signature(raw->GetMethodSignature(method_id).ToString());
- ASSERT_EQ(r.signature, signature);
-
- std::string plain_method = std::string("GetMethodSignature.") + r.name;
- ASSERT_EQ(plain_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ false));
- ASSERT_EQ(r.pretty_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ true));
- }
-}
-
-TEST_F(DexFileTest, FindStringId) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
- ASSERT_TRUE(raw.get() != nullptr);
- EXPECT_EQ(1U, raw->NumClassDefs());
-
- const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
- "D", "I", "J", nullptr };
- for (size_t i = 0; strings[i] != nullptr; i++) {
- const char* str = strings[i];
- const DexFile::StringId* str_id = raw->FindStringId(str);
- const char* dex_str = raw->GetStringData(*str_id);
- EXPECT_STREQ(dex_str, str);
- }
-}
-
-TEST_F(DexFileTest, FindTypeId) {
- for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
- const char* type_str = java_lang_dex_file_->StringByTypeIdx(dex::TypeIndex(i));
- const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
- ASSERT_TRUE(type_str_id != nullptr);
- dex::StringIndex type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
- const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
- ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
- ASSERT_TRUE(type_id != nullptr);
- EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id).index_, i);
- }
-}
-
-TEST_F(DexFileTest, FindProtoId) {
- for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
- const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
- const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
- std::vector<dex::TypeIndex> to_find_types;
- if (to_find_tl != nullptr) {
- for (size_t j = 0; j < to_find_tl->Size(); j++) {
- to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
- }
- }
- const DexFile::ProtoId* found =
- java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
- ASSERT_TRUE(found != nullptr);
- EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
- }
-}
-
-TEST_F(DexFileTest, FindMethodId) {
- for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
- const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
- const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
- const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
- const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
- const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
- ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
- << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
- << java_lang_dex_file_->GetStringData(name)
- << java_lang_dex_file_->GetMethodSignature(to_find);
- EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
- }
-}
-
-TEST_F(DexFileTest, FindFieldId) {
- for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
- const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
- const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
- const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
- const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
- const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
- ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
- << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
- << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
- << java_lang_dex_file_->GetStringData(name);
- EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
- }
+ const DexFileLoader dex_file_loader;
+ ASSERT_FALSE(dex_file_loader.OpenAll(dex_bytes.data(),
+ dex_bytes.size(),
+ kLocationString,
+ /* verify */ true,
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files));
}
-TEST_F(DexFileTest, GetMultiDexClassesDexName) {
+TEST_F(DexFileLoaderTest, GetMultiDexClassesDexName) {
ASSERT_EQ("classes.dex", DexFileLoader::GetMultiDexClassesDexName(0));
ASSERT_EQ("classes2.dex", DexFileLoader::GetMultiDexClassesDexName(1));
ASSERT_EQ("classes3.dex", DexFileLoader::GetMultiDexClassesDexName(2));
ASSERT_EQ("classes100.dex", DexFileLoader::GetMultiDexClassesDexName(99));
}
-TEST_F(DexFileTest, GetMultiDexLocation) {
+TEST_F(DexFileLoaderTest, GetMultiDexLocation) {
std::string dex_location_str = "/system/app/framework.jar";
const char* dex_location = dex_location_str.c_str();
ASSERT_EQ("/system/app/framework.jar", DexFileLoader::GetMultiDexLocation(0, dex_location));
@@ -658,28 +400,6 @@ TEST_F(DexFileTest, GetMultiDexLocation) {
DexFileLoader::GetMultiDexLocation(100, dex_location));
}
-TEST_F(DexFileTest, GetDexCanonicalLocation) {
- ScratchFile file;
- UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
- std::string dex_location(dex_location_real.get());
-
- ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location.c_str()));
- std::string multidex_location = DexFileLoader::GetMultiDexLocation(1, dex_location.c_str());
- ASSERT_EQ(multidex_location, DexFileLoader::GetDexCanonicalLocation(multidex_location.c_str()));
-
- std::string dex_location_sym = dex_location + "symlink";
- ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
-
- ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location_sym.c_str()));
-
- std::string multidex_location_sym = DexFileLoader::GetMultiDexLocation(
- 1, dex_location_sym.c_str());
- ASSERT_EQ(multidex_location,
- DexFileLoader::GetDexCanonicalLocation(multidex_location_sym.c_str()));
-
- ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
-}
-
TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
EXPECT_EQ("/foo/bar/baz.jar", DexFileLoader::GetBaseLocation("/foo/bar/baz.jar"));
EXPECT_EQ("/foo/bar/baz.jar", DexFileLoader::GetBaseLocation("/foo/bar/baz.jar!classes2.dex"));
@@ -689,43 +409,56 @@ TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
EXPECT_EQ("!classes8.dex", DexFileLoader::GetMultiDexSuffix("/foo/bar/baz.jar!classes8.dex"));
}
-TEST_F(DexFileTest, ZipOpenClassesPresent) {
- ScratchFile tmp;
+TEST_F(DexFileLoaderTest, ZipOpenClassesPresent) {
+ std::vector<uint8_t> dex_bytes;
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::string error_msg;
- ASSERT_TRUE(OpenDexFilesBase64(kRawZipClassesDexPresent, tmp.GetFilename().c_str(), &dex_files,
+ ASSERT_TRUE(OpenDexFilesBase64(kRawZipClassesDexPresent,
+ kLocationString,
+ &dex_bytes,
+ &dex_files,
&error_msg));
EXPECT_EQ(dex_files.size(), 1u);
}
-TEST_F(DexFileTest, ZipOpenClassesAbsent) {
- ScratchFile tmp;
+TEST_F(DexFileLoaderTest, ZipOpenClassesAbsent) {
+ std::vector<uint8_t> dex_bytes;
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::string error_msg;
- ASSERT_FALSE(OpenDexFilesBase64(kRawZipClassesDexAbsent, tmp.GetFilename().c_str(), &dex_files,
+ ASSERT_FALSE(OpenDexFilesBase64(kRawZipClassesDexAbsent,
+ kLocationString,
+ &dex_bytes,
+ &dex_files,
&error_msg));
EXPECT_EQ(dex_files.size(), 0u);
}
-TEST_F(DexFileTest, ZipOpenThreeDexFiles) {
- ScratchFile tmp;
+TEST_F(DexFileLoaderTest, ZipOpenThreeDexFiles) {
+ std::vector<uint8_t> dex_bytes;
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::string error_msg;
- ASSERT_TRUE(OpenDexFilesBase64(kRawZipThreeDexFiles, tmp.GetFilename().c_str(), &dex_files,
+ ASSERT_TRUE(OpenDexFilesBase64(kRawZipThreeDexFiles,
+ kLocationString,
+ &dex_bytes,
+ &dex_files,
&error_msg));
EXPECT_EQ(dex_files.size(), 3u);
}
-TEST_F(DexFileTest, OpenDexBadMapOffset) {
- ScratchFile tmp;
+TEST_F(DexFileLoaderTest, OpenDexBadMapOffset) {
+ std::vector<uint8_t> dex_bytes;
std::unique_ptr<const DexFile> raw =
- OpenDexFileInMemoryBase64(kRawDexBadMapOffset, tmp.GetFilename().c_str(), 0xb3642819U, false);
+ OpenDexFileInMemoryBase64(kRawDexBadMapOffset,
+ kLocationString,
+ 0xb3642819U,
+ false,
+ &dex_bytes);
EXPECT_EQ(raw, nullptr);
}
-TEST_F(DexFileTest, GetStringWithNoIndex) {
- ScratchFile tmp;
- std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
+TEST_F(DexFileLoaderTest, GetStringWithNoIndex) {
+ std::vector<uint8_t> dex_bytes;
+ std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, kLocationString, &dex_bytes));
dex::TypeIndex idx;
EXPECT_EQ(raw->StringByTypeIdx(idx), nullptr);
}
@@ -734,10 +467,13 @@ static void Callback(void* context ATTRIBUTE_UNUSED,
const DexFile::LocalInfo& entry ATTRIBUTE_UNUSED) {
}
-TEST_F(DexFileTest, OpenDexDebugInfoLocalNullType) {
- ScratchFile tmp;
- std::unique_ptr<const DexFile> raw = OpenDexFileInMemoryBase64(
- kRawDexDebugInfoLocalNullType, tmp.GetFilename().c_str(), 0xf25f2b38U, true);
+TEST_F(DexFileLoaderTest, OpenDexDebugInfoLocalNullType) {
+ std::vector<uint8_t> dex_bytes;
+ std::unique_ptr<const DexFile> raw = OpenDexFileInMemoryBase64(kRawDexDebugInfoLocalNullType,
+ kLocationString,
+ 0xf25f2b38U,
+ true,
+ &dex_bytes);
const DexFile::ClassDef& class_def = raw->GetClassDef(0);
constexpr uint32_t kMethodIdx = 1;
const DexFile::CodeItem* code_item = raw->GetCodeItem(raw->FindCodeItemOffset(class_def,
diff --git a/runtime/dex/dex_file_reference.h b/libdexfile/dex/dex_file_reference.h
index 6f882900c6..3ac778121a 100644
--- a/runtime/dex/dex_file_reference.h
+++ b/libdexfile/dex/dex_file_reference.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_
-#define ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
#include <cstdint>
@@ -49,4 +49,4 @@ inline bool operator==(const DexFileReference& a, const DexFileReference& b) {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
diff --git a/runtime/dex/dex_file_tracking_registrar.cc b/libdexfile/dex/dex_file_tracking_registrar.cc
index 78ea9c16cb..78ea9c16cb 100644
--- a/runtime/dex/dex_file_tracking_registrar.cc
+++ b/libdexfile/dex/dex_file_tracking_registrar.cc
diff --git a/runtime/dex/dex_file_tracking_registrar.h b/libdexfile/dex/dex_file_tracking_registrar.h
index 71b8ed7bde..8b7716e729 100644
--- a/runtime/dex/dex_file_tracking_registrar.h
+++ b/libdexfile/dex/dex_file_tracking_registrar.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
-#define ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
#include <deque>
#include <tuple>
@@ -78,4 +78,4 @@ void RegisterDexFile(const DexFile* dex_file);
} // namespace dex
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_
diff --git a/runtime/dex/dex_file_types.h b/libdexfile/dex/dex_file_types.h
index 2c508f9c99..2bb70ff261 100644
--- a/runtime/dex/dex_file_types.h
+++ b/libdexfile/dex/dex_file_types.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_TYPES_H_
-#define ART_RUNTIME_DEX_DEX_FILE_TYPES_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
#include <limits>
#include <ostream>
@@ -114,4 +114,4 @@ template<> struct hash<art::dex::TypeIndex> {
} // namespace std
-#endif // ART_RUNTIME_DEX_DEX_FILE_TYPES_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
diff --git a/runtime/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index 62667052ad..62667052ad 100644
--- a/runtime/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
diff --git a/runtime/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h
index 6cb5d4c629..c4982c24c9 100644
--- a/runtime/dex/dex_file_verifier.h
+++ b/libdexfile/dex/dex_file_verifier.h
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_
-#define ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_
+#define ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_
#include <unordered_set>
-#include "base/allocator.h"
#include "base/hash_map.h"
#include "dex_file.h"
#include "dex_file_types.h"
@@ -254,4 +253,4 @@ class DexFileVerifier {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_
diff --git a/runtime/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc
index 1cd4b2c07b..1cd4b2c07b 100644
--- a/runtime/dex/dex_file_verifier_test.cc
+++ b/libdexfile/dex/dex_file_verifier_test.cc
diff --git a/runtime/dex/dex_instruction-inl.h b/libdexfile/dex/dex_instruction-inl.h
index a6b8414e62..6bef18c85f 100644
--- a/runtime/dex/dex_instruction-inl.h
+++ b/libdexfile/dex/dex_instruction-inl.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_
-#define ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_
+#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_
#include "dex_instruction.h"
@@ -555,4 +555,4 @@ inline void Instruction::GetVarArgs(uint32_t arg[kMaxVarArgRegs], uint16_t inst_
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_
diff --git a/runtime/dex/dex_instruction.cc b/libdexfile/dex/dex_instruction.cc
index b84791ffae..886218129e 100644
--- a/runtime/dex/dex_instruction.cc
+++ b/libdexfile/dex/dex_instruction.cc
@@ -558,4 +558,11 @@ uint32_t VarArgsInstructionOperands::GetOperand(size_t operand_index) const {
return operands_[operand_index];
}
+uint32_t NoReceiverInstructionOperands::GetOperand(size_t operand_index) const {
+ DCHECK_LT(GetNumberOfOperands(), inner_->GetNumberOfOperands());
+ // The receiver is the first operand and since we're skipping it, we need to
+ // add 1 to the operand_index.
+ return inner_->GetOperand(operand_index + 1);
+}
+
} // namespace art
diff --git a/runtime/dex/dex_instruction.h b/libdexfile/dex/dex_instruction.h
index 8b1a5ce670..c9533656d3 100644
--- a/runtime/dex/dex_instruction.h
+++ b/libdexfile/dex/dex_instruction.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_H_
-#define ART_RUNTIME_DEX_DEX_INSTRUCTION_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
+#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
#include <android-base/logging.h>
@@ -701,7 +701,7 @@ class InstructionOperands {
size_t GetNumberOfOperands() const { return num_operands_; }
private:
- size_t num_operands_;
+ const size_t num_operands_;
DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands);
};
@@ -737,6 +737,21 @@ class VarArgsInstructionOperands FINAL : public InstructionOperands {
DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands);
};
+// Class for accessing operands without the receiver by wrapping an
+// existing InstructionOperands instance.
+class NoReceiverInstructionOperands FINAL : public InstructionOperands {
+ public:
+ explicit NoReceiverInstructionOperands(InstructionOperands* inner)
+ : InstructionOperands(inner->GetNumberOfOperands() - 1), inner_(inner) {}
+ ~NoReceiverInstructionOperands() {}
+ uint32_t GetOperand(size_t operand_index) const OVERRIDE;
+
+ private:
+ const InstructionOperands* const inner_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NoReceiverInstructionOperands);
+};
+
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
diff --git a/runtime/dex/dex_instruction_iterator.h b/libdexfile/dex/dex_instruction_iterator.h
index c1b3118f85..db3ff95e02 100644
--- a/runtime/dex/dex_instruction_iterator.h
+++ b/libdexfile/dex/dex_instruction_iterator.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_
-#define ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_
+#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_
#include <iterator>
@@ -234,4 +234,4 @@ class SafeDexInstructionIterator : public DexInstructionIteratorBase {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_
diff --git a/runtime/dex/dex_instruction_list.h b/libdexfile/dex/dex_instruction_list.h
index aa63fadb66..9f0aba421a 100644
--- a/runtime/dex/dex_instruction_list.h
+++ b/libdexfile/dex/dex_instruction_list.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_
-#define ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_
+#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_
// V(opcode, instruction_code, name, format, index, flags, extended_flags, verifier_flags);
#define DEX_INSTRUCTION_LIST(V) \
@@ -304,5 +304,5 @@
V(k4rcc) \
V(k51l)
-#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_
-#undef ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_ // the guard in this file is just for cpplint
+#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_
+#undef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_ // the guard in this file is just for cpplint
diff --git a/runtime/dex/dex_instruction_test.cc b/libdexfile/dex/dex_instruction_test.cc
index c944085b9e..c944085b9e 100644
--- a/runtime/dex/dex_instruction_test.cc
+++ b/libdexfile/dex/dex_instruction_test.cc
diff --git a/runtime/dex/dex_instruction_utils.h b/libdexfile/dex/dex_instruction_utils.h
index 27501927e7..e7614ada31 100644
--- a/runtime/dex/dex_instruction_utils.h
+++ b/libdexfile/dex/dex_instruction_utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_
-#define ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_
+#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_
#include "dex_instruction.h"
@@ -216,4 +216,4 @@ constexpr DexMemAccessType AGetOrAPutMemAccessType(Instruction::Code code) {
} // namespace art
-#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_
diff --git a/runtime/dex/invoke_type.h b/libdexfile/dex/invoke_type.h
index 726d269a3e..9b3af673a8 100644
--- a/runtime/dex/invoke_type.h
+++ b/libdexfile/dex/invoke_type.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_INVOKE_TYPE_H_
-#define ART_RUNTIME_DEX_INVOKE_TYPE_H_
+#ifndef ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_
+#define ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_
#include <iosfwd>
@@ -35,4 +35,4 @@ std::ostream& operator<<(std::ostream& os, const InvokeType& rhs);
} // namespace art
-#endif // ART_RUNTIME_DEX_INVOKE_TYPE_H_
+#endif // ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_
diff --git a/runtime/dex/modifiers.cc b/libdexfile/dex/modifiers.cc
index 30daefb172..30daefb172 100644
--- a/runtime/dex/modifiers.cc
+++ b/libdexfile/dex/modifiers.cc
diff --git a/runtime/dex/modifiers.h b/libdexfile/dex/modifiers.h
index 2998f602d4..2425a588df 100644
--- a/runtime/dex/modifiers.h
+++ b/libdexfile/dex/modifiers.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_MODIFIERS_H_
-#define ART_RUNTIME_DEX_MODIFIERS_H_
+#ifndef ART_LIBDEXFILE_DEX_MODIFIERS_H_
+#define ART_LIBDEXFILE_DEX_MODIFIERS_H_
#include <stdint.h>
@@ -144,5 +144,5 @@ std::string PrettyJavaAccessFlags(uint32_t access_flags);
} // namespace art
-#endif // ART_RUNTIME_DEX_MODIFIERS_H_
+#endif // ART_LIBDEXFILE_DEX_MODIFIERS_H_
diff --git a/runtime/dex/standard_dex_file.cc b/libdexfile/dex/standard_dex_file.cc
index f7317eb997..f7317eb997 100644
--- a/runtime/dex/standard_dex_file.cc
+++ b/libdexfile/dex/standard_dex_file.cc
diff --git a/runtime/dex/standard_dex_file.h b/libdexfile/dex/standard_dex_file.h
index e0e9f2f11c..9b13caa2be 100644
--- a/runtime/dex/standard_dex_file.h
+++ b/libdexfile/dex/standard_dex_file.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_
-#define ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_
+#ifndef ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_
+#define ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_
#include <iosfwd>
@@ -115,4 +115,4 @@ class StandardDexFile : public DexFile {
} // namespace art
-#endif // ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_
+#endif // ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_
diff --git a/runtime/dex/utf-inl.h b/libdexfile/dex/utf-inl.h
index 4f626a8580..5355766aae 100644
--- a/runtime/dex/utf-inl.h
+++ b/libdexfile/dex/utf-inl.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_UTF_INL_H_
-#define ART_RUNTIME_DEX_UTF_INL_H_
+#ifndef ART_LIBDEXFILE_DEX_UTF_INL_H_
+#define ART_LIBDEXFILE_DEX_UTF_INL_H_
#include "utf.h"
@@ -96,4 +96,4 @@ inline int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* u
} // namespace art
-#endif // ART_RUNTIME_DEX_UTF_INL_H_
+#endif // ART_LIBDEXFILE_DEX_UTF_INL_H_
diff --git a/runtime/dex/utf.cc b/libdexfile/dex/utf.cc
index 772a610140..772a610140 100644
--- a/runtime/dex/utf.cc
+++ b/libdexfile/dex/utf.cc
diff --git a/runtime/dex/utf.h b/libdexfile/dex/utf.h
index 4adfc4af8c..c86b389175 100644
--- a/runtime/dex/utf.h
+++ b/libdexfile/dex/utf.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_UTF_H_
-#define ART_RUNTIME_DEX_UTF_H_
+#ifndef ART_LIBDEXFILE_DEX_UTF_H_
+#define ART_LIBDEXFILE_DEX_UTF_H_
#include "base/macros.h"
@@ -132,4 +132,4 @@ std::string PrintableString(const char* utf8);
} // namespace art
-#endif // ART_RUNTIME_DEX_UTF_H_
+#endif // ART_LIBDEXFILE_DEX_UTF_H_
diff --git a/runtime/dex/utf_test.cc b/libdexfile/dex/utf_test.cc
index d2f22d16ef..d2f22d16ef 100644
--- a/runtime/dex/utf_test.cc
+++ b/libdexfile/dex/utf_test.cc
diff --git a/libdexfile/generate-operator-out.py b/libdexfile/generate-operator-out.py
new file mode 120000
index 0000000000..cc291d20c1
--- /dev/null
+++ b/libdexfile/generate-operator-out.py
@@ -0,0 +1 @@
+../tools/generate-operator-out.py \ No newline at end of file
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index c93c172eb4..012100d470 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -51,7 +51,7 @@ art_cc_binary {
"libartd",
"libartd-compiler",
"libartd-disassembler",
- "libdexfile",
+ "libdexfiled",
"libbase",
],
}
@@ -76,6 +76,7 @@ art_cc_binary {
],
static_libs: [
"libart",
+ "libdexfile",
"libart-compiler",
"libart-disassembler",
"libvixl-arm",
@@ -106,6 +107,7 @@ art_cc_binary {
],
static_libs: [
"libartd",
+ "libdexfiled",
"libartd-compiler",
"libartd-disassembler",
"libvixld-arm",
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 6c9f569b19..82bb88a5d5 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -2394,9 +2394,11 @@ class ImageDumper {
} else if (obj->IsClass()) {
ObjPtr<mirror::Class> klass = obj->AsClass();
- os << "SUBTYPE_CHECK_BITS: ";
- SubtypeCheck<ObjPtr<mirror::Class>>::Dump(klass, os);
- os << "\n";
+ if (kBitstringSubtypeCheckEnabled) {
+ os << "SUBTYPE_CHECK_BITS: ";
+ SubtypeCheck<ObjPtr<mirror::Class>>::Dump(klass, os);
+ os << "\n";
+ }
if (klass->NumStaticFields() != 0) {
os << "STATICS:\n";
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 1500bcae24..1553b78f46 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -58,7 +58,6 @@ cc_defaults {
"libopenjdkjvmti_headers",
],
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -70,6 +69,7 @@ art_cc_library {
"libart",
"libart-compiler",
"libart-dexlayout",
+ "libdexfile",
],
}
@@ -83,5 +83,6 @@ art_cc_library {
"libartd",
"libartd-compiler",
"libartd-dexlayout",
+ "libdexfiled",
],
}
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
index a0c7f40b6f..ef5151990c 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -73,8 +73,10 @@
namespace openjdkjvmti {
-EventHandler gEventHandler;
-DeoptManager gDeoptManager;
+// NB These are heap allocated to avoid the static destructors being run if an agent calls exit(3).
+// These should never be null.
+EventHandler* gEventHandler;
+DeoptManager* gDeoptManager;
#define ENSURE_NON_NULL(n) \
do { \
@@ -776,7 +778,7 @@ class JvmtiFunctions {
ENSURE_HAS_CAP(env, can_retransform_classes);
std::string error_msg;
jvmtiError res = Transformer::RetransformClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
- &gEventHandler,
+ gEventHandler,
art::Runtime::Current(),
art::Thread::Current(),
class_count,
@@ -795,7 +797,7 @@ class JvmtiFunctions {
ENSURE_HAS_CAP(env, can_redefine_classes);
std::string error_msg;
jvmtiError res = Redefiner::RedefineClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
- &gEventHandler,
+ gEventHandler,
art::Runtime::Current(),
art::Thread::Current(),
class_count,
@@ -1061,7 +1063,10 @@ class JvmtiFunctions {
}
ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(env);
- return gEventHandler.SetEvent(art_env, art_thread, GetArtJvmtiEvent(art_env, event_type), mode);
+ return gEventHandler->SetEvent(art_env,
+ art_thread,
+ GetArtJvmtiEvent(art_env, event_type),
+ mode);
}
static jvmtiError GenerateEvents(jvmtiEnv* env,
@@ -1095,7 +1100,7 @@ class JvmtiFunctions {
return ExtensionUtil::SetExtensionEventCallback(env,
extension_event_index,
callback,
- &gEventHandler);
+ gEventHandler);
}
#define FOR_ALL_CAPABILITIES(FUN) \
@@ -1186,9 +1191,9 @@ class JvmtiFunctions {
FOR_ALL_CAPABILITIES(ADD_CAPABILITY);
#undef ADD_CAPABILITY
- gEventHandler.HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
- changed,
- /*added*/true);
+ gEventHandler->HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+ changed,
+ /*added*/true);
return ret;
}
@@ -1210,9 +1215,9 @@ class JvmtiFunctions {
FOR_ALL_CAPABILITIES(DEL_CAPABILITY);
#undef DEL_CAPABILITY
- gEventHandler.HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
- changed,
- /*added*/false);
+ gEventHandler->HandleChangedCapabilities(ArtJvmTiEnv::AsArtJvmTiEnv(env),
+ changed,
+ /*added*/false);
return OK;
}
@@ -1302,7 +1307,7 @@ class JvmtiFunctions {
static jvmtiError DisposeEnvironment(jvmtiEnv* env) {
ENSURE_VALID_ENV(env);
ArtJvmTiEnv* tienv = ArtJvmTiEnv::AsArtJvmTiEnv(env);
- gEventHandler.RemoveArtJvmTiEnv(tienv);
+ gEventHandler->RemoveArtJvmTiEnv(tienv);
art::Runtime::Current()->RemoveSystemWeakHolder(tienv->object_tag_table.get());
ThreadUtil::RemoveEnvironment(tienv);
delete tienv;
@@ -1490,10 +1495,10 @@ ArtJvmTiEnv::ArtJvmTiEnv(art::JavaVMExt* runtime, EventHandler* event_handler, j
// Creates a jvmtiEnv and returns it with the art::ti::Env that is associated with it. new_art_ti
// is a pointer to the uninitialized memory for an art::ti::Env.
static void CreateArtJvmTiEnv(art::JavaVMExt* vm, jint version, /*out*/void** new_jvmtiEnv) {
- struct ArtJvmTiEnv* env = new ArtJvmTiEnv(vm, &gEventHandler, version);
+ struct ArtJvmTiEnv* env = new ArtJvmTiEnv(vm, gEventHandler, version);
*new_jvmtiEnv = env;
- gEventHandler.RegisterArtJvmTiEnv(env);
+ gEventHandler->RegisterArtJvmTiEnv(env);
art::Runtime::Current()->AddSystemWeakHolder(
ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get());
@@ -1522,17 +1527,20 @@ static jint GetEnvHandler(art::JavaVMExt* vm, /*out*/void** env, jint version) {
extern "C" bool ArtPlugin_Initialize() {
art::Runtime* runtime = art::Runtime::Current();
- gDeoptManager.Setup();
+ gDeoptManager = new DeoptManager;
+ gEventHandler = new EventHandler;
+
+ gDeoptManager->Setup();
if (runtime->IsStarted()) {
PhaseUtil::SetToLive();
} else {
PhaseUtil::SetToOnLoad();
}
- PhaseUtil::Register(&gEventHandler);
- ThreadUtil::Register(&gEventHandler);
- ClassUtil::Register(&gEventHandler);
- DumpUtil::Register(&gEventHandler);
- MethodUtil::Register(&gEventHandler);
+ PhaseUtil::Register(gEventHandler);
+ ThreadUtil::Register(gEventHandler);
+ ClassUtil::Register(gEventHandler);
+ DumpUtil::Register(gEventHandler);
+ MethodUtil::Register(gEventHandler);
SearchUtil::Register();
HeapUtil::Register();
Transformer::Setup();
@@ -1540,7 +1548,7 @@ extern "C" bool ArtPlugin_Initialize() {
{
// Make sure we can deopt anything we need to.
art::ScopedObjectAccess soa(art::Thread::Current());
- gDeoptManager.FinishSetup();
+ gDeoptManager->FinishSetup();
}
runtime->GetJavaVM()->AddEnvironmentHook(GetEnvHandler);
@@ -1549,8 +1557,8 @@ extern "C" bool ArtPlugin_Initialize() {
}
extern "C" bool ArtPlugin_Deinitialize() {
- gEventHandler.Shutdown();
- gDeoptManager.Shutdown();
+ gEventHandler->Shutdown();
+ gDeoptManager->Shutdown();
PhaseUtil::Unregister();
ThreadUtil::Unregister();
ClassUtil::Unregister();
@@ -1559,6 +1567,11 @@ extern "C" bool ArtPlugin_Deinitialize() {
SearchUtil::Unregister();
HeapUtil::Unregister();
+ // TODO It would be good to delete the gEventHandler and gDeoptManager here but we cannot since
+ // daemon threads might be suspended and we want to make sure that even if they wake up briefly
+ // they won't hit deallocated memory. By this point none of the functions will do anything since
+ // they have already shutdown.
+
return true;
}
diff --git a/openjdkjvmti/deopt_manager.cc b/openjdkjvmti/deopt_manager.cc
index 9e11a25e58..6d84ffa53f 100644
--- a/openjdkjvmti/deopt_manager.cc
+++ b/openjdkjvmti/deopt_manager.cc
@@ -277,7 +277,7 @@ void DeoptManager::AddDeoptimizeAllMethodsLocked(art::Thread* self) {
}
void DeoptManager::RemoveDeoptimizeAllMethodsLocked(art::Thread* self) {
- DCHECK_GT(global_deopt_count_, 0u) << "Request to remove non-existant global deoptimization!";
+ DCHECK_GT(global_deopt_count_, 0u) << "Request to remove non-existent global deoptimization!";
global_deopt_count_--;
if (global_deopt_count_ == 0) {
PerformGlobalUndeoptimization(self);
@@ -343,9 +343,9 @@ void DeoptManager::DeoptimizeThread(art::Thread* target) {
art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(target);
}
-extern DeoptManager gDeoptManager;
+extern DeoptManager* gDeoptManager;
DeoptManager* DeoptManager::Get() {
- return &gDeoptManager;
+ return gDeoptManager;
}
} // namespace openjdkjvmti
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index 62b73c08c0..8b40a7e072 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -1186,8 +1186,9 @@ void EventHandler::Shutdown() {
art::Runtime::Current()->GetInstrumentation()->RemoveListener(method_trace_listener_.get(), ~0);
}
-EventHandler::EventHandler() : envs_lock_("JVMTI Environment List Lock",
- art::LockLevel::kTopLockLevel) {
+EventHandler::EventHandler()
+ : envs_lock_("JVMTI Environment List Lock", art::LockLevel::kTopLockLevel),
+ frame_pop_enabled(false) {
alloc_listener_.reset(new JvmtiAllocationListener(this));
ddm_listener_.reset(new JvmtiDdmChunkListener(this));
gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc
index dc9f69a96a..43b8fe94f4 100644
--- a/openjdkjvmti/transform.cc
+++ b/openjdkjvmti/transform.cc
@@ -124,7 +124,7 @@ class TransformationFaultHandler FINAL : public art::FaultHandler {
return std::find_if(initialized_class_definitions_.begin(),
initialized_class_definitions_.end(),
[&](const auto op) { return op->ContainsAddress(ptr); }) !=
- uninitialized_class_definitions_.end();
+ initialized_class_definitions_.end();
}
}
diff --git a/profman/Android.bp b/profman/Android.bp
index 6592b9dec0..163be2b64f 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -31,7 +31,6 @@ cc_defaults {
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -41,6 +40,7 @@ art_cc_binary {
defaults: ["profman-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -52,6 +52,7 @@ art_cc_binary {
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index 79310ac166..188d0b0a24 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -31,6 +31,8 @@
namespace art {
+using Hotness = ProfileCompilationInfo::MethodHotness;
+
static constexpr size_t kMaxMethodIds = 65535;
class ProfileAssistantTest : public CommonRuntimeTest {
@@ -80,12 +82,17 @@ class ProfileAssistantTest : public CommonRuntimeTest {
ProfileCompilationInfo::OfflineProfileMethodInfo pmi =
GetOfflineProfileMethodInfo(dex_location1, dex_location_checksum1,
dex_location2, dex_location_checksum2);
+ Hotness::Flag flags = Hotness::kFlagPostStartup;
if (reverse_dex_write_order) {
- ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi));
- ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi));
+ ASSERT_TRUE(info->AddMethod(
+ dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi, flags));
+ ASSERT_TRUE(info->AddMethod(
+ dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi, flags));
} else {
- ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi));
- ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi));
+ ASSERT_TRUE(info->AddMethod(
+ dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi, flags));
+ ASSERT_TRUE(info->AddMethod(
+ dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi, flags));
}
}
for (uint16_t i = 0; i < number_of_classes; i++) {
@@ -109,7 +116,6 @@ class ProfileAssistantTest : public CommonRuntimeTest {
const ScratchFile& profile,
ProfileCompilationInfo* info) {
std::string dex_location = "location1" + id;
- using Hotness = ProfileCompilationInfo::MethodHotness;
for (uint32_t idx : hot_methods) {
info->AddMethodIndex(Hotness::kFlagHot, dex_location, checksum, idx, number_of_methods);
}
@@ -1086,10 +1092,10 @@ TEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) {
ASSERT_EQ(1u, classes.size());
ASSERT_TRUE(classes.find(invalid_class_index) != classes.end());
- // Verify that the invalid method is in the profile.
- ASSERT_EQ(2u, hot_methods.size());
+ // Verify that the invalid method did not get in the profile.
+ ASSERT_EQ(1u, hot_methods.size());
uint16_t invalid_method_index = std::numeric_limits<uint16_t>::max() - 1;
- ASSERT_TRUE(hot_methods.find(invalid_method_index) != hot_methods.end());
+ ASSERT_FALSE(hot_methods.find(invalid_method_index) != hot_methods.end());
}
TEST_F(ProfileAssistantTest, DumpOnly) {
diff --git a/profman/profman.cc b/profman/profman.cc
index 387ce8dfae..efb7fcfec6 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -895,6 +895,17 @@ class ProfMan FINAL {
method_str = line.substr(method_sep_index + kMethodSep.size());
}
+ uint32_t flags = 0;
+ if (is_hot) {
+ flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
+ }
+ if (is_startup) {
+ flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup;
+ }
+ if (is_post_startup) {
+ flags |= ProfileCompilationInfo::MethodHotness::kFlagPostStartup;
+ }
+
TypeReference class_ref(/* dex_file */ nullptr, dex::TypeIndex());
if (!FindClass(dex_files, klass, &class_ref)) {
LOG(WARNING) << "Could not find class: " << klass;
@@ -930,7 +941,7 @@ class ProfMan FINAL {
}
}
// TODO: Check return values?
- profile->AddMethods(methods);
+ profile->AddMethods(methods, static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags));
profile->AddClasses(resolved_class_set);
return true;
}
@@ -982,18 +993,12 @@ class ProfMan FINAL {
}
MethodReference ref(class_ref.dex_file, method_index);
if (is_hot) {
- profile->AddMethod(ProfileMethodInfo(ref, inline_caches));
- }
- uint32_t flags = 0;
- using Hotness = ProfileCompilationInfo::MethodHotness;
- if (is_startup) {
- flags |= Hotness::kFlagStartup;
- }
- if (is_post_startup) {
- flags |= Hotness::kFlagPostStartup;
+ profile->AddMethod(ProfileMethodInfo(ref, inline_caches),
+ static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags));
}
if (flags != 0) {
- if (!profile->AddMethodIndex(static_cast<Hotness::Flag>(flags), ref)) {
+ if (!profile->AddMethodIndex(
+ static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags), ref)) {
return false;
}
DCHECK(profile->GetMethodHotness(ref).IsInProfile());
diff --git a/runtime/Android.bp b/runtime/Android.bp
index db9bceaf29..1ac770fd06 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -14,83 +14,6 @@
// limitations under the License.
//
-cc_defaults {
- name: "libdexfile_defaults",
- defaults: ["art_defaults"],
- host_supported: true,
- srcs: [
- "dex/compact_dex_debug_info.cc",
- "dex/compact_dex_file.cc",
- "dex/descriptors_names.cc",
- "dex/dex_file.cc",
- "dex/dex_file_exception_helpers.cc",
- "dex/dex_file_loader.cc",
- "dex/dex_file_tracking_registrar.cc",
- "dex/dex_file_verifier.cc",
- "dex/dex_instruction.cc",
- "dex/modifiers.cc",
- "dex/standard_dex_file.cc",
- "dex/utf.cc",
- ],
-
- target: {
- android: {
- static_libs: [
- "libziparchive",
- "libz",
- "libbase",
- ],
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- shared_libs: [
- "libziparchive",
- "libz",
- ],
- },
- },
- generated_sources: ["dexfile_operator_srcs"],
- include_dirs: [
- "external/zlib",
- ],
- shared_libs: [
- "liblog",
- // For common macros.
- "libbase",
- "libz",
- ],
-
- // Exporting "." would shadow the system elf.h with our elf.h,
- // which in turn breaks any tools that reference this library.
- // export_include_dirs: ["."],
-}
-
-gensrcs {
- name: "dexfile_operator_srcs",
- cmd: "$(location generate-operator-out.py) art/runtime $(in) > $(out)",
- tool_files: ["generate-operator-out.py"],
- srcs: [
- "dex/dex_file.h",
- "dex/dex_file_layout.h",
- "dex/dex_instruction.h",
- "dex/dex_instruction_utils.h",
- "dex/invoke_type.h",
- ],
- output_extension: "operator_out.cc",
-}
-
-art_cc_library {
- name: "libdexfile",
- defaults: ["libdexfile_defaults"],
- // Leave the symbols in the shared library so that stack unwinders can
- // produce meaningful name resolution.
- strip: {
- keep_symbols: true,
- },
-}
-
// Keep the __jit_debug_register_code symbol as a unique symbol during ICF for architectures where
// we use gold as the linker (arm, x86, x86_64). The symbol is used by the debuggers to detect when
// new jit code is generated. We don't want it to be called when a different function with the same
@@ -133,9 +56,9 @@ cc_defaults {
"common_throws.cc",
"compiler_filter.cc",
"debugger.cc",
+ "dex/art_dex_file_loader.cc",
"dex/dex_file_annotations.cc",
"dex/dex_file_layout.cc",
- "dex/art_dex_file_loader.cc",
"dex_to_dex_decompiler.cc",
"elf_file.cc",
"exec_utils.cc",
@@ -244,7 +167,6 @@ cc_defaults {
"native/java_lang_Thread.cc",
"native/java_lang_Throwable.cc",
"native/java_lang_VMClassLoader.cc",
- "native/java_lang_Void.cc",
"native/java_lang_invoke_MethodHandleImpl.cc",
"native/java_lang_ref_FinalizerReference.cc",
"native/java_lang_ref_Reference.cc",
@@ -487,7 +409,6 @@ cc_defaults {
"jni_platform_headers",
],
shared_libs: [
- "libdexfile",
"libnativebridge",
"libnativeloader",
"libbacktrace",
@@ -521,9 +442,9 @@ gensrcs {
"base/callee_save_type.h",
"base/enums.h",
"base/mutex.h",
- "debugger.h",
"base/unix_file/fd_file.h",
"class_status.h",
+ "debugger.h",
"dex/dex_file_layout.h",
"gc_root.h",
"gc/allocator_type.h",
@@ -565,6 +486,8 @@ art_cc_library {
strip: {
keep_symbols: true,
},
+ shared_libs: ["libdexfile"],
+ export_shared_lib_headers: ["libdexfile"],
}
art_cc_library {
@@ -573,6 +496,8 @@ art_cc_library {
"art_debug_defaults",
"libart_defaults",
],
+ shared_libs: ["libdexfiled"],
+ export_shared_lib_headers: ["libdexfiled"],
}
art_cc_library {
@@ -637,13 +562,7 @@ art_cc_test {
"class_loader_context_test.cc",
"class_table_test.cc",
"compiler_filter_test.cc",
- "dex/code_item_accessors_test.cc",
- "dex/compact_dex_debug_info_test.cc",
- "dex/compact_dex_file_test.cc",
- "dex/dex_file_test.cc",
- "dex/dex_file_verifier_test.cc",
- "dex/dex_instruction_test.cc",
- "dex/utf_test.cc",
+ "dex/art_dex_file_loader_test.cc",
"entrypoints/math_entrypoints_test.cc",
"entrypoints/quick/quick_trampoline_entrypoints_test.cc",
"entrypoints_order_test.cc",
diff --git a/runtime/arch/memcmp16_test.cc b/runtime/arch/memcmp16_test.cc
index 2f3639c4b1..37aad21a40 100644
--- a/runtime/arch/memcmp16_test.cc
+++ b/runtime/arch/memcmp16_test.cc
@@ -100,7 +100,7 @@ static void CheckSeparate(size_t max_length, size_t min_length) {
}
size_t min = count1 < count2 ? count1 : count2;
- bool fill_same = r.next() % 1 == 1;
+ bool fill_same = r.next() % 2 == 1;
if (fill_same) {
for (size_t i = 0; i < min; ++i) {
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index e6e35c89c9..8b48aa27f9 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -328,6 +328,7 @@ inline mirror::DexCache* ArtMethod::GetDexCache() {
}
inline bool ArtMethod::IsProxyMethod() {
+ DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method";
// Avoid read barrier since the from-space version of the class will have the correct proxy class
// flags since they are constant for the lifetime of the class.
return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
diff --git a/runtime/art_method.h b/runtime/art_method.h
index cec2ec4df2..21ee8f19e5 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -551,7 +551,7 @@ class ArtMethod FINAL {
// Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
// conventions for a method of managed code. Returns false for Proxy methods.
ALWAYS_INLINE bool IsRuntimeMethod() {
- return dex_method_index_ == kRuntimeMethodDexMethodIndex;;
+ return dex_method_index_ == kRuntimeMethodDexMethodIndex;
}
// Is this a hand crafted method used for something like describing callee saves?
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
index 5e97a63c0d..c706c7ebf2 100644
--- a/runtime/base/bit_vector.cc
+++ b/runtime/base/bit_vector.cc
@@ -223,7 +223,7 @@ void BitVector::Subtract(const BitVector *src) {
// Difference until max, we know both accept it:
// There is no need to do more:
// If we are bigger than src, the upper bits are unchanged.
- // If we are smaller than src, the non-existant upper bits are 0 and thus can't get subtracted.
+ // If we are smaller than src, the nonexistent upper bits are 0 and thus can't get subtracted.
for (uint32_t idx = 0; idx < min_size; idx++) {
storage_[idx] &= (~(src->GetRawStorageWord(idx)));
}
diff --git a/runtime/base/stringpiece.cc b/runtime/base/stringpiece.cc
index 672431cf9d..aea4e74bb1 100644
--- a/runtime/base/stringpiece.cc
+++ b/runtime/base/stringpiece.cc
@@ -23,13 +23,6 @@
namespace art {
-#if !defined(NDEBUG)
-char StringPiece::operator[](size_type i) const {
- CHECK_LT(i, length_);
- return ptr_[i];
-}
-#endif
-
void StringPiece::CopyToString(std::string* target) const {
target->assign(ptr_, length_);
}
diff --git a/runtime/base/stringpiece.h b/runtime/base/stringpiece.h
index 46743e9643..e7109dc18a 100644
--- a/runtime/base/stringpiece.h
+++ b/runtime/base/stringpiece.h
@@ -20,6 +20,8 @@
#include <string.h>
#include <string>
+#include <android-base/logging.h>
+
namespace art {
// A string-like object that points to a sized piece of memory.
@@ -84,13 +86,10 @@ class StringPiece {
length_ = len;
}
-#if defined(NDEBUG)
char operator[](size_type i) const {
+ DCHECK_LT(i, length_);
return ptr_[i];
}
-#else
- char operator[](size_type i) const;
-#endif
void remove_prefix(size_type n) {
ptr_ += n;
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 5549122c34..05f099f3b2 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -46,6 +46,7 @@
#include "well_known_classes.h"
namespace art {
+namespace {
using android::base::StringAppendF;
using android::base::StringPrintf;
@@ -1211,7 +1212,7 @@ class ScopedCheck {
// this particular instance of JNIEnv.
if (env != threadEnv) {
// Get the thread owning the JNIEnv that's being used.
- Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self_;
+ Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
AbortF("thread %s using JNIEnv* from thread %s",
ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
return false;
@@ -1223,7 +1224,7 @@ class ScopedCheck {
case kFlag_CritOkay: // okay to call this method
break;
case kFlag_CritBad: // not okay to call
- if (threadEnv->critical_ > 0) {
+ if (threadEnv->GetCritical() > 0) {
AbortF("thread %s using JNI after critical get",
ToStr<Thread>(*self).c_str());
return false;
@@ -1231,25 +1232,25 @@ class ScopedCheck {
break;
case kFlag_CritGet: // this is a "get" call
// Don't check here; we allow nested gets.
- if (threadEnv->critical_ == 0) {
- threadEnv->critical_start_us_ = self->GetCpuMicroTime();
+ if (threadEnv->GetCritical() == 0) {
+ threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
}
- threadEnv->critical_++;
+ threadEnv->SetCritical(threadEnv->GetCritical() + 1);
break;
case kFlag_CritRelease: // this is a "release" call
- if (threadEnv->critical_ == 0) {
+ if (threadEnv->GetCritical() == 0) {
AbortF("thread %s called too many critical releases",
ToStr<Thread>(*self).c_str());
return false;
- } else if (threadEnv->critical_ == 1) {
+ } else if (threadEnv->GetCritical() == 1) {
// Leaving the critical region, possibly warn about long critical regions.
- uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->critical_start_us_;
+ uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
if (critical_duration_us > kCriticalWarnTimeUs) {
LOG(WARNING) << "JNI critical lock held for "
<< PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
}
}
- threadEnv->critical_--;
+ threadEnv->SetCritical(threadEnv->GetCritical() - 1);
break;
default:
LOG(FATAL) << "Bad flags (internal error): " << flags_;
@@ -2621,7 +2622,7 @@ class CheckJNI {
}
static const JNINativeInterface* baseEnv(JNIEnv* env) {
- return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions_;
+ return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
}
static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
@@ -3847,10 +3848,6 @@ const JNINativeInterface gCheckNativeInterface = {
CheckJNI::GetObjectRefType,
};
-const JNINativeInterface* GetCheckJniNativeInterface() {
- return &gCheckNativeInterface;
-}
-
class CheckJII {
public:
static jint DestroyJavaVM(JavaVM* vm) {
@@ -3922,6 +3919,12 @@ const JNIInvokeInterface gCheckInvokeInterface = {
CheckJII::AttachCurrentThreadAsDaemon
};
+} // anonymous namespace
+
+const JNINativeInterface* GetCheckJniNativeInterface() {
+ return &gCheckNativeInterface;
+}
+
const JNIInvokeInterface* GetCheckJniInvokeInterface() {
return &gCheckInvokeInterface;
}
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index cd6e8d59e8..ae06f8f9bc 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -226,14 +226,7 @@ inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
if (klass != nullptr) {
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache, method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache, method_idx, pointer_size);
- }
- if (resolved != nullptr) {
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
}
}
return resolved;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 800427d6ab..62627287b0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -457,7 +457,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
VoidFunctor()));
// Initialize the SubtypeCheck bitstring for java.lang.Object and java.lang.Class.
- {
+ if (kBitstringSubtypeCheckEnabled) {
// It might seem the lock here is unnecessary, however all the SubtypeCheck
// functions are annotated to require locks all the way down.
//
@@ -1856,7 +1856,7 @@ bool ClassLinker::AddImageSpace(
visitor(root.Read());
}
- {
+ if (kBitstringSubtypeCheckEnabled) {
// Every class in the app image has initially SubtypeCheckInfo in the
// Uninitialized state.
//
@@ -4484,6 +4484,14 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
Runtime::Current()->GetRuntimeCallbacks()->ClassPrepare(temp_klass, klass);
+ // SubtypeCheckInfo::Initialized must happen-before any new-instance for that type.
+ // See also ClassLinker::EnsureInitialized().
+ if (kBitstringSubtypeCheckEnabled) {
+ MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_);
+ SubtypeCheck<ObjPtr<mirror::Class>>::EnsureInitialized(klass.Get());
+ // TODO: Avoid taking subtype_check_lock_ if SubtypeCheck for j.l.r.Proxy is already assigned.
+ }
+
{
// Lock on klass is released. Lock new class object.
ObjectLock<mirror::Class> initialization_lock(self, klass);
@@ -5231,7 +5239,7 @@ bool ClassLinker::EnsureInitialized(Thread* self,
// can be used as a source for the IsSubClass check, and that all ancestors
// of the class are Assigned (can be used as a target for IsSubClass check)
// or Overflowed (can be used as a source for IsSubClass check).
- {
+ if (kBitstringSubtypeCheckEnabled) {
MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_);
SubtypeCheck<ObjPtr<mirror::Class>>::EnsureInitialized(c.Get());
// TODO: Avoid taking subtype_check_lock_ if SubtypeCheck is already initialized.
@@ -7931,6 +7939,38 @@ std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* clas
return oss.str();
}
+ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx) {
+ // Search for the method using dex_cache and method_idx. The Class::Find*Method()
+ // functions can optimize the search if the dex_cache is the same as the DexCache
+ // of the class, with fall-back to name and signature search otherwise.
+ ArtMethod* resolved = nullptr;
+ if (klass->IsInterface()) {
+ resolved = klass->FindInterfaceMethod(dex_cache, method_idx, image_pointer_size_);
+ } else {
+ resolved = klass->FindClassMethod(dex_cache, method_idx, image_pointer_size_);
+ }
+ DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
+ if (resolved != nullptr) {
+ // In case of jmvti, the dex file gets verified before being registered, so first
+ // check if it's registered before checking class tables.
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ CHECK(!IsDexFileRegistered(Thread::Current(), dex_file) ||
+ FindClassTable(Thread::Current(), dex_cache) == ClassTableForClassLoader(class_loader))
+ << "DexFile referrer: " << dex_file.GetLocation()
+ << " ClassLoader: " << DescribeLoaders(class_loader, "");
+ // Be a good citizen and update the dex cache to speed subsequent calls.
+ dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_);
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+ CHECK(LookupResolvedType(method_id.class_idx_, dex_cache, class_loader) != nullptr)
+ << "Class: " << klass->PrettyClass() << ", "
+ << "DexFile referrer: " << dex_file.GetLocation();
+ }
+ return resolved;
+}
+
template <ClassLinker::ResolveMode kResolveMode>
ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
Handle<mirror::DexCache> dex_cache,
@@ -7963,6 +8003,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
<< resolved->PrettyMethod() << ";" << resolved
<< "/0x" << std::hex << resolved->GetAccessFlags()
<< " ReferencedClass: " << descriptor
+ << " DexFile referrer: " << dex_file.GetLocation()
<< " ClassLoader: " << DescribeLoaders(class_loader.Get(), descriptor);
}
} else {
@@ -7983,19 +8024,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
}
if (!valid_dex_cache_method) {
- // Search for the method using dex_cache and method_idx. The Class::Find*Method()
- // functions can optimize the search if the dex_cache is the same as the DexCache
- // of the class, with fall-back to name and signature search otherwise.
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache.Get(), method_idx, pointer_size);
- }
- DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
- if (resolved != nullptr) {
- // Be a good citizen and update the dex cache to speed subsequent calls.
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx);
}
// Note: We can check for IllegalAccessError only if we have a referrer.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 16fa1ce801..6bb924fc7d 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -312,6 +312,13 @@ class ClassLinker {
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Find a method with the given index from class `klass`, and update the dex cache.
+ ArtMethod* FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Resolve a method with a given ID from the DexFile associated with the given DexCache
// and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader are
// used as in ResolveType. What is unique is the method type argument which is used to
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 1b6f317053..8f65c66441 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -53,6 +53,11 @@ static void AddReferrerLocation(std::ostream& os, ObjPtr<mirror::Class> referrer
}
}
+static void ThrowException(const char* exception_descriptor) REQUIRES_SHARED(Locks::mutator_lock_) {
+ Thread* self = Thread::Current();
+ self->ThrowNewException(exception_descriptor, nullptr);
+}
+
static void ThrowException(const char* exception_descriptor,
ObjPtr<mirror::Class> referrer,
const char* fmt,
@@ -243,6 +248,11 @@ void ThrowIllegalArgumentException(const char* msg) {
ThrowException("Ljava/lang/IllegalArgumentException;", nullptr, msg);
}
+// IllegalStateException
+
+void ThrowIllegalStateException(const char* msg) {
+ ThrowException("Ljava/lang/IllegalStateException;", nullptr, msg);
+}
// IncompatibleClassChangeError
@@ -314,6 +324,13 @@ void ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod* method) {
ArtMethod::PrettyMethod(method).c_str()).c_str());
}
+// IndexOutOfBoundsException
+
+void ThrowIndexOutOfBoundsException(int index, int length) {
+ ThrowException("Ljava/lang/IndexOutOfBoundsException;", nullptr,
+ StringPrintf("length=%d; index=%d", length, index).c_str());
+}
+
// InternalError
void ThrowInternalError(const char* fmt, ...) {
@@ -721,6 +738,12 @@ void ThrowNullPointerException(const char* msg) {
ThrowException("Ljava/lang/NullPointerException;", nullptr, msg);
}
+// ReadOnlyBufferException
+
+void ThrowReadOnlyBufferException() {
+ Thread::Current()->ThrowNewException("Ljava/nio/ReadOnlyBufferException;", nullptr);
+}
+
// RuntimeException
void ThrowRuntimeException(const char* fmt, ...) {
@@ -844,6 +867,12 @@ void ThrowStringIndexOutOfBoundsException(int index, int length) {
StringPrintf("length=%d; index=%d", length, index).c_str());
}
+// UnsupportedOperationException
+
+void ThrowUnsupportedOperationException() {
+ ThrowException("Ljava/lang/UnsupportedOperationException;");
+}
+
// VerifyError
void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) {
@@ -855,13 +884,13 @@ void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) {
// WrongMethodTypeException
-void ThrowWrongMethodTypeException(mirror::MethodType* callee_type,
- mirror::MethodType* callsite_type) {
+void ThrowWrongMethodTypeException(mirror::MethodType* expected_type,
+ mirror::MethodType* actual_type) {
ThrowException("Ljava/lang/invoke/WrongMethodTypeException;",
nullptr,
StringPrintf("Expected %s but was %s",
- callee_type->PrettyDescriptor().c_str(),
- callsite_type->PrettyDescriptor().c_str()).c_str());
+ expected_type->PrettyDescriptor().c_str(),
+ actual_type->PrettyDescriptor().c_str()).c_str());
}
} // namespace art
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 3512b2b5bf..e9baa4fef0 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -120,6 +120,11 @@ void ThrowIllegalAccessException(const char* msg)
void ThrowIllegalArgumentException(const char* msg)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+// IllegalAccessException
+
+void ThrowIllegalStateException(const char* msg)
+ REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+
// IncompatibleClassChangeError
void ThrowIncompatibleClassChangeError(InvokeType expected_type,
@@ -151,6 +156,11 @@ void ThrowIncompatibleClassChangeError(ObjPtr<mirror::Class> referrer, const cha
void ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+// IndexOutOfBoundsException
+
+void ThrowIndexOutOfBoundsException(int index, int length)
+ REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+
// InternalError
void ThrowInternalError(const char* fmt, ...)
@@ -223,6 +233,10 @@ void ThrowNullPointerExceptionFromDexPC(bool check_address = false, uintptr_t ad
void ThrowNullPointerException(const char* msg)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+// ReadOnlyBufferException
+
+void ThrowReadOnlyBufferException() REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+
// RuntimeException
void ThrowRuntimeException(const char* fmt, ...)
@@ -244,6 +258,10 @@ void ThrowStackOverflowError(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_)
void ThrowStringIndexOutOfBoundsException(int index, int length)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+// UnsupportedOperationException
+
+void ThrowUnsupportedOperationException() REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+
// VerifyError
void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...)
@@ -251,6 +269,7 @@ void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
// WrongMethodTypeException
+
void ThrowWrongMethodTypeException(mirror::MethodType* callee_type,
mirror::MethodType* callsite_type)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc
index 08cf30d5bf..0817cb4b6a 100644
--- a/runtime/dex/art_dex_file_loader.cc
+++ b/runtime/dex/art_dex_file_loader.cc
@@ -25,10 +25,10 @@
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
-#include "compact_dex_file.h"
-#include "dex_file.h"
-#include "dex_file_verifier.h"
-#include "standard_dex_file.h"
+#include "dex/compact_dex_file.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_verifier.h"
+#include "dex/standard_dex_file.h"
#include "zip_archive.h"
namespace art {
diff --git a/runtime/dex/art_dex_file_loader.h b/runtime/dex/art_dex_file_loader.h
index b31d1e94e0..3585381f9b 100644
--- a/runtime/dex/art_dex_file_loader.h
+++ b/runtime/dex/art_dex_file_loader.h
@@ -22,8 +22,8 @@
#include <string>
#include <vector>
-#include "dex_file_loader.h"
#include "base/macros.h"
+#include "dex/dex_file_loader.h"
namespace art {
diff --git a/runtime/dex/art_dex_file_loader_test.cc b/runtime/dex/art_dex_file_loader_test.cc
new file mode 100644
index 0000000000..25d4dd0875
--- /dev/null
+++ b/runtime/dex/art_dex_file_loader_test.cc
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include <sys/mman.h>
+
+#include <memory>
+
+#include "art_dex_file_loader.h"
+#include "base/stl_util.h"
+#include "base/unix_file/fd_file.h"
+#include "common_runtime_test.h"
+#include "dex/base64_test_util.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/descriptors_names.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file_loader.h"
+#include "mem_map.h"
+#include "os.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread-current-inl.h"
+
+namespace art {
+
+class ArtDexFileLoaderTest : public CommonRuntimeTest {};
+
+// TODO: Port OpenTestDexFile(s) need to be ported to use non-ART utilities, and
+// the tests that depend upon them should be moved to dex_file_loader_test.cc
+
+TEST_F(ArtDexFileLoaderTest, Open) {
+ ScopedObjectAccess soa(Thread::Current());
+ std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
+ ASSERT_TRUE(dex.get() != nullptr);
+}
+
+TEST_F(ArtDexFileLoaderTest, GetLocationChecksum) {
+ ScopedObjectAccess soa(Thread::Current());
+ std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
+ EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
+}
+
+TEST_F(ArtDexFileLoaderTest, GetChecksum) {
+ std::vector<uint32_t> checksums;
+ ScopedObjectAccess soa(Thread::Current());
+ std::string error_msg;
+ const ArtDexFileLoader dex_file_loader;
+ EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
+ &checksums,
+ &error_msg))
+ << error_msg;
+ ASSERT_EQ(1U, checksums.size());
+ EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
+}
+
+TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) {
+ std::string error_msg;
+ std::vector<uint32_t> checksums;
+ std::string multidex_file = GetTestDexFileName("MultiDex");
+ const ArtDexFileLoader dex_file_loader;
+ EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(),
+ &checksums,
+ &error_msg)) << error_msg;
+
+ std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
+ ASSERT_EQ(2U, dexes.size());
+ ASSERT_EQ(2U, checksums.size());
+
+ EXPECT_EQ(dexes[0]->GetLocation(), DexFileLoader::GetMultiDexLocation(0, multidex_file.c_str()));
+ EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
+
+ EXPECT_EQ(dexes[1]->GetLocation(), DexFileLoader::GetMultiDexLocation(1, multidex_file.c_str()));
+ EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
+}
+
+TEST_F(ArtDexFileLoaderTest, ClassDefs) {
+ ScopedObjectAccess soa(Thread::Current());
+ std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
+ ASSERT_TRUE(raw.get() != nullptr);
+ EXPECT_EQ(3U, raw->NumClassDefs());
+
+ const DexFile::ClassDef& c0 = raw->GetClassDef(0);
+ EXPECT_STREQ("LNested$1;", raw->GetClassDescriptor(c0));
+
+ const DexFile::ClassDef& c1 = raw->GetClassDef(1);
+ EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c1));
+
+ const DexFile::ClassDef& c2 = raw->GetClassDef(2);
+ EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c2));
+}
+
+TEST_F(ArtDexFileLoaderTest, GetMethodSignature) {
+ ScopedObjectAccess soa(Thread::Current());
+ std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
+ ASSERT_TRUE(raw.get() != nullptr);
+ EXPECT_EQ(1U, raw->NumClassDefs());
+
+ const DexFile::ClassDef& class_def = raw->GetClassDef(0);
+ ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
+
+ const uint8_t* class_data = raw->GetClassData(class_def);
+ ASSERT_TRUE(class_data != nullptr);
+ ClassDataItemIterator it(*raw, class_data);
+
+ EXPECT_EQ(1u, it.NumDirectMethods());
+
+ // Check the signature for the static initializer.
+ {
+ ASSERT_EQ(1U, it.NumDirectMethods());
+ const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
+ const char* name = raw->StringDataByIdx(method_id.name_idx_);
+ ASSERT_STREQ("<init>", name);
+ std::string signature(raw->GetMethodSignature(method_id).ToString());
+ ASSERT_EQ("()V", signature);
+ }
+
+ // Check all virtual methods.
+ struct Result {
+ const char* name;
+ const char* signature;
+ const char* pretty_method;
+ };
+ static const Result results[] = {
+ {
+ "m1",
+ "(IDJLjava/lang/Object;)Ljava/lang/Float;",
+ "java.lang.Float GetMethodSignature.m1(int, double, long, java.lang.Object)"
+ },
+ {
+ "m2",
+ "(ZSC)LGetMethodSignature;",
+ "GetMethodSignature GetMethodSignature.m2(boolean, short, char)"
+ },
+ {
+ "m3",
+ "()V",
+ "void GetMethodSignature.m3()"
+ },
+ {
+ "m4",
+ "(I)V",
+ "void GetMethodSignature.m4(int)"
+ },
+ {
+ "m5",
+ "(II)V",
+ "void GetMethodSignature.m5(int, int)"
+ },
+ {
+ "m6",
+ "(II[[I)V",
+ "void GetMethodSignature.m6(int, int, int[][])"
+ },
+ {
+ "m7",
+ "(II[[ILjava/lang/Object;)V",
+ "void GetMethodSignature.m7(int, int, int[][], java.lang.Object)"
+ },
+ {
+ "m8",
+ "(II[[ILjava/lang/Object;[[Ljava/lang/Object;)V",
+ "void GetMethodSignature.m8(int, int, int[][], java.lang.Object, java.lang.Object[][])"
+ },
+ {
+ "m9",
+ "()I",
+ "int GetMethodSignature.m9()"
+ },
+ {
+ "mA",
+ "()[[I",
+ "int[][] GetMethodSignature.mA()"
+ },
+ {
+ "mB",
+ "()[[Ljava/lang/Object;",
+ "java.lang.Object[][] GetMethodSignature.mB()"
+ },
+ };
+ ASSERT_EQ(arraysize(results), it.NumVirtualMethods());
+ for (const Result& r : results) {
+ it.Next();
+ const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
+
+ const char* name = raw->StringDataByIdx(method_id.name_idx_);
+ ASSERT_STREQ(r.name, name);
+
+ std::string signature(raw->GetMethodSignature(method_id).ToString());
+ ASSERT_EQ(r.signature, signature);
+
+ std::string plain_method = std::string("GetMethodSignature.") + r.name;
+ ASSERT_EQ(plain_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ false));
+ ASSERT_EQ(r.pretty_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ true));
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, FindStringId) {
+ ScopedObjectAccess soa(Thread::Current());
+ std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
+ ASSERT_TRUE(raw.get() != nullptr);
+ EXPECT_EQ(1U, raw->NumClassDefs());
+
+ const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
+ "D", "I", "J", nullptr };
+ for (size_t i = 0; strings[i] != nullptr; i++) {
+ const char* str = strings[i];
+ const DexFile::StringId* str_id = raw->FindStringId(str);
+ const char* dex_str = raw->GetStringData(*str_id);
+ EXPECT_STREQ(dex_str, str);
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, FindTypeId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
+ const char* type_str = java_lang_dex_file_->StringByTypeIdx(dex::TypeIndex(i));
+ const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
+ ASSERT_TRUE(type_str_id != nullptr);
+ dex::StringIndex type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
+ const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
+ ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
+ ASSERT_TRUE(type_id != nullptr);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id).index_, i);
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, FindProtoId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
+ const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
+ const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
+ std::vector<dex::TypeIndex> to_find_types;
+ if (to_find_tl != nullptr) {
+ for (size_t j = 0; j < to_find_tl->Size(); j++) {
+ to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
+ }
+ }
+ const DexFile::ProtoId* found =
+ java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
+ ASSERT_TRUE(found != nullptr);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, FindMethodId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
+ const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
+ const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
+ const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
+ const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
+ const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
+ ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
+ << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
+ << java_lang_dex_file_->GetStringData(name)
+ << java_lang_dex_file_->GetMethodSignature(to_find);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, FindFieldId) {
+ for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
+ const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
+ const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
+ const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
+ const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
+ const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
+ ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
+ << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
+ << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
+ << java_lang_dex_file_->GetStringData(name);
+ EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
+ }
+}
+
+TEST_F(ArtDexFileLoaderTest, GetDexCanonicalLocation) {
+ ScratchFile file;
+ UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
+ std::string dex_location(dex_location_real.get());
+
+ ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location.c_str()));
+ std::string multidex_location = DexFileLoader::GetMultiDexLocation(1, dex_location.c_str());
+ ASSERT_EQ(multidex_location, DexFileLoader::GetDexCanonicalLocation(multidex_location.c_str()));
+
+ std::string dex_location_sym = dex_location + "symlink";
+ ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
+
+ ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location_sym.c_str()));
+
+ std::string multidex_location_sym = DexFileLoader::GetMultiDexLocation(
+ 1, dex_location_sym.c_str());
+ ASSERT_EQ(multidex_location,
+ DexFileLoader::GetDexCanonicalLocation(multidex_location_sym.c_str()));
+
+ ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
+}
+
+} // namespace art
diff --git a/runtime/dex/code_item_accessors-no_art-inl.h b/runtime/dex/code_item_accessors-no_art-inl.h
deleted file mode 100644
index 8082be3818..0000000000
--- a/runtime/dex/code_item_accessors-no_art-inl.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
-#define ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
-
-// TODO: delete this file once system/core is updated.
-#include "code_item_accessors-inl.h"
-
-#endif // ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index e01890f541..3431bb7efb 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -23,7 +23,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "class_linker-inl.h"
-#include "dex_file-inl.h"
+#include "dex/dex_file-inl.h"
#include "jni_internal.h"
#include "jvalue-inl.h"
#include "mirror/field.h"
diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h
index 26773729c2..d7ebf84b1c 100644
--- a/runtime/dex/dex_file_annotations.h
+++ b/runtime/dex/dex_file_annotations.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_DEX_DEX_FILE_ANNOTATIONS_H_
#define ART_RUNTIME_DEX_DEX_FILE_ANNOTATIONS_H_
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "handle.h"
#include "mirror/dex_cache.h"
diff --git a/runtime/dex/dex_file_layout.cc b/runtime/dex/dex_file_layout.cc
index 312898d82f..d85d61d56b 100644
--- a/runtime/dex/dex_file_layout.cc
+++ b/runtime/dex/dex_file_layout.cc
@@ -19,8 +19,7 @@
#include <sys/mman.h>
#include "base/file_utils.h"
-#include "descriptors_names.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
namespace art {
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 037d1fb49c..8ce7921287 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -49,7 +49,8 @@ void DexoptTest::GenerateOatForTest(const std::string& dex_location,
CompilerFilter::Filter filter,
bool relocate,
bool pic,
- bool with_alternate_image) {
+ bool with_alternate_image,
+ const char* compilation_reason) {
std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA));
std::string dalvik_cache_tmp = dalvik_cache + ".redirected";
std::string oat_location = oat_location_in;
@@ -89,6 +90,10 @@ void DexoptTest::GenerateOatForTest(const std::string& dex_location,
args.push_back("--boot-image=" + GetImageLocation2());
}
+ if (compilation_reason != nullptr) {
+ args.push_back("--compilation-reason=" + std::string(compilation_reason));
+ }
+
std::string error_msg;
ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
@@ -155,13 +160,15 @@ void DexoptTest::GenerateOdexForTest(const std::string& dex_location,
void DexoptTest::GeneratePicOdexForTest(const std::string& dex_location,
const std::string& odex_location,
- CompilerFilter::Filter filter) {
+ CompilerFilter::Filter filter,
+ const char* compilation_reason) {
GenerateOatForTest(dex_location,
odex_location,
filter,
/*relocate*/false,
/*pic*/true,
- /*with_alternate_image*/false);
+ /*with_alternate_image*/false,
+ compilation_reason);
}
void DexoptTest::GenerateOatForTest(const char* dex_location,
diff --git a/runtime/dexopt_test.h b/runtime/dexopt_test.h
index 5f0eafd8eb..6e8dc097d5 100644
--- a/runtime/dexopt_test.h
+++ b/runtime/dexopt_test.h
@@ -46,7 +46,8 @@ class DexoptTest : public Dex2oatEnvironmentTest {
CompilerFilter::Filter filter,
bool relocate,
bool pic,
- bool with_alternate_image);
+ bool with_alternate_image,
+ const char* compilation_reason = nullptr);
// Generate a non-PIC odex file for the purposes of test.
// The generated odex file will be un-relocated.
@@ -56,7 +57,8 @@ class DexoptTest : public Dex2oatEnvironmentTest {
void GeneratePicOdexForTest(const std::string& dex_location,
const std::string& odex_location,
- CompilerFilter::Filter filter);
+ CompilerFilter::Filter filter,
+ const char* compilation_reason = nullptr);
// Generate an oat file for the given dex location in its oat location (under
// the dalvik cache).
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 9ef7d426df..404c5357bf 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -99,14 +99,13 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
<< "This must be due to playing wrongly with class loaders";
}
- inlined_method = klass->FindClassMethod(dex_cache, method_index, kRuntimePointerSize);
+ inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index);
if (inlined_method == nullptr) {
LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
<< " does not have " << dex_file->GetMethodName(method_id)
<< dex_file->GetMethodSignature(method_id) << " declared. "
<< "This must be due to duplicate classes or playing wrongly with class loaders";
}
- dex_cache->SetResolvedMethod(method_index, inlined_method, kRuntimePointerSize);
return inlined_method;
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index c5157ce9f4..a8c328fbc7 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -319,7 +319,7 @@ class QuickArgumentVisitor {
// 'this' object is the 1st argument. They also have the same frame layout as the
// kRefAndArgs runtime method. Since 'this' is a reference, it is located in the
// 1st GPR.
- static mirror::Object* GetProxyThisObject(ArtMethod** sp)
+ static StackReference<mirror::Object>* GetProxyThisObjectReference(ArtMethod** sp)
REQUIRES_SHARED(Locks::mutator_lock_) {
CHECK((*sp)->IsProxyMethod());
CHECK_GT(kNumQuickGprArgs, 0u);
@@ -327,7 +327,7 @@ class QuickArgumentVisitor {
size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset +
GprIndexToGprOffset(kThisGprIndex);
uint8_t* this_arg_address = reinterpret_cast<uint8_t*>(sp) + this_arg_offset;
- return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address)->AsMirrorPtr();
+ return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address);
}
static ArtMethod* GetCallingMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -647,7 +647,11 @@ class QuickArgumentVisitor {
// allows to use the QuickArgumentVisitor constants without moving all the code in its own module.
extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp)
REQUIRES_SHARED(Locks::mutator_lock_) {
- return QuickArgumentVisitor::GetProxyThisObject(sp);
+ return QuickArgumentVisitor::GetProxyThisObjectReference(sp)->AsMirrorPtr();
+}
+extern "C" StackReference<mirror::Object>* artQuickGetProxyThisObjectReference(ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return QuickArgumentVisitor::GetProxyThisObjectReference(sp);
}
// Visits arguments on the stack placing them into the shadow frame.
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 72eb8274c8..f8d8271335 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -41,7 +41,7 @@ namespace art {
namespace gc {
namespace accounting {
-// Internal representation is StackReference<T>, so this only works with mirror::Object or it's
+// Internal representation is StackReference<T>, so this only works with mirror::Object or its
// subclasses.
template <typename T>
class AtomicStack {
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index df9ee8c219..354b9e1dbd 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -62,7 +62,8 @@ inline bool SpaceBitmap<kAlignment>::Test(const mirror::Object* obj) const {
return (bitmap_begin_[OffsetToIndex(offset)].LoadRelaxed() & OffsetToMask(offset)) != 0;
}
-template<size_t kAlignment> template<typename Visitor>
+template<size_t kAlignment>
+template<typename Visitor>
inline void SpaceBitmap<kAlignment>::VisitMarkedRange(uintptr_t visit_begin,
uintptr_t visit_end,
Visitor&& visitor) const {
@@ -121,6 +122,7 @@ inline void SpaceBitmap<kAlignment>::VisitMarkedRange(uintptr_t visit_begin,
uintptr_t w = bitmap_begin_[i].LoadRelaxed();
if (w != 0) {
const uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
+ // Iterate on the bits set in word `w`, from the least to the most significant bit.
do {
const size_t shift = CTZ(w);
mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
@@ -147,6 +149,7 @@ inline void SpaceBitmap<kAlignment>::VisitMarkedRange(uintptr_t visit_begin,
right_edge &= ((static_cast<uintptr_t>(1) << bit_end) - 1);
if (right_edge != 0) {
const uintptr_t ptr_base = IndexToOffset(index_end) + heap_begin_;
+ // Iterate on the bits set in word `right_edge`, from the least to the most significant bit.
do {
const size_t shift = CTZ(right_edge);
mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
@@ -157,7 +160,8 @@ inline void SpaceBitmap<kAlignment>::VisitMarkedRange(uintptr_t visit_begin,
#endif
}
-template<size_t kAlignment> template<typename Visitor>
+template<size_t kAlignment>
+template<typename Visitor>
void SpaceBitmap<kAlignment>::Walk(Visitor&& visitor) {
CHECK(bitmap_begin_ != nullptr);
@@ -177,7 +181,8 @@ void SpaceBitmap<kAlignment>::Walk(Visitor&& visitor) {
}
}
-template<size_t kAlignment> template<bool kSetBit>
+template<size_t kAlignment>
+template<bool kSetBit>
inline bool SpaceBitmap<kAlignment>::Modify(const mirror::Object* obj) {
uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
DCHECK_GE(addr, heap_begin_);
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 237ee80ba0..0247564a8c 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -33,7 +33,12 @@ using android::base::StringPrintf;
template<size_t kAlignment>
size_t SpaceBitmap<kAlignment>::ComputeBitmapSize(uint64_t capacity) {
+ // Number of space (heap) bytes covered by one bitmap word.
+ // (Word size in bytes = `sizeof(intptr_t)`, which is expected to be
+ // 4 on a 32-bit architecture and 8 on a 64-bit one.)
const uint64_t kBytesCoveredPerWord = kAlignment * kBitsPerIntPtrT;
+ // Calculate the number of words required to cover a space (heap)
+ // having a size of `capacity` bytes.
return (RoundUp(capacity, kBytesCoveredPerWord) / kBytesCoveredPerWord) * sizeof(intptr_t);
}
@@ -74,7 +79,8 @@ SpaceBitmap<kAlignment>::~SpaceBitmap() {}
template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::Create(
const std::string& name, uint8_t* heap_begin, size_t heap_capacity) {
- // Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
+ // Round up since `heap_capacity` is not necessarily a multiple of `kAlignment * kBitsPerIntPtrT`
+ // (we represent one word as an `intptr_t`).
const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
std::string error_msg;
std::unique_ptr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), nullptr, bitmap_size,
@@ -116,7 +122,7 @@ template<size_t kAlignment>
void SpaceBitmap<kAlignment>::ClearRange(const mirror::Object* begin, const mirror::Object* end) {
uintptr_t begin_offset = reinterpret_cast<uintptr_t>(begin) - heap_begin_;
uintptr_t end_offset = reinterpret_cast<uintptr_t>(end) - heap_begin_;
- // Align begin and end to word boundaries.
+ // Align begin and end to bitmap word boundaries.
while (begin_offset < end_offset && OffsetBitIndex(begin_offset) != 0) {
Clear(reinterpret_cast<mirror::Object*>(heap_begin_ + begin_offset));
begin_offset += kAlignment;
@@ -125,6 +131,7 @@ void SpaceBitmap<kAlignment>::ClearRange(const mirror::Object* begin, const mirr
end_offset -= kAlignment;
Clear(reinterpret_cast<mirror::Object*>(heap_begin_ + end_offset));
}
+ // Bitmap word boundaries.
const uintptr_t start_index = OffsetToIndex(begin_offset);
const uintptr_t end_index = OffsetToIndex(end_offset);
ZeroAndReleasePages(reinterpret_cast<uint8_t*>(&bitmap_begin_[start_index]),
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 2f33bac902..437aecc2b1 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -55,6 +55,10 @@ class SpaceBitmap {
~SpaceBitmap();
+ // Return the bitmap word index corresponding to memory offset (relative to
+ // `HeapBegin()`) `offset`.
+ // See also SpaceBitmap::OffsetBitIndex.
+ //
// <offset> is the difference from .base to a pointer address.
// <index> is the index of .bits that contains the bit representing
// <offset>.
@@ -62,24 +66,32 @@ class SpaceBitmap {
return offset / kAlignment / kBitsPerIntPtrT;
}
+ // Return the memory offset (relative to `HeapBegin()`) corresponding to
+ // bitmap word index `index`.
template<typename T>
static constexpr T IndexToOffset(T index) {
return static_cast<T>(index * kAlignment * kBitsPerIntPtrT);
}
+ // Return the bit within the bitmap word index corresponding to
+ // memory offset (relative to `HeapBegin()`) `offset`.
+ // See also SpaceBitmap::OffsetToIndex.
ALWAYS_INLINE static constexpr uintptr_t OffsetBitIndex(uintptr_t offset) {
return (offset / kAlignment) % kBitsPerIntPtrT;
}
+ // Return the word-wide bit mask corresponding to `OffsetBitIndex(offset)`.
// Bits are packed in the obvious way.
static constexpr uintptr_t OffsetToMask(uintptr_t offset) {
return static_cast<size_t>(1) << OffsetBitIndex(offset);
}
+ // Set the bit corresponding to `obj` in the bitmap and return the previous value of that bit.
bool Set(const mirror::Object* obj) ALWAYS_INLINE {
return Modify<true>(obj);
}
+ // Clear the bit corresponding to `obj` in the bitmap and return the previous value of that bit.
bool Clear(const mirror::Object* obj) ALWAYS_INLINE {
return Modify<false>(obj);
}
@@ -90,9 +102,14 @@ class SpaceBitmap {
// Fill the bitmap with zeroes. Returns the bitmap's memory to the system as a side-effect.
void Clear();
- // Clear a covered by the bitmap using madvise if possible.
+ // Clear a range covered by the bitmap using madvise if possible.
void ClearRange(const mirror::Object* begin, const mirror::Object* end);
+ // Test whether `obj` is part of the bitmap (i.e. return whether the bit
+ // corresponding to `obj` has been set in the bitmap).
+ //
+ // Precondition: `obj` is within the range of pointers that this bitmap could
+ // potentially cover (i.e. `this->HasAddress(obj)` is true)
bool Test(const mirror::Object* obj) const;
// Return true iff <obj> is within the range of pointers that this bitmap could potentially cover,
@@ -204,6 +221,8 @@ class SpaceBitmap {
const void* heap_begin,
size_t heap_capacity);
+ // Change the value of the bit corresponding to `obj` in the bitmap
+ // to `kSetBit` and return the previous value of that bit.
template<bool kSetBit>
bool Modify(const mirror::Object* obj);
diff --git a/runtime/gc/accounting/space_bitmap_test.cc b/runtime/gc/accounting/space_bitmap_test.cc
index bd5f77ebb1..1ca3fd6d12 100644
--- a/runtime/gc/accounting/space_bitmap_test.cc
+++ b/runtime/gc/accounting/space_bitmap_test.cc
@@ -74,7 +74,7 @@ TEST_F(SpaceBitmapTest, ScanRange) {
}
}
// Try every possible starting bit in the first word. Then for each starting bit, try each
- // possible length up to a maximum of kBitsPerWord * 2 - 1 bits.
+ // possible length up to a maximum of `kBitsPerIntPtrT * 2 - 1` bits.
// This handles all the cases, having runs which start and end on the same word, and different
// words.
for (size_t i = 0; i < static_cast<size_t>(kBitsPerIntPtrT); ++i) {
diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h
index 85a656ec51..d739ed2867 100644
--- a/runtime/gc/collector/concurrent_copying-inl.h
+++ b/runtime/gc/collector/concurrent_copying-inl.h
@@ -52,7 +52,8 @@ inline mirror::Object* ConcurrentCopying::MarkUnevacFromSpaceRegion(
// we can avoid an expensive CAS.
// For the baker case, an object is marked if either the mark bit marked or the bitmap bit is
// set.
- success = ref->AtomicSetReadBarrierState(ReadBarrier::WhiteState(), ReadBarrier::GrayState());
+ success = ref->AtomicSetReadBarrierState(/* expected_rb_state */ ReadBarrier::WhiteState(),
+ /* rb_state */ ReadBarrier::GrayState());
} else {
success = !bitmap->AtomicTestAndSet(ref);
}
@@ -86,8 +87,8 @@ inline mirror::Object* ConcurrentCopying::MarkImmuneSpace(mirror::Object* ref) {
return ref;
}
// This may or may not succeed, which is ok because the object may already be gray.
- bool success = ref->AtomicSetReadBarrierState(ReadBarrier::WhiteState(),
- ReadBarrier::GrayState());
+ bool success = ref->AtomicSetReadBarrierState(/* expected_rb_state */ ReadBarrier::WhiteState(),
+ /* rb_state */ ReadBarrier::GrayState());
if (success) {
MutexLock mu(Thread::Current(), immune_gray_stack_lock_);
immune_gray_stack_.push_back(ref);
@@ -133,6 +134,8 @@ inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref,
// It isn't marked yet. Mark it by copying it to the to-space.
to_ref = Copy(from_ref, holder, offset);
}
+ // The copy should either be in a to-space region, or in the
+ // non-moving space, if it could not fit in a to-space region.
DCHECK(region_space_->IsInToSpace(to_ref) || heap_->non_moving_space_->HasAddress(to_ref))
<< "from_ref=" << from_ref << " to_ref=" << to_ref;
return to_ref;
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 1e0c0b16e4..3770085c07 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -347,8 +347,9 @@ class ConcurrentCopying::ThreadFlipVisitor : public Closure, public RootVisitor
// This must come before the revoke.
size_t thread_local_objects = thread->GetThreadLocalObjectsAllocated();
concurrent_copying_->region_space_->RevokeThreadLocalBuffers(thread);
- reinterpret_cast<Atomic<size_t>*>(&concurrent_copying_->from_space_num_objects_at_first_pause_)->
- FetchAndAddSequentiallyConsistent(thread_local_objects);
+ reinterpret_cast<Atomic<size_t>*>(
+ &concurrent_copying_->from_space_num_objects_at_first_pause_)->
+ FetchAndAddSequentiallyConsistent(thread_local_objects);
} else {
concurrent_copying_->region_space_->RevokeThreadLocalBuffers(thread);
}
@@ -440,7 +441,7 @@ class ConcurrentCopying::FlipCallback : public Closure {
if (kUseBakerReadBarrier && kGrayDirtyImmuneObjects) {
cc->GrayAllNewlyDirtyImmuneObjects();
if (kIsDebugBuild) {
- // Check that all non-gray immune objects only refernce immune objects.
+ // Check that all non-gray immune objects only reference immune objects.
cc->VerifyGrayImmuneObjects();
}
}
@@ -1534,7 +1535,8 @@ inline void ConcurrentCopying::ProcessMarkStackRef(mirror::Object* to_ref) {
!IsInToSpace(referent)))) {
// Leave this reference gray in the queue so that GetReferent() will trigger a read barrier. We
// will change it to white later in ReferenceQueue::DequeuePendingReference().
- DCHECK(to_ref->AsReference()->GetPendingNext() != nullptr) << "Left unenqueued ref gray " << to_ref;
+ DCHECK(to_ref->AsReference()->GetPendingNext() != nullptr)
+ << "Left unenqueued ref gray " << to_ref;
} else {
// We may occasionally leave a reference white in the queue if its referent happens to be
// concurrently marked after the Scan() call above has enqueued the Reference, in which case the
@@ -1552,7 +1554,7 @@ inline void ConcurrentCopying::ProcessMarkStackRef(mirror::Object* to_ref) {
#endif
if (add_to_live_bytes) {
- // Add to the live bytes per unevacuated from space. Note this code is always run by the
+ // Add to the live bytes per unevacuated from-space. Note this code is always run by the
// GC-running thread (no synchronization required).
DCHECK(region_space_bitmap_->Test(to_ref));
size_t obj_size = to_ref->SizeOf<kDefaultVerifyFlags>();
@@ -1759,13 +1761,14 @@ void ConcurrentCopying::ReclaimPhase() {
}
CHECK_LE(to_objects, from_objects);
CHECK_LE(to_bytes, from_bytes);
- // cleared_bytes and cleared_objects may be greater than the from space equivalents since
- // ClearFromSpace may clear empty unevac regions.
+ // Cleared bytes and objects, populated by the call to RegionSpace::ClearFromSpace below.
uint64_t cleared_bytes;
uint64_t cleared_objects;
{
TimingLogger::ScopedTiming split4("ClearFromSpace", GetTimings());
region_space_->ClearFromSpace(&cleared_bytes, &cleared_objects);
+ // `cleared_bytes` and `cleared_objects` may be greater than the from space equivalents since
+ // RegionSpace::ClearFromSpace may clear empty unevac regions.
CHECK_GE(cleared_bytes, from_bytes);
CHECK_GE(cleared_objects, from_objects);
}
@@ -1774,17 +1777,20 @@ void ConcurrentCopying::ReclaimPhase() {
if (kVerboseMode) {
LOG(INFO) << "RecordFree:"
<< " from_bytes=" << from_bytes << " from_objects=" << from_objects
- << " unevac_from_bytes=" << unevac_from_bytes << " unevac_from_objects=" << unevac_from_objects
+ << " unevac_from_bytes=" << unevac_from_bytes
+ << " unevac_from_objects=" << unevac_from_objects
<< " to_bytes=" << to_bytes << " to_objects=" << to_objects
<< " freed_bytes=" << freed_bytes << " freed_objects=" << freed_objects
<< " from_space size=" << region_space_->FromSpaceSize()
<< " unevac_from_space size=" << region_space_->UnevacFromSpaceSize()
<< " to_space size=" << region_space_->ToSpaceSize();
- LOG(INFO) << "(before) num_bytes_allocated=" << heap_->num_bytes_allocated_.LoadSequentiallyConsistent();
+ LOG(INFO) << "(before) num_bytes_allocated="
+ << heap_->num_bytes_allocated_.LoadSequentiallyConsistent();
}
RecordFree(ObjectBytePair(freed_objects, freed_bytes));
if (kVerboseMode) {
- LOG(INFO) << "(after) num_bytes_allocated=" << heap_->num_bytes_allocated_.LoadSequentiallyConsistent();
+ LOG(INFO) << "(after) num_bytes_allocated="
+ << heap_->num_bytes_allocated_.LoadSequentiallyConsistent();
}
}
@@ -1806,27 +1812,82 @@ void ConcurrentCopying::ReclaimPhase() {
}
}
-// Assert the to-space invariant.
+std::string ConcurrentCopying::DumpReferenceInfo(mirror::Object* ref,
+ const char* ref_name,
+ std::string indent) {
+ std::ostringstream oss;
+ oss << indent << heap_->GetVerification()->DumpObjectInfo(ref, ref_name) << '\n';
+ if (ref != nullptr) {
+ if (kUseBakerReadBarrier) {
+ oss << indent << ref_name << "->GetMarkBit()=" << ref->GetMarkBit() << '\n';
+ oss << indent << ref_name << "->GetReadBarrierState()=" << ref->GetReadBarrierState() << '\n';
+ }
+ }
+ if (region_space_->HasAddress(ref)) {
+ oss << indent << "Region containing " << ref_name << ":" << '\n';
+ region_space_->DumpRegionForObject(oss, ref);
+ if (region_space_bitmap_ != nullptr) {
+ oss << indent << "region_space_bitmap_->Test(" << ref_name << ")="
+ << std::boolalpha << region_space_bitmap_->Test(ref) << std::noboolalpha;
+ }
+ }
+ return oss.str();
+}
+
+std::string ConcurrentCopying::DumpHeapReference(mirror::Object* obj,
+ MemberOffset offset,
+ mirror::Object* ref) {
+ std::ostringstream oss;
+ std::string indent = " ";
+ oss << indent << "Invalid reference: ref=" << ref
+ << " referenced from: object=" << obj << " offset= " << offset << '\n';
+ // Information about `obj`.
+ oss << DumpReferenceInfo(obj, "obj", indent) << '\n';
+ // Information about `ref`.
+ oss << DumpReferenceInfo(ref, "ref", indent);
+ return oss.str();
+}
+
void ConcurrentCopying::AssertToSpaceInvariant(mirror::Object* obj,
MemberOffset offset,
mirror::Object* ref) {
- CHECK_EQ(heap_->collector_type_, kCollectorTypeCC);
+ CHECK_EQ(heap_->collector_type_, kCollectorTypeCC) << static_cast<size_t>(heap_->collector_type_);
if (is_asserting_to_space_invariant_) {
- using RegionType = space::RegionSpace::RegionType;
- space::RegionSpace::RegionType type = region_space_->GetRegionType(ref);
- if (type == RegionType::kRegionTypeToSpace) {
- // OK.
- return;
- } else if (type == RegionType::kRegionTypeUnevacFromSpace) {
- CHECK(IsMarkedInUnevacFromSpace(ref)) << ref;
- } else if (UNLIKELY(type == RegionType::kRegionTypeFromSpace)) {
- // Not OK. Do extra logging.
- if (obj != nullptr) {
- LogFromSpaceRefHolder(obj, offset);
+ if (region_space_->HasAddress(ref)) {
+ // Check to-space invariant in region space (moving space).
+ using RegionType = space::RegionSpace::RegionType;
+ space::RegionSpace::RegionType type = region_space_->GetRegionType(ref);
+ if (type == RegionType::kRegionTypeToSpace) {
+ // OK.
+ return;
+ } else if (type == RegionType::kRegionTypeUnevacFromSpace) {
+ if (!IsMarkedInUnevacFromSpace(ref)) {
+ LOG(FATAL_WITHOUT_ABORT) << "Found unmarked reference in unevac from-space:";
+ LOG(FATAL_WITHOUT_ABORT) << DumpHeapReference(obj, offset, ref);
+ }
+ CHECK(IsMarkedInUnevacFromSpace(ref)) << ref;
+ } else {
+ // Not OK: either a from-space ref or a reference in an unused region.
+ // Do extra logging.
+ if (type == RegionType::kRegionTypeFromSpace) {
+ LOG(FATAL_WITHOUT_ABORT) << "Found from-space reference:";
+ } else {
+ LOG(FATAL_WITHOUT_ABORT) << "Found reference in region with type " << type << ":";
+ }
+ LOG(FATAL_WITHOUT_ABORT) << DumpHeapReference(obj, offset, ref);
+ if (obj != nullptr) {
+ LogFromSpaceRefHolder(obj, offset);
+ }
+ ref->GetLockWord(false).Dump(LOG_STREAM(FATAL_WITHOUT_ABORT));
+ LOG(FATAL_WITHOUT_ABORT) << "Non-free regions:";
+ region_space_->DumpNonFreeRegions(LOG_STREAM(FATAL_WITHOUT_ABORT));
+ PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT);
+ MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true);
+ LOG(FATAL) << "Invalid reference " << ref
+ << " referenced from object " << obj << " at offset " << offset;
}
- ref->GetLockWord(false).Dump(LOG_STREAM(FATAL_WITHOUT_ABORT));
- CHECK(false) << "Found from-space ref " << ref << " " << ref->PrettyTypeOf();
} else {
+ // Check to-space invariant in non-moving space.
AssertToSpaceInvariantInNonMovingSpace(obj, ref);
}
}
@@ -1857,39 +1918,66 @@ class RootPrinter {
}
};
+std::string ConcurrentCopying::DumpGcRoot(mirror::Object* ref) {
+ std::ostringstream oss;
+ std::string indent = " ";
+ oss << indent << "Invalid GC root: ref=" << ref << '\n';
+ // Information about `ref`.
+ oss << DumpReferenceInfo(ref, "ref", indent);
+ return oss.str();
+}
+
void ConcurrentCopying::AssertToSpaceInvariant(GcRootSource* gc_root_source,
mirror::Object* ref) {
- CHECK(heap_->collector_type_ == kCollectorTypeCC) << static_cast<size_t>(heap_->collector_type_);
+ CHECK_EQ(heap_->collector_type_, kCollectorTypeCC) << static_cast<size_t>(heap_->collector_type_);
if (is_asserting_to_space_invariant_) {
- if (region_space_->IsInToSpace(ref)) {
- // OK.
- return;
- } else if (region_space_->IsInUnevacFromSpace(ref)) {
- CHECK(IsMarkedInUnevacFromSpace(ref)) << ref;
- } else if (region_space_->IsInFromSpace(ref)) {
- // Not OK. Do extra logging.
- if (gc_root_source == nullptr) {
- // No info.
- } else if (gc_root_source->HasArtField()) {
- ArtField* field = gc_root_source->GetArtField();
- LOG(FATAL_WITHOUT_ABORT) << "gc root in field " << field << " "
- << ArtField::PrettyField(field);
- RootPrinter root_printer;
- field->VisitRoots(root_printer);
- } else if (gc_root_source->HasArtMethod()) {
- ArtMethod* method = gc_root_source->GetArtMethod();
- LOG(FATAL_WITHOUT_ABORT) << "gc root in method " << method << " "
- << ArtMethod::PrettyMethod(method);
- RootPrinter root_printer;
- method->VisitRoots(root_printer, kRuntimePointerSize);
+ if (region_space_->HasAddress(ref)) {
+ // Check to-space invariant in region space (moving space).
+ using RegionType = space::RegionSpace::RegionType;
+ space::RegionSpace::RegionType type = region_space_->GetRegionType(ref);
+ if (type == RegionType::kRegionTypeToSpace) {
+ // OK.
+ return;
+ } else if (type == RegionType::kRegionTypeUnevacFromSpace) {
+ if (!IsMarkedInUnevacFromSpace(ref)) {
+ LOG(FATAL_WITHOUT_ABORT) << "Found unmarked reference in unevac from-space:";
+ LOG(FATAL_WITHOUT_ABORT) << DumpGcRoot(ref);
+ }
+ CHECK(IsMarkedInUnevacFromSpace(ref)) << ref;
+ } else {
+ // Not OK: either a from-space ref or a reference in an unused region.
+ // Do extra logging.
+ if (type == RegionType::kRegionTypeFromSpace) {
+ LOG(FATAL_WITHOUT_ABORT) << "Found from-space reference:";
+ } else {
+ LOG(FATAL_WITHOUT_ABORT) << "Found reference in region with type " << type << ":";
+ }
+ LOG(FATAL_WITHOUT_ABORT) << DumpGcRoot(ref);
+ if (gc_root_source == nullptr) {
+ // No info.
+ } else if (gc_root_source->HasArtField()) {
+ ArtField* field = gc_root_source->GetArtField();
+ LOG(FATAL_WITHOUT_ABORT) << "gc root in field " << field << " "
+ << ArtField::PrettyField(field);
+ RootPrinter root_printer;
+ field->VisitRoots(root_printer);
+ } else if (gc_root_source->HasArtMethod()) {
+ ArtMethod* method = gc_root_source->GetArtMethod();
+ LOG(FATAL_WITHOUT_ABORT) << "gc root in method " << method << " "
+ << ArtMethod::PrettyMethod(method);
+ RootPrinter root_printer;
+ method->VisitRoots(root_printer, kRuntimePointerSize);
+ }
+ ref->GetLockWord(false).Dump(LOG_STREAM(FATAL_WITHOUT_ABORT));
+ LOG(FATAL_WITHOUT_ABORT) << "Non-free regions:";
+ region_space_->DumpNonFreeRegions(LOG_STREAM(FATAL_WITHOUT_ABORT));
+ PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT);
+ MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true);
+ LOG(FATAL) << "Invalid reference " << ref;
}
- ref->GetLockWord(false).Dump(LOG_STREAM(FATAL_WITHOUT_ABORT));
- region_space_->DumpNonFreeRegions(LOG_STREAM(FATAL_WITHOUT_ABORT));
- PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT);
- MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true);
- CHECK(false) << "Found from-space ref " << ref << " " << ref->PrettyTypeOf();
} else {
- AssertToSpaceInvariantInNonMovingSpace(nullptr, ref);
+ // Check to-space invariant in non-moving space.
+ AssertToSpaceInvariantInNonMovingSpace(/* obj */ nullptr, ref);
}
}
}
@@ -1944,7 +2032,8 @@ void ConcurrentCopying::LogFromSpaceRefHolder(mirror::Object* obj, MemberOffset
void ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace(mirror::Object* obj,
mirror::Object* ref) {
- // In a non-moving spaces. Check that the ref is marked.
+ CHECK(!region_space_->HasAddress(ref)) << "obj=" << obj << " ref=" << ref;
+ // In a non-moving space. Check that the ref is marked.
if (immune_spaces_.ContainsObject(ref)) {
if (kUseBakerReadBarrier) {
// Immune object may not be gray if called from the GC.
@@ -1968,11 +2057,13 @@ void ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace(mirror::Object* o
(is_los && los_bitmap->Test(ref))) {
// OK.
} else {
- // If ref is on the allocation stack, then it may not be
+ // If `ref` is on the allocation stack, then it may not be
// marked live, but considered marked/alive (but not
// necessarily on the live stack).
- CHECK(IsOnAllocStack(ref)) << "Unmarked ref that's not on the allocation stack. "
- << "obj=" << obj << " ref=" << ref;
+ CHECK(IsOnAllocStack(ref)) << "Unmarked ref that's not on the allocation stack."
+ << " obj=" << obj
+ << " ref=" << ref
+ << " is_los=" << std::boolalpha << is_los << std::noboolalpha;
}
}
}
@@ -2013,7 +2104,6 @@ class ConcurrentCopying::RefFieldsVisitor {
ConcurrentCopying* const collector_;
};
-// Scan ref fields of an object.
inline void ConcurrentCopying::Scan(mirror::Object* to_ref) {
if (kDisallowReadBarrierDuringScan && !Runtime::Current()->IsActiveTransaction()) {
// Avoid all read barriers during visit references to help performance.
@@ -2032,7 +2122,6 @@ inline void ConcurrentCopying::Scan(mirror::Object* to_ref) {
}
}
-// Process a field.
inline void ConcurrentCopying::Process(mirror::Object* obj, MemberOffset offset) {
DCHECK_EQ(Thread::Current(), thread_running_gc_);
mirror::Object* ref = obj->GetFieldObject<
@@ -2053,7 +2142,7 @@ inline void ConcurrentCopying::Process(mirror::Object* obj, MemberOffset offset)
// It was updated by the mutator.
break;
}
- // Use release cas to make sure threads reading the reference see contents of copied objects.
+ // Use release CAS to make sure threads reading the reference see contents of copied objects.
} while (!obj->CasFieldWeakReleaseObjectWithoutWriteBarrier<false, false, kVerifyNone>(
offset,
expected_ref,
@@ -2428,6 +2517,9 @@ mirror::Object* ConcurrentCopying::IsMarked(mirror::Object* from_ref) {
to_ref = nullptr;
}
} else {
+ // At this point, `from_ref` should not be in the region space
+ // (i.e. within an "unused" region).
+ DCHECK(!region_space_->HasAddress(from_ref)) << from_ref;
// from_ref is in a non-moving space.
if (immune_spaces_.ContainsObject(from_ref)) {
// An immune object is alive.
@@ -2598,7 +2690,12 @@ void ConcurrentCopying::FinishPhase() {
DCHECK(rb_mark_bit_stack_ != nullptr);
const auto* limit = rb_mark_bit_stack_->End();
for (StackReference<mirror::Object>* it = rb_mark_bit_stack_->Begin(); it != limit; ++it) {
- CHECK(it->AsMirrorPtr()->AtomicSetMarkBit(1, 0));
+ CHECK(it->AsMirrorPtr()->AtomicSetMarkBit(1, 0))
+ << "rb_mark_bit_stack_->Begin()" << rb_mark_bit_stack_->Begin() << '\n'
+ << "rb_mark_bit_stack_->End()" << rb_mark_bit_stack_->End() << '\n'
+ << "rb_mark_bit_stack_->IsFull()"
+ << std::boolalpha << rb_mark_bit_stack_->IsFull() << std::noboolalpha << '\n'
+ << DumpReferenceInfo(it->AsMirrorPtr(), "*it");
}
rb_mark_bit_stack_->Reset();
}
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index 8b4b58e7b1..c58dd44648 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -100,8 +100,10 @@ class ConcurrentCopying : public GarbageCollector {
space::RegionSpace* RegionSpace() {
return region_space_;
}
+ // Assert the to-space invariant for a heap reference `ref` held in `obj` at offset `offset`.
void AssertToSpaceInvariant(mirror::Object* obj, MemberOffset offset, mirror::Object* ref)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Assert the to-space invariant for a GC root reference `ref`.
void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref)
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsInToSpace(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -109,6 +111,7 @@ class ConcurrentCopying : public GarbageCollector {
return IsMarked(ref) == ref;
}
template<bool kGrayImmuneObject = true, bool kFromGCThread = false>
+ // Mark object `from_ref`, copying it to the to-space if needed.
ALWAYS_INLINE mirror::Object* Mark(mirror::Object* from_ref,
mirror::Object* holder = nullptr,
MemberOffset offset = MemberOffset(0))
@@ -148,8 +151,10 @@ class ConcurrentCopying : public GarbageCollector {
MemberOffset offset)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
+ // Scan the reference fields of object `to_ref`.
void Scan(mirror::Object* to_ref) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_);
+ // Process a field.
void Process(mirror::Object* obj, MemberOffset offset)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_ , !skipped_blocks_lock_, !immune_gray_stack_lock_);
@@ -232,6 +237,16 @@ class ConcurrentCopying : public GarbageCollector {
void ComputeUnevacFromSpaceLiveRatio();
void LogFromSpaceRefHolder(mirror::Object* obj, MemberOffset offset)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Dump information about reference `ref` and return it as a string.
+ // Use `ref_name` to name the reference in messages. Each message is prefixed with `indent`.
+ std::string DumpReferenceInfo(mirror::Object* ref, const char* ref_name, std::string indent = "")
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Dump information about heap reference `ref`, referenced from object `obj` at offset `offset`,
+ // and return it as a string.
+ std::string DumpHeapReference(mirror::Object* obj, MemberOffset offset, mirror::Object* ref)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Dump information about GC root `ref` and return it as a string.
+ std::string DumpGcRoot(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
void AssertToSpaceInvariantInNonMovingSpace(mirror::Object* obj, mirror::Object* ref)
REQUIRES_SHARED(Locks::mutator_lock_);
void ReenableWeakRefAccess(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -266,8 +281,20 @@ class ConcurrentCopying : public GarbageCollector {
space::RegionSpace* region_space_; // The underlying region space.
std::unique_ptr<Barrier> gc_barrier_;
std::unique_ptr<accounting::ObjectStack> gc_mark_stack_;
+
+ // The read-barrier mark-bit stack. Stores object references whose
+ // mark bit has been set by ConcurrentCopying::MarkFromReadBarrier,
+ // so that this bit can be reset at the end of the collection in
+ // ConcurrentCopying::FinishPhase. The mark bit of an object can be
+ // used by mutator read barrier code to quickly test whether that
+ // object has been already marked.
std::unique_ptr<accounting::ObjectStack> rb_mark_bit_stack_;
+ // Thread-unsafe Boolean value hinting that `rb_mark_bit_stack_` is
+ // full. A thread-safe test of whether the read-barrier mark-bit
+ // stack is full is implemented by `rb_mark_bit_stack_->AtomicPushBack(ref)`
+ // (see use case in ConcurrentCopying::MarkFromReadBarrier).
bool rb_mark_bit_stack_full_;
+
std::vector<mirror::Object*> false_gray_stack_ GUARDED_BY(mark_stack_lock_);
Mutex mark_stack_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
std::vector<accounting::ObjectStack*> revoked_mark_stacks_
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index fdfe949265..9ab965ec78 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -191,7 +191,7 @@ void MarkSweep::PausePhase() {
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
// Re-mark root set.
ReMarkRoots();
- // Scan dirty objects, this is only required if we are not doing concurrent GC.
+ // Scan dirty objects, this is only required if we are doing concurrent GC.
RecursiveMarkDirtyObjects(true, accounting::CardTable::kCardDirty);
}
{
@@ -259,8 +259,30 @@ void MarkSweep::MarkingPhase() {
BindBitmaps();
FindDefaultSpaceBitmap();
// Process dirty cards and add dirty cards to mod union tables.
- // If the GC type is non sticky, then we just clear the cards instead of ageing them.
- heap_->ProcessCards(GetTimings(), false, true, GetGcType() != kGcTypeSticky);
+ // If the GC type is non sticky, then we just clear the cards of the
+ // alloc space instead of aging them.
+ //
+ // Note that it is fine to clear the cards of the alloc space here,
+ // in the case of a concurrent (non-sticky) mark-sweep GC (whose
+ // marking phase _is_ performed concurrently with mutator threads
+ // running and possibly dirtying cards), as the whole alloc space
+ // will be traced in that case, starting *after* this call to
+ // Heap::ProcessCards (see calls to MarkSweep::MarkRoots and
+ // MarkSweep::MarkReachableObjects). References held by objects on
+ // cards that became dirty *after* the actual marking work started
+ // will be marked in the pause (see MarkSweep::PausePhase), in a
+ // *non-concurrent* way to prevent races with mutator threads.
+ //
+ // TODO: Do we need some sort of fence between the call to
+ // Heap::ProcessCard and the calls to MarkSweep::MarkRoot /
+ // MarkSweep::MarkReachableObjects below to make sure write
+ // operations in the card table clearing the alloc space's dirty
+ // cards (during the call to Heap::ProcessCard) are not reordered
+ // *after* marking actually starts?
+ heap_->ProcessCards(GetTimings(),
+ /* use_rem_sets */ false,
+ /* process_alloc_space_cards */ true,
+ /* clear_alloc_space_cards */ GetGcType() != kGcTypeSticky);
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
MarkRoots(self);
MarkReachableObjects();
@@ -1287,7 +1309,7 @@ void MarkSweep::Sweep(bool swap_bitmaps) {
CHECK_GE(live_stack_freeze_size_, GetHeap()->GetLiveStack()->Size());
{
TimingLogger::ScopedTiming t2("MarkAllocStackAsLive", GetTimings());
- // Mark everything allocated since the last as GC live so that we can sweep concurrently,
+ // Mark everything allocated since the last GC as live so that we can sweep concurrently,
// knowing that new allocations won't be marked as live.
accounting::ObjectStack* live_stack = heap_->GetLiveStack();
heap_->MarkAllocStackAsLive(live_stack);
diff --git a/runtime/gc/collector/sticky_mark_sweep.cc b/runtime/gc/collector/sticky_mark_sweep.cc
index b66095fc2a..d93bd89835 100644
--- a/runtime/gc/collector/sticky_mark_sweep.cc
+++ b/runtime/gc/collector/sticky_mark_sweep.cc
@@ -63,7 +63,7 @@ void StickyMarkSweep::MarkReachableObjects() {
void StickyMarkSweep::MarkConcurrentRoots(VisitRootFlags flags) {
TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
// Visit all runtime roots and clear dirty flags including class loader. This is done to prevent
- // incorrect class unloading since the GC does not card mark when storing store the class during
+ // incorrect class unloading since the GC does not card mark when storing the class during
// object allocation. Doing this for each allocation would be slow.
// Since the card is not dirty, it means the object may not get scanned. This can cause class
// unloading to occur even though the class and class loader are reachable through the object's
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 84671c34b5..17913fc2dc 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -434,6 +434,7 @@ Heap::Heap(size_t initial_size,
// Create other spaces based on whether or not we have a moving GC.
if (foreground_collector_type_ == kCollectorTypeCC) {
CHECK(separate_non_moving_space);
+ // Reserve twice the capacity, to allow evacuating every region for explicit GCs.
MemMap* region_space_mem_map = space::RegionSpace::CreateMemMap(kRegionSpaceName,
capacity_ * 2,
request_begin);
@@ -517,7 +518,7 @@ Heap::Heap(size_t initial_size,
// Since we don't know where in the low_4gb the app image will be located, make the card table
// cover the whole low_4gb. TODO: Extend the card table in AddSpace.
UNUSED(heap_capacity);
- // Start at 64 KB, we can be sure there are no spaces mapped this low since the address range is
+ // Start at 4 KB, we can be sure there are no spaces mapped this low since the address range is
// reserved by the kernel.
static constexpr size_t kMinHeapAddress = 4 * KB;
card_table_.reset(accounting::CardTable::Create(reinterpret_cast<uint8_t*>(kMinHeapAddress),
@@ -1536,7 +1537,7 @@ void Heap::RecordFree(uint64_t freed_objects, int64_t freed_bytes) {
void Heap::RecordFreeRevoke() {
// Subtract num_bytes_freed_revoke_ from num_bytes_allocated_ to cancel out the
- // the ahead-of-time, bulk counting of bytes allocated in rosalloc thread-local buffers.
+ // ahead-of-time, bulk counting of bytes allocated in rosalloc thread-local buffers.
// If there's a concurrent revoke, ok to not necessarily reset num_bytes_freed_revoke_
// all the way to zero exactly as the remainder will be subtracted at the next GC.
size_t bytes_freed = num_bytes_freed_revoke_.LoadSequentiallyConsistent();
@@ -1758,7 +1759,7 @@ void Heap::SetTargetHeapUtilization(float target) {
size_t Heap::GetObjectsAllocated() const {
Thread* const self = Thread::Current();
ScopedThreadStateChange tsc(self, kWaitingForGetObjectsAllocated);
- // Prevent GC running during GetObjectsALlocated since we may get a checkpoint request that tells
+ // Prevent GC running during GetObjectsAllocated since we may get a checkpoint request that tells
// us to suspend while we are doing SuspendAll. b/35232978
gc::ScopedGCCriticalSection gcs(Thread::Current(),
gc::kGcCauseGetObjectsAllocated,
@@ -1899,10 +1900,10 @@ HomogeneousSpaceCompactResult Heap::PerformHomogeneousSpaceCompact() {
MutexLock mu(self, *gc_complete_lock_);
// Ensure there is only one GC at a time.
WaitForGcToCompleteLocked(kGcCauseHomogeneousSpaceCompact, self);
- // Homogeneous space compaction is a copying transition, can't run it if the moving GC disable count
- // is non zero.
- // If the collector type changed to something which doesn't benefit from homogeneous space compaction,
- // exit.
+ // Homogeneous space compaction is a copying transition, can't run it if the moving GC disable
+ // count is non zero.
+ // If the collector type changed to something which doesn't benefit from homogeneous space
+ // compaction, exit.
if (disable_moving_gc_count_ != 0 || IsMovingGc(collector_type_) ||
!main_space_->CanMoveObjects()) {
return kErrorReject;
@@ -3445,8 +3446,8 @@ void Heap::GrowForUtilization(collector::GarbageCollector* collector_ran,
TraceHeapSize(bytes_allocated);
uint64_t target_size;
collector::GcType gc_type = collector_ran->GetGcType();
- const double multiplier = HeapGrowthMultiplier(); // Use the multiplier to grow more for
- // foreground.
+ // Use the multiplier to grow more for foreground.
+ const double multiplier = HeapGrowthMultiplier();
const uint64_t adjusted_min_free = static_cast<uint64_t>(min_free_ * multiplier);
const uint64_t adjusted_max_free = static_cast<uint64_t>(max_free_ * multiplier);
if (gc_type != collector::kGcTypeSticky) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index faa6195259..7fb634fcf7 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -551,7 +551,7 @@ class Heap {
return total_memory - std::min(total_memory, byte_allocated);
}
- // get the space that corresponds to an object's address. Current implementation searches all
+ // Get the space that corresponds to an object's address. Current implementation searches all
// spaces in turn. If fail_ok is false then failing to find a space will cause an abort.
// TODO: consider using faster data structure like binary tree.
space::ContinuousSpace* FindContinuousSpaceFromObject(ObjPtr<mirror::Object>, bool fail_ok) const
@@ -1293,8 +1293,9 @@ class Heap {
// Parallel GC data structures.
std::unique_ptr<ThreadPool> thread_pool_;
- // For a GC cycle, a bitmap that is set corresponding to the
+ // A bitmap that is set corresponding to the known live objects since the last GC cycle.
std::unique_ptr<accounting::HeapBitmap> live_bitmap_ GUARDED_BY(Locks::heap_bitmap_lock_);
+ // A bitmap that is set corresponding to the marked objects in the current GC cycle.
std::unique_ptr<accounting::HeapBitmap> mark_bitmap_ GUARDED_BY(Locks::heap_bitmap_lock_);
// Mark stack that we reuse to avoid re-allocating the mark stack.
@@ -1312,7 +1313,7 @@ class Heap {
AllocatorType current_allocator_;
const AllocatorType current_non_moving_allocator_;
- // Which GCs we run in order when we an allocation fails.
+ // Which GCs we run in order when an allocation fails.
std::vector<collector::GcType> gc_plan_;
// Bump pointer spaces.
@@ -1320,6 +1321,7 @@ class Heap {
// Temp space is the space which the semispace collector copies to.
space::BumpPointerSpace* temp_space_;
+ // Region space, used by the concurrent collector.
space::RegionSpace* region_space_;
// Minimum free guarantees that you always have at least min_free_ free bytes after growing for
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 9d8e5d23eb..6d426c2dd0 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -81,7 +81,6 @@ class ZygoteHeapTest : public CommonRuntimeTest {
void SetUpRuntimeOptions(RuntimeOptions* options) {
CommonRuntimeTest::SetUpRuntimeOptions(options);
options->push_back(std::make_pair("-Xzygote", nullptr));
- options->push_back(std::make_pair("-Xno-hidden-api-checks", nullptr));
}
};
diff --git a/runtime/gc/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h
index e74e9b169f..410931cbe5 100644
--- a/runtime/gc/space/region_space-inl.h
+++ b/runtime/gc/space/region_space-inl.h
@@ -24,26 +24,30 @@ namespace art {
namespace gc {
namespace space {
-inline mirror::Object* RegionSpace::Alloc(Thread*, size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) {
+inline mirror::Object* RegionSpace::Alloc(Thread* self ATTRIBUTE_UNUSED,
+ size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) {
num_bytes = RoundUp(num_bytes, kAlignment);
return AllocNonvirtual<false>(num_bytes, bytes_allocated, usable_size,
bytes_tl_bulk_allocated);
}
-inline mirror::Object* RegionSpace::AllocThreadUnsafe(Thread* self, size_t num_bytes,
- size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) {
+inline mirror::Object* RegionSpace::AllocThreadUnsafe(Thread* self,
+ size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) {
Locks::mutator_lock_->AssertExclusiveHeld(self);
return Alloc(self, num_bytes, bytes_allocated, usable_size, bytes_tl_bulk_allocated);
}
template<bool kForEvac>
-inline mirror::Object* RegionSpace::AllocNonvirtual(size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) {
+inline mirror::Object* RegionSpace::AllocNonvirtual(size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) {
DCHECK_ALIGNED(num_bytes, kAlignment);
mirror::Object* obj;
if (LIKELY(num_bytes <= kRegionSize)) {
@@ -79,8 +83,7 @@ inline mirror::Object* RegionSpace::AllocNonvirtual(size_t num_bytes, size_t* by
}
} else {
// Large object.
- obj = AllocLarge<kForEvac>(num_bytes, bytes_allocated, usable_size,
- bytes_tl_bulk_allocated);
+ obj = AllocLarge<kForEvac>(num_bytes, bytes_allocated, usable_size, bytes_tl_bulk_allocated);
if (LIKELY(obj != nullptr)) {
return obj;
}
@@ -88,9 +91,10 @@ inline mirror::Object* RegionSpace::AllocNonvirtual(size_t num_bytes, size_t* by
return nullptr;
}
-inline mirror::Object* RegionSpace::Region::Alloc(size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) {
+inline mirror::Object* RegionSpace::Region::Alloc(size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) {
DCHECK(IsAllocated() && IsInToSpace());
DCHECK_ALIGNED(num_bytes, kAlignment);
uint8_t* old_top;
@@ -238,9 +242,9 @@ inline mirror::Object* RegionSpace::GetNextObject(mirror::Object* obj) {
template<bool kForEvac>
inline mirror::Object* RegionSpace::AllocLarge(size_t num_bytes,
- size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) {
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) {
DCHECK_ALIGNED(num_bytes, kAlignment);
DCHECK_GT(num_bytes, kRegionSize);
size_t num_regs = RoundUp(num_bytes, kRegionSize) / kRegionSize;
@@ -254,7 +258,7 @@ inline mirror::Object* RegionSpace::AllocLarge(size_t num_bytes,
return nullptr;
}
}
- // Find a large enough contiguous free regions.
+ // Find a large enough set of contiguous free regions.
size_t left = 0;
while (left + num_regs - 1 < num_regions_) {
bool found = true;
@@ -270,7 +274,7 @@ inline mirror::Object* RegionSpace::AllocLarge(size_t num_bytes,
}
}
if (found) {
- // right points to the one region past the last free region.
+ // `right` points to the one region past the last free region.
DCHECK_EQ(left + num_regs, right);
Region* first_reg = &regions_[left];
DCHECK(first_reg->IsFree());
@@ -345,7 +349,7 @@ inline size_t RegionSpace::Region::BytesAllocated() const {
DCHECK_EQ(begin_, Top());
return 0;
} else {
- DCHECK(IsAllocated()) << static_cast<uint>(state_);
+ DCHECK(IsAllocated()) << "state=" << state_;
DCHECK_LE(begin_, Top());
size_t bytes;
if (is_a_tlab_) {
@@ -358,6 +362,20 @@ inline size_t RegionSpace::Region::BytesAllocated() const {
}
}
+inline size_t RegionSpace::Region::ObjectsAllocated() const {
+ if (IsLarge()) {
+ DCHECK_LT(begin_ + kRegionSize, Top());
+ DCHECK_EQ(objects_allocated_.LoadRelaxed(), 0U);
+ return 1;
+ } else if (IsLargeTail()) {
+ DCHECK_EQ(begin_, Top());
+ DCHECK_EQ(objects_allocated_.LoadRelaxed(), 0U);
+ return 0;
+ } else {
+ DCHECK(IsAllocated()) << "state=" << state_;
+ return objects_allocated_;
+ }
+}
} // namespace space
} // namespace gc
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index a505f32c49..8d94c86701 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -27,7 +27,7 @@ namespace space {
// If a region has live objects whose size is less than this percent
// value of the region size, evaculate the region.
-static constexpr uint kEvaculateLivePercentThreshold = 75U;
+static constexpr uint kEvacuateLivePercentThreshold = 75U;
// If we protect the cleared regions.
// Only protect for target builds to prevent flaky test failures (b/63131961).
@@ -158,14 +158,14 @@ size_t RegionSpace::ToSpaceSize() {
inline bool RegionSpace::Region::ShouldBeEvacuated() {
DCHECK((IsAllocated() || IsLarge()) && IsInToSpace());
- // if the region was allocated after the start of the
- // previous GC or the live ratio is below threshold, evacuate
- // it.
+ // The region should be evacuated if:
+ // - the region was allocated after the start of the previous GC (newly allocated region); or
+ // - the live ratio is below threshold (`kEvacuateLivePercentThreshold`).
bool result;
if (is_newly_allocated_) {
result = true;
} else {
- bool is_live_percent_valid = live_bytes_ != static_cast<size_t>(-1);
+ bool is_live_percent_valid = (live_bytes_ != static_cast<size_t>(-1));
if (is_live_percent_valid) {
DCHECK(IsInToSpace());
DCHECK(!IsLargeTail());
@@ -177,10 +177,10 @@ inline bool RegionSpace::Region::ShouldBeEvacuated() {
// Side node: live_percent == 0 does not necessarily mean
// there's no live objects due to rounding (there may be a
// few).
- result = live_bytes_ * 100U < kEvaculateLivePercentThreshold * bytes_allocated;
+ result = (live_bytes_ * 100U < kEvacuateLivePercentThreshold * bytes_allocated);
} else {
DCHECK(IsLarge());
- result = live_bytes_ == 0U;
+ result = (live_bytes_ == 0U);
}
} else {
result = false;
@@ -198,7 +198,10 @@ void RegionSpace::SetFromSpace(accounting::ReadBarrierTable* rb_table, bool forc
rb_table->SetAll();
}
MutexLock mu(Thread::Current(), region_lock_);
- size_t num_expected_large_tails = 0;
+ // Counter for the number of expected large tail regions following a large region.
+ size_t num_expected_large_tails = 0U;
+ // Flag to store whether the previously seen large region has been evacuated.
+ // This is used to apply the same evacuation policy to related large tail regions.
bool prev_large_evacuated = false;
VerifyNonFreeRegionLimit();
const size_t iter_limit = kUseTableLookupReadBarrier
@@ -260,7 +263,8 @@ static void ZeroAndProtectRegion(uint8_t* begin, uint8_t* end) {
}
}
-void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_objects) {
+void RegionSpace::ClearFromSpace(/* out */ uint64_t* cleared_bytes,
+ /* out */ uint64_t* cleared_objects) {
DCHECK(cleared_bytes != nullptr);
DCHECK(cleared_objects != nullptr);
*cleared_bytes = 0;
@@ -272,18 +276,32 @@ void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_obje
// Update max of peak non free region count before reclaiming evacuated regions.
max_peak_num_non_free_regions_ = std::max(max_peak_num_non_free_regions_,
num_non_free_regions_);
- // Combine zeroing and releasing pages to reduce how often madvise is called. This helps
- // reduce contention on the mmap semaphore. b/62194020
- // clear_region adds a region to the current block. If the region is not adjacent, the
- // clear block is zeroed, released, and a new block begins.
+
+ // Lambda expression `clear_region` clears a region and adds a region to the
+ // "clear block".
+ //
+ // As we sweep regions to clear them, we maintain a "clear block", composed of
+ // adjacent cleared regions and whose bounds are `clear_block_begin` and
+ // `clear_block_end`. When processing a new region which is not adjacent to
+ // the clear block (discontinuity in cleared regions), the clear block
+ // is zeroed and released and the clear block is reset (to the most recent
+ // cleared region).
+ //
+ // This is done in order to combine zeroing and releasing pages to reduce how
+ // often madvise is called. This helps reduce contention on the mmap semaphore
+ // (see b/62194020).
uint8_t* clear_block_begin = nullptr;
uint8_t* clear_block_end = nullptr;
auto clear_region = [&clear_block_begin, &clear_block_end](Region* r) {
r->Clear(/*zero_and_release_pages*/false);
if (clear_block_end != r->Begin()) {
+ // Region `r` is not adjacent to the current clear block; zero and release
+ // pages within the current block and restart a new clear block at the
+ // beginning of region `r`.
ZeroAndProtectRegion(clear_block_begin, clear_block_end);
clear_block_begin = r->Begin();
}
+ // Add region `r` to the clear block.
clear_block_end = r->End();
};
for (size_t i = 0; i < std::min(num_regions_, non_free_region_index_limit_); ++i) {
@@ -334,12 +352,22 @@ void RegionSpace::ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_obje
++regions_to_clear_bitmap;
}
+ // Optimization: If the live bytes are *all* live in a region
+ // then the live-bit information for these objects is superfluous:
+ // - We can determine that these objects are all live by using
+ // Region::AllAllocatedBytesAreLive (which just checks whether
+ // `LiveBytes() == static_cast<size_t>(Top() - Begin())`.
+ // - We can visit the objects in this region using
+ // RegionSpace::GetNextObject, i.e. without resorting to the
+ // live bits (see RegionSpace::WalkInternal).
+ // Therefore, we can clear the bits for these objects in the
+ // (live) region space bitmap (and release the corresponding pages).
GetLiveBitmap()->ClearRange(
reinterpret_cast<mirror::Object*>(r->Begin()),
reinterpret_cast<mirror::Object*>(r->Begin() + regions_to_clear_bitmap * kRegionSize));
- // Skip over extra regions we cleared the bitmaps: we don't need to clear them, as they
- // are unevac region sthat are live.
- // Subtract one for the for loop.
+ // Skip over extra regions for which we cleared the bitmaps: we shall not clear them,
+ // as they are unevac regions that are live.
+ // Subtract one for the for-loop.
i += regions_to_clear_bitmap - 1;
}
}
@@ -432,7 +460,13 @@ void RegionSpace::ClampGrowthLimit(size_t new_capacity) {
void RegionSpace::Dump(std::ostream& os) const {
os << GetName() << " "
- << reinterpret_cast<void*>(Begin()) << "-" << reinterpret_cast<void*>(Limit());
+ << reinterpret_cast<void*>(Begin()) << "-" << reinterpret_cast<void*>(Limit());
+}
+
+void RegionSpace::DumpRegionForObject(std::ostream& os, mirror::Object* obj) {
+ CHECK(HasAddress(obj));
+ MutexLock mu(Thread::Current(), region_lock_);
+ RefToRegionUnlocked(obj)->Dump(os);
}
void RegionSpace::DumpRegions(std::ostream& os) {
@@ -526,13 +560,18 @@ void RegionSpace::AssertAllThreadLocalBuffersAreRevoked() {
}
void RegionSpace::Region::Dump(std::ostream& os) const {
- os << "Region[" << idx_ << "]=" << reinterpret_cast<void*>(begin_) << "-"
- << reinterpret_cast<void*>(Top())
+ os << "Region[" << idx_ << "]="
+ << reinterpret_cast<void*>(begin_)
+ << "-" << reinterpret_cast<void*>(Top())
<< "-" << reinterpret_cast<void*>(end_)
- << " state=" << static_cast<uint>(state_) << " type=" << static_cast<uint>(type_)
+ << " state=" << state_
+ << " type=" << type_
<< " objects_allocated=" << objects_allocated_
- << " alloc_time=" << alloc_time_ << " live_bytes=" << live_bytes_
- << " is_newly_allocated=" << is_newly_allocated_ << " is_a_tlab=" << is_a_tlab_ << " thread=" << thread_ << "\n";
+ << " alloc_time=" << alloc_time_
+ << " live_bytes=" << live_bytes_
+ << " is_newly_allocated=" << std::boolalpha << is_newly_allocated_ << std::noboolalpha
+ << " is_a_tlab=" << std::boolalpha << is_a_tlab_ << std::noboolalpha
+ << " thread=" << thread_ << '\n';
}
size_t RegionSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index 55c2772129..c3b7ff72ef 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -46,24 +46,33 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
static MemMap* CreateMemMap(const std::string& name, size_t capacity, uint8_t* requested_begin);
static RegionSpace* Create(const std::string& name, MemMap* mem_map);
- // Allocate num_bytes, returns null if the space is full.
- mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size, size_t* bytes_tl_bulk_allocated)
+ // Allocate `num_bytes`, returns null if the space is full.
+ mirror::Object* Alloc(Thread* self,
+ size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated)
OVERRIDE REQUIRES(!region_lock_);
// Thread-unsafe allocation for when mutators are suspended, used by the semispace collector.
- mirror::Object* AllocThreadUnsafe(Thread* self, size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size, size_t* bytes_tl_bulk_allocated)
+ mirror::Object* AllocThreadUnsafe(Thread* self,
+ size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated)
OVERRIDE REQUIRES(Locks::mutator_lock_) REQUIRES(!region_lock_);
// The main allocation routine.
template<bool kForEvac>
- ALWAYS_INLINE mirror::Object* AllocNonvirtual(size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated)
+ ALWAYS_INLINE mirror::Object* AllocNonvirtual(size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated)
REQUIRES(!region_lock_);
- // Allocate/free large objects (objects that are larger than the region size.)
+ // Allocate/free large objects (objects that are larger than the region size).
template<bool kForEvac>
- mirror::Object* AllocLarge(size_t num_bytes, size_t* bytes_allocated, size_t* usable_size,
- size_t* bytes_tl_bulk_allocated) REQUIRES(!region_lock_);
+ mirror::Object* AllocLarge(size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated) REQUIRES(!region_lock_);
template<bool kForEvac>
void FreeLarge(mirror::Object* large_obj, size_t bytes_allocated) REQUIRES(!region_lock_);
@@ -101,6 +110,8 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
void Dump(std::ostream& os) const;
void DumpRegions(std::ostream& os) REQUIRES(!region_lock_);
+ // Dump region containing object `obj`. Precondition: `obj` is in the region space.
+ void DumpRegionForObject(std::ostream& os, mirror::Object* obj) REQUIRES(!region_lock_);
void DumpNonFreeRegions(std::ostream& os) REQUIRES(!region_lock_);
size_t RevokeThreadLocalBuffers(Thread* thread) REQUIRES(!region_lock_);
@@ -174,7 +185,7 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
template <typename Visitor>
ALWAYS_INLINE void WalkToSpace(Visitor&& visitor)
REQUIRES(Locks::mutator_lock_) {
- WalkInternal<true>(visitor);
+ WalkInternal<true /* kToSpaceOnly */>(visitor);
}
accounting::ContinuousSpaceBitmap::SweepCallback* GetSweepCallback() OVERRIDE {
@@ -228,13 +239,16 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
return RegionType::kRegionTypeNone;
}
+ // Determine which regions to evacuate and tag them as
+ // from-space. Tag the rest as unevacuated from-space.
void SetFromSpace(accounting::ReadBarrierTable* rb_table, bool force_evacuate_all)
REQUIRES(!region_lock_);
size_t FromSpaceSize() REQUIRES(!region_lock_);
size_t UnevacFromSpaceSize() REQUIRES(!region_lock_);
size_t ToSpaceSize() REQUIRES(!region_lock_);
- void ClearFromSpace(uint64_t* cleared_bytes, uint64_t* cleared_objects) REQUIRES(!region_lock_);
+ void ClearFromSpace(/* out */ uint64_t* cleared_bytes, /* out */ uint64_t* cleared_objects)
+ REQUIRES(!region_lock_);
void AddLiveBytes(mirror::Object* ref, size_t alloc_size) {
Region* reg = RefToRegionUnlocked(ref);
@@ -301,12 +315,13 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
void Clear(bool zero_and_release_pages);
- ALWAYS_INLINE mirror::Object* Alloc(size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated);
+ ALWAYS_INLINE mirror::Object* Alloc(size_t num_bytes,
+ /* out */ size_t* bytes_allocated,
+ /* out */ size_t* usable_size,
+ /* out */ size_t* bytes_tl_bulk_allocated);
bool IsFree() const {
- bool is_free = state_ == RegionState::kRegionStateFree;
+ bool is_free = (state_ == RegionState::kRegionStateFree);
if (is_free) {
DCHECK(IsInNoSpace());
DCHECK_EQ(begin_, Top());
@@ -319,9 +334,11 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
void Unfree(RegionSpace* region_space, uint32_t alloc_time)
REQUIRES(region_space->region_lock_);
+ // Given a free region, declare it non-free (allocated) and large.
void UnfreeLarge(RegionSpace* region_space, uint32_t alloc_time)
REQUIRES(region_space->region_lock_);
+ // Given a free region, declare it non-free (allocated) and large tail.
void UnfreeLargeTail(RegionSpace* region_space, uint32_t alloc_time)
REQUIRES(region_space->region_lock_);
@@ -339,7 +356,7 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
// Large allocated.
bool IsLarge() const {
- bool is_large = state_ == RegionState::kRegionStateLarge;
+ bool is_large = (state_ == RegionState::kRegionStateLarge);
if (is_large) {
DCHECK_LT(begin_ + kRegionSize, Top());
}
@@ -348,7 +365,7 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
// Large-tail allocated.
bool IsLargeTail() const {
- bool is_large_tail = state_ == RegionState::kRegionStateLargeTail;
+ bool is_large_tail = (state_ == RegionState::kRegionStateLargeTail);
if (is_large_tail) {
DCHECK_EQ(begin_, Top());
}
@@ -379,23 +396,33 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
return type_ == RegionType::kRegionTypeNone;
}
+ // Set this region as evacuated from-space. At the end of the
+ // collection, RegionSpace::ClearFromSpace will clear and reclaim
+ // the space used by this region, and tag it as unallocated/free.
void SetAsFromSpace() {
DCHECK(!IsFree() && IsInToSpace());
type_ = RegionType::kRegionTypeFromSpace;
live_bytes_ = static_cast<size_t>(-1);
}
+ // Set this region as unevacuated from-space. At the end of the
+ // collection, RegionSpace::ClearFromSpace will preserve the space
+ // used by this region, and tag it as to-space (see
+ // Region::SetUnevacFromSpaceAsToSpace below).
void SetAsUnevacFromSpace() {
DCHECK(!IsFree() && IsInToSpace());
type_ = RegionType::kRegionTypeUnevacFromSpace;
live_bytes_ = 0U;
}
+ // Set this region as to-space. Used by RegionSpace::ClearFromSpace.
+ // This is only valid if it is currently an unevac from-space region.
void SetUnevacFromSpaceAsToSpace() {
DCHECK(!IsFree() && IsInUnevacFromSpace());
type_ = RegionType::kRegionTypeToSpace;
}
+ // Return whether this region should be evacuated. Used by RegionSpace::SetFromSpace.
ALWAYS_INLINE bool ShouldBeEvacuated();
void AddLiveBytes(size_t live_bytes) {
@@ -418,20 +445,7 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
size_t BytesAllocated() const;
- size_t ObjectsAllocated() const {
- if (IsLarge()) {
- DCHECK_LT(begin_ + kRegionSize, Top());
- DCHECK_EQ(objects_allocated_.LoadRelaxed(), 0U);
- return 1;
- } else if (IsLargeTail()) {
- DCHECK_EQ(begin_, Top());
- DCHECK_EQ(objects_allocated_.LoadRelaxed(), 0U);
- return 0;
- } else {
- DCHECK(IsAllocated()) << static_cast<uint>(state_);
- return objects_allocated_;
- }
- }
+ size_t ObjectsAllocated() const;
uint8_t* Begin() const {
return begin_;
@@ -467,12 +481,17 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
private:
size_t idx_; // The region's index in the region space.
uint8_t* begin_; // The begin address of the region.
+ // Note that `top_` can be higher than `end_` in the case of a
+ // large region, where an allocated object spans multiple regions
+ // (large region + one or more large tail regions).
Atomic<uint8_t*> top_; // The current position of the allocation.
uint8_t* end_; // The end address of the region.
RegionState state_; // The region state (see RegionState).
RegionType type_; // The region type (see RegionType).
Atomic<size_t> objects_allocated_; // The number of objects allocated.
uint32_t alloc_time_; // The allocation time of the region.
+ // Note that newly allocated and evacuated regions use -1 as
+ // special value for `live_bytes_`.
size_t live_bytes_; // The live bytes. Used to compute the live percent.
bool is_newly_allocated_; // True if it's allocated after the last collection.
bool is_a_tlab_; // True if it's a tlab.
@@ -488,12 +507,12 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
Region* RefToRegionUnlocked(mirror::Object* ref) NO_THREAD_SAFETY_ANALYSIS {
// For a performance reason (this is frequently called via
- // IsInFromSpace() etc.) we avoid taking a lock here. Note that
- // since we only change a region from to-space to from-space only
- // during a pause (SetFromSpace()) and from from-space to free
- // (after GC is done) as long as ref is a valid reference into an
- // allocated region, it's safe to access the region state without
- // the lock.
+ // RegionSpace::IsInFromSpace, etc.) we avoid taking a lock here.
+ // Note that since we only change a region from to-space to (evac)
+ // from-space during a pause (in RegionSpace::SetFromSpace) and
+ // from (evac) from-space to free (after GC is done), as long as
+ // `ref` is a valid reference into an allocated region, it's safe
+ // to access the region state without the lock.
return RefToRegionLocked(ref);
}
@@ -508,6 +527,13 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
return reg;
}
+ // Return the object location following `obj` in the region space
+ // (i.e., the object location at `obj + obj->SizeOf()`).
+ //
+ // Note that
+ // - unless the region containing `obj` is fully used; and
+ // - `obj` is not the last object of that region;
+ // the returned location is not guaranteed to be a valid object.
mirror::Object* GetNextObject(mirror::Object* obj)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -524,6 +550,8 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
VerifyNonFreeRegionLimit();
}
+ // Implementation of this invariant:
+ // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true.
void VerifyNonFreeRegionLimit() REQUIRES(region_lock_) {
if (kIsDebugBuild && non_free_region_index_limit_ < num_regions_) {
for (size_t i = non_free_region_index_limit_; i < num_regions_; ++i) {
@@ -549,14 +577,18 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
// regions are in non-free.
size_t max_peak_num_non_free_regions_;
+ // The pointer to the region array.
std::unique_ptr<Region[]> regions_ GUARDED_BY(region_lock_);
- // The pointer to the region array.
+
// The upper-bound index of the non-free regions. Used to avoid scanning all regions in
- // SetFromSpace(). Invariant: for all i >= non_free_region_index_limit_, regions_[i].IsFree() is
- // true.
+ // RegionSpace::SetFromSpace and RegionSpace::ClearFromSpace.
+ //
+ // Invariant (verified by RegionSpace::VerifyNonFreeRegionLimit):
+ // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true.
size_t non_free_region_index_limit_ GUARDED_BY(region_lock_);
- Region* current_region_; // The region that's being allocated currently.
- Region* evac_region_; // The region that's being evacuated to currently.
+
+ Region* current_region_; // The region currently used for allocation.
+ Region* evac_region_; // The region currently used for evacuation.
Region full_region_; // The dummy/sentinel region that looks full.
// Mark bitmap used by the GC.
diff --git a/runtime/gc/space/space.cc b/runtime/gc/space/space.cc
index 2c6afa7eb8..a8bd7b816e 100644
--- a/runtime/gc/space/space.cc
+++ b/runtime/gc/space/space.cc
@@ -107,7 +107,6 @@ collector::ObjectBytePair ContinuousMemMapAllocSpace::Sweep(bool swap_bitmaps) {
return scc.freed;
}
-// Returns the old mark bitmap.
void ContinuousMemMapAllocSpace::BindLiveToMarkBitmap() {
CHECK(!HasBoundBitmaps());
accounting::ContinuousSpaceBitmap* live_bitmap = GetLiveBitmap();
@@ -125,7 +124,7 @@ bool ContinuousMemMapAllocSpace::HasBoundBitmaps() const {
void ContinuousMemMapAllocSpace::UnBindBitmaps() {
CHECK(HasBoundBitmaps());
- // At this point, the temp_bitmap holds our old mark bitmap.
+ // At this point, `temp_bitmap_` holds our old mark bitmap.
accounting::ContinuousSpaceBitmap* new_bitmap = temp_bitmap_.release();
Runtime::Current()->GetHeap()->GetMarkBitmap()->ReplaceBitmap(mark_bitmap_.get(), new_bitmap);
CHECK_EQ(mark_bitmap_.release(), live_bitmap_.get());
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 6b76048cb1..12bccb35e7 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -389,7 +389,11 @@ class MemMapSpace : public ContinuousSpace {
}
protected:
- MemMapSpace(const std::string& name, MemMap* mem_map, uint8_t* begin, uint8_t* end, uint8_t* limit,
+ MemMapSpace(const std::string& name,
+ MemMap* mem_map,
+ uint8_t* begin,
+ uint8_t* end,
+ uint8_t* limit,
GcRetentionPolicy gc_retention_policy)
: ContinuousSpace(name, gc_retention_policy, begin, end, limit),
mem_map_(mem_map) {
@@ -420,7 +424,10 @@ class ContinuousMemMapAllocSpace : public MemMapSpace, public AllocSpace {
}
bool HasBoundBitmaps() const REQUIRES(Locks::heap_bitmap_lock_);
+ // Make the mark bitmap an alias of the live bitmap. Save the current mark bitmap into
+ // `temp_bitmap_`, so that we can restore it later in ContinuousMemMapAllocSpace::UnBindBitmaps.
void BindLiveToMarkBitmap() REQUIRES(Locks::heap_bitmap_lock_);
+ // Unalias the mark bitmap from the live bitmap and restore the old mark bitmap.
void UnBindBitmaps() REQUIRES(Locks::heap_bitmap_lock_);
// Swap the live and mark bitmaps of this space. This is used by the GC for concurrent sweeping.
void SwapBitmaps();
diff --git a/runtime/gc/space/zygote_space.h b/runtime/gc/space/zygote_space.h
index 4d10de8237..08231017e7 100644
--- a/runtime/gc/space/zygote_space.h
+++ b/runtime/gc/space/zygote_space.h
@@ -26,7 +26,7 @@ namespace gc {
namespace space {
-// An zygote space is a space which you cannot allocate into or free from.
+// A zygote space is a space which you cannot allocate into or free from.
class ZygoteSpace FINAL : public ContinuousMemMapAllocSpace {
public:
// Returns the remaining storage in the out_map field.
diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc
index d99b37762f..fb5db1147f 100644
--- a/runtime/gc/verification.cc
+++ b/runtime/gc/verification.cc
@@ -140,7 +140,7 @@ bool Verification::IsValidClass(const void* addr) const {
if (!IsValidHeapObjectAddress(k1)) {
return false;
}
- // k should be class class, take the class again to verify.
+ // `k1` should be class class, take the class again to verify.
// Note that this check may not be valid for the no image space since the class class might move
// around from moving GC.
mirror::Class* k2 = k1->GetClass<kVerifyNone, kWithoutReadBarrier>();
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 05e68e66dd..d7e5e18b9e 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -31,6 +31,23 @@ enum Action {
kDeny
};
+enum AccessMethod {
+ kReflection,
+ kJNI
+};
+
+inline std::ostream& operator<<(std::ostream& os, AccessMethod value) {
+ switch (value) {
+ case kReflection:
+ os << "reflection";
+ break;
+ case kJNI:
+ os << "JNI";
+ break;
+ }
+ return os;
+}
+
inline Action GetMemberAction(uint32_t access_flags) {
switch (HiddenApiAccessFlags::DecodeFromRuntime(access_flags)) {
case HiddenApiAccessFlags::kWhitelist:
@@ -45,19 +62,25 @@ inline Action GetMemberAction(uint32_t access_flags) {
}
// Issue a warning about field access.
-inline void WarnAboutMemberAccess(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) {
+inline void WarnAboutMemberAccess(ArtField* field, AccessMethod access_method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
std::string tmp;
LOG(WARNING) << "Accessing hidden field "
<< field->GetDeclaringClass()->GetDescriptor(&tmp) << "->"
- << field->GetName() << ":" << field->GetTypeDescriptor();
+ << field->GetName() << ":" << field->GetTypeDescriptor()
+ << " (" << HiddenApiAccessFlags::DecodeFromRuntime(field->GetAccessFlags())
+ << ", " << access_method << ")";
}
// Issue a warning about method access.
-inline void WarnAboutMemberAccess(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+inline void WarnAboutMemberAccess(ArtMethod* method, AccessMethod access_method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
std::string tmp;
LOG(WARNING) << "Accessing hidden method "
<< method->GetDeclaringClass()->GetDescriptor(&tmp) << "->"
- << method->GetName() << method->GetSignature().ToString();
+ << method->GetName() << method->GetSignature().ToString()
+ << " (" << HiddenApiAccessFlags::DecodeFromRuntime(method->GetAccessFlags())
+ << ", " << access_method << ")";
}
// Returns true if access to `member` should be denied to the caller of the
@@ -69,7 +92,8 @@ inline void WarnAboutMemberAccess(ArtMethod* method) REQUIRES_SHARED(Locks::muta
template<typename T>
inline bool ShouldBlockAccessToMember(T* member,
Thread* self,
- std::function<bool(Thread*)> fn_caller_in_boot)
+ std::function<bool(Thread*)> fn_caller_in_boot,
+ AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member != nullptr);
Runtime* runtime = Runtime::Current();
@@ -92,25 +116,33 @@ inline bool ShouldBlockAccessToMember(T* member,
return false;
}
- // Member is hidden and we are not in the boot class path. Act accordingly.
+ // Member is hidden and we are not in the boot class path.
+
+ // Print a log message with information about this class member access.
+ // We do this regardless of whether we block the access or not.
+ WarnAboutMemberAccess(member, access_method);
+
+ // Block access if on blacklist.
if (action == kDeny) {
return true;
- } else {
- DCHECK(action == kAllowButWarn || action == kAllowButWarnAndToast);
-
- // Allow access to this member but print a warning. Depending on a runtime
- // flag, we might move the member into whitelist and skip the warning the
- // next time the member is used.
- if (runtime->ShouldDedupeHiddenApiWarnings()) {
- member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
- member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
- }
- WarnAboutMemberAccess(member);
- if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
- Runtime::Current()->SetPendingHiddenApiWarning(true);
- }
- return false;
}
+
+ // Allow access to this member but print a warning.
+ DCHECK(action == kAllowButWarn || action == kAllowButWarnAndToast);
+
+ // Depending on a runtime flag, we might move the member into whitelist and
+ // skip the warning the next time the member is accessed.
+ if (runtime->ShouldDedupeHiddenApiWarnings()) {
+ member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
+ member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
+ }
+
+ // If this action requires a UI warning, set the appropriate flag.
+ if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
+ Runtime::Current()->SetPendingHiddenApiWarning(true);
+ }
+
+ return false;
}
// Returns true if access to member with `access_flags` should be denied to `caller`.
diff --git a/runtime/hidden_api_access_flags.h b/runtime/hidden_api_access_flags.h
index c328f965d2..6a88c12be5 100644
--- a/runtime/hidden_api_access_flags.h
+++ b/runtime/hidden_api_access_flags.h
@@ -146,6 +146,24 @@ class HiddenApiAccessFlags {
};
};
+inline std::ostream& operator<<(std::ostream& os, HiddenApiAccessFlags::ApiList value) {
+ switch (value) {
+ case HiddenApiAccessFlags::kWhitelist:
+ os << "whitelist";
+ break;
+ case HiddenApiAccessFlags::kLightGreylist:
+ os << "light greylist";
+ break;
+ case HiddenApiAccessFlags::kDarkGreylist:
+ os << "dark greylist";
+ break;
+ case HiddenApiAccessFlags::kBlacklist:
+ os << "blacklist";
+ break;
+ }
+ return os;
+}
+
} // namespace art
diff --git a/runtime/image.cc b/runtime/image.cc
index 8e3615ffcf..99406229a5 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', '4', '\0' }; // Math.pow() intrinsic.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '5', '\0' }; // Bitstring type check off.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 24cedb093b..0ae6dbfa88 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -269,7 +269,20 @@ static void InstrumentationInstallStack(Thread* thread, void* arg)
}
} else {
CHECK_NE(return_pc, 0U);
- CHECK(!reached_existing_instrumentation_frames_);
+ if (UNLIKELY(reached_existing_instrumentation_frames_)) {
+ std::string thread_name;
+ GetThread()->GetThreadName(thread_name);
+ uint32_t dex_pc = dex::kDexNoIndex;
+ if (last_return_pc_ != 0 &&
+ GetCurrentOatQuickMethodHeader() != nullptr) {
+ dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
+ }
+ LOG(FATAL) << "While walking " << thread_name << " found existing instrumentation frames."
+ << " method is " << GetMethod()->PrettyMethod()
+ << " return_pc is " << std::hex << return_pc
+ << " dex pc: " << dex_pc;
+ UNREACHABLE();
+ }
InstrumentationStackFrame instrumentation_frame(
m->IsRuntimeMethod() ? nullptr : GetThisObject(),
m,
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 12b8c38bbb..a8ab626a62 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -31,6 +31,7 @@
#include "mirror/class.h"
#include "mirror/emulated_stack_frame.h"
#include "mirror/method_handle_impl-inl.h"
+#include "mirror/var_handle.h"
#include "reflection-inl.h"
#include "reflection.h"
#include "stack.h"
@@ -723,263 +724,149 @@ bool DoMethodHandleInvoke(Thread* self,
}
}
-static bool UnimplementedSignaturePolymorphicMethod(Thread* self ATTRIBUTE_UNUSED,
- ShadowFrame& shadow_frame ATTRIBUTE_UNUSED,
- const Instruction* inst ATTRIBUTE_UNUSED,
- uint16_t inst_data ATTRIBUTE_UNUSED,
- JValue* result ATTRIBUTE_UNUSED)
+static bool DoVarHandleInvokeChecked(Thread* self,
+ Handle<mirror::VarHandle> var_handle,
+ Handle<mirror::MethodType> callsite_type,
+ mirror::VarHandle::AccessMode access_mode,
+ ShadowFrame& shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_) {
- UNIMPLEMENTED(FATAL) << "TODO(oth): b/65872996";
- return false;
-}
-
-bool DoVarHandleCompareAndExchange(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleCompareAndExchangeAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleCompareAndExchangeRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleCompareAndSet(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGet(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndAdd(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndAddAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndAddRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseAnd(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseAndAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseAndRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseOr(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseOrAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseOrRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseXor(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseXorAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndBitwiseXorRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndSet(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndSetAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetAndSetRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetOpaque(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
-
-bool DoVarHandleGetVolatile(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
+ // TODO(oth): GetMethodTypeForAccessMode() allocates a MethodType()
+ // which is only required if we need to convert argument and/or
+ // return types.
+ StackHandleScope<1> hs(self);
+ Handle<mirror::MethodType> accessor_type(hs.NewHandle(
+ var_handle->GetMethodTypeForAccessMode(self, access_mode)));
+ const size_t num_vregs = accessor_type->NumberOfVRegs();
+ const int num_params = accessor_type->GetPTypes()->GetLength();
+ ShadowFrameAllocaUniquePtr accessor_frame =
+ CREATE_SHADOW_FRAME(num_vregs, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC());
+ ShadowFrameGetter getter(shadow_frame, operands);
+ static const uint32_t kFirstDestinationReg = 0;
+ ShadowFrameSetter setter(accessor_frame.get(), kFirstDestinationReg);
+ if (!PerformConversions(self, callsite_type, accessor_type, &getter, &setter, num_params)) {
+ return false;
+ }
+ RangeInstructionOperands accessor_operands(kFirstDestinationReg,
+ kFirstDestinationReg + num_vregs);
+ if (!var_handle->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) {
+ return false;
+ }
+ return ConvertReturnValue(callsite_type, accessor_type, result);
}
-bool DoVarHandleSet(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+static bool DoVarHandleInvokeCommon(Thread* self,
+ ShadowFrame& shadow_frame,
+ const Instruction* inst,
+ uint16_t inst_data,
+ JValue* result,
+ mirror::VarHandle::AccessMode access_mode)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Make sure to check for async exceptions
+ if (UNLIKELY(self->ObserveAsyncException())) {
+ return false;
+ }
-bool DoVarHandleSetOpaque(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+ bool is_var_args = inst->HasVarArgs();
+ const uint32_t vRegC = is_var_args ? inst->VRegC_45cc() : inst->VRegC_4rcc();
+ ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(vRegC));
+ if (receiver.IsNull()) {
+ ThrowNullPointerExceptionFromDexPC();
+ return false;
+ }
-bool DoVarHandleSetRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+ StackHandleScope<2> hs(self);
+ Handle<mirror::VarHandle> var_handle(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver.Ptr())));
+ if (!var_handle->IsAccessModeSupported(access_mode)) {
+ ThrowUnsupportedOperationException();
+ return false;
+ }
-bool DoVarHandleSetVolatile(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+ const uint32_t vRegH = is_var_args ? inst->VRegH_45cc() : inst->VRegH_4rcc();
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::MethodType> callsite_type(hs.NewHandle(
+ class_linker->ResolveMethodType(self, vRegH, shadow_frame.GetMethod())));
+ // This implies we couldn't resolve one or more types in this VarHandle.
+ if (UNLIKELY(callsite_type == nullptr)) {
+ CHECK(self->IsExceptionPending());
+ return false;
+ }
-bool DoVarHandleWeakCompareAndSet(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+ if (!var_handle->IsMethodTypeCompatible(access_mode, callsite_type.Get())) {
+ ThrowWrongMethodTypeException(var_handle->GetMethodTypeForAccessMode(self, access_mode),
+ callsite_type.Get());
+ return false;
+ }
-bool DoVarHandleWeakCompareAndSetAcquire(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
+ if (is_var_args) {
+ uint32_t args[Instruction::kMaxVarArgRegs];
+ inst->GetVarArgs(args, inst_data);
+ VarArgsInstructionOperands all_operands(args, inst->VRegA_45cc());
+ NoReceiverInstructionOperands operands(&all_operands);
+ return DoVarHandleInvokeChecked(self,
+ var_handle,
+ callsite_type,
+ access_mode,
+ shadow_frame,
+ &operands,
+ result);
+ } else {
+ RangeInstructionOperands all_operands(inst->VRegC_4rcc(), inst->VRegA_4rcc());
+ NoReceiverInstructionOperands operands(&all_operands);
+ return DoVarHandleInvokeChecked(self,
+ var_handle,
+ callsite_type,
+ access_mode,
+ shadow_frame,
+ &operands,
+ result);
+ }
}
-bool DoVarHandleWeakCompareAndSetPlain(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
+#define DO_VAR_HANDLE_ACCESSOR(_access_mode) \
+bool DoVarHandle ## _access_mode(Thread* self, \
+ ShadowFrame& shadow_frame, \
+ const Instruction* inst, \
+ uint16_t inst_data, \
+ JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { \
+ const auto access_mode = mirror::VarHandle::AccessMode::k ## _access_mode; \
+ return DoVarHandleInvokeCommon(self, shadow_frame, inst, inst_data, result, access_mode); \
}
-bool DoVarHandleWeakCompareAndSetRelease(Thread* self,
- ShadowFrame& shadow_frame,
- const Instruction* inst,
- uint16_t inst_data,
- JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
- return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result);
-}
+DO_VAR_HANDLE_ACCESSOR(CompareAndExchange)
+DO_VAR_HANDLE_ACCESSOR(CompareAndExchangeAcquire)
+DO_VAR_HANDLE_ACCESSOR(CompareAndExchangeRelease)
+DO_VAR_HANDLE_ACCESSOR(CompareAndSet)
+DO_VAR_HANDLE_ACCESSOR(Get)
+DO_VAR_HANDLE_ACCESSOR(GetAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndAdd)
+DO_VAR_HANDLE_ACCESSOR(GetAndAddAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndAddRelease)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAnd)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAndAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAndRelease)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOr)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOrAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOrRelease)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXor)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXorAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXorRelease)
+DO_VAR_HANDLE_ACCESSOR(GetAndSet)
+DO_VAR_HANDLE_ACCESSOR(GetAndSetAcquire)
+DO_VAR_HANDLE_ACCESSOR(GetAndSetRelease)
+DO_VAR_HANDLE_ACCESSOR(GetOpaque)
+DO_VAR_HANDLE_ACCESSOR(GetVolatile)
+DO_VAR_HANDLE_ACCESSOR(Set)
+DO_VAR_HANDLE_ACCESSOR(SetOpaque)
+DO_VAR_HANDLE_ACCESSOR(SetRelease)
+DO_VAR_HANDLE_ACCESSOR(SetVolatile)
+DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSet)
+DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetAcquire)
+DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetPlain)
+DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetRelease)
+
+#undef DO_VAR_HANDLE_ACCESSOR
template<bool is_range>
bool DoInvokePolymorphic(Thread* self,
@@ -1049,7 +936,8 @@ static ObjPtr<mirror::CallSite> InvokeBootstrapMethod(Thread* self,
// The first parameter is a MethodHandles lookup instance.
{
- Handle<mirror::Class> lookup_class(hs.NewHandle(bootstrap->GetTargetClass()));
+ Handle<mirror::Class> lookup_class =
+ hs.NewHandle(shadow_frame.GetMethod()->GetDeclaringClass());
ObjPtr<mirror::MethodHandlesLookup> lookup =
mirror::MethodHandlesLookup::Create(self, lookup_class);
if (lookup.IsNull()) {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 8180222e22..39a1db85d4 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -176,7 +176,8 @@ static inline bool DoInvoke(Thread* self,
}
const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
- ObjPtr<mirror::Object> receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
+ ObjPtr<mirror::Object> receiver =
+ (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
ArtMethod* sf_method = shadow_frame.GetMethod();
ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>(
method_idx, &receiver, sf_method, self);
@@ -645,7 +646,7 @@ EXPLICIT_DO_FAST_INVOKE_TEMPLATE_DECL(kVirtual); // invoke-virtual
// Explicitly instantiate all DoInvokeVirtualQuick functions.
#define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range) \
- template REQUIRES_SHARED(Locks::mutator_lock_) \
+ template REQUIRES_SHARED(Locks::mutator_lock_) \
bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame, \
const Instruction* inst, uint16_t inst_data, \
JValue* result)
diff --git a/runtime/interpreter/mterp/arm/entry.S b/runtime/interpreter/mterp/arm/entry.S
index df4bcc66f3..7c7c527ef4 100644
--- a/runtime/interpreter/mterp/arm/entry.S
+++ b/runtime/interpreter/mterp/arm/entry.S
@@ -56,7 +56,7 @@ ENTRY ExecuteMterpImpl
VREG_INDEX_TO_ADDR rREFS, r0 @ point to reference array in shadow frame
ldr r0, [r2, #SHADOWFRAME_DEX_PC_OFFSET] @ Get starting dex_pc.
add rPC, r1, r0, lsl #1 @ Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/arm/header.S b/runtime/interpreter/mterp/arm/header.S
index 64ab9efa19..1f15f870ea 100644
--- a/runtime/interpreter/mterp/arm/header.S
+++ b/runtime/interpreter/mterp/arm/header.S
@@ -93,6 +93,8 @@ unspecified registers or condition codes.
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC r4
+#define CFI_DEX 4 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define rFP r5
#define rSELF r6
#define rINST r7
diff --git a/runtime/interpreter/mterp/arm64/entry.S b/runtime/interpreter/mterp/arm64/entry.S
index 8d61210be8..cf38a2992d 100644
--- a/runtime/interpreter/mterp/arm64/entry.S
+++ b/runtime/interpreter/mterp/arm64/entry.S
@@ -46,7 +46,7 @@ ENTRY ExecuteMterpImpl
add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame
ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc.
add xPC, x1, w0, lsl #1 // Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, xPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/arm64/header.S b/runtime/interpreter/mterp/arm64/header.S
index 9261b770d6..f0bf8ca34e 100644
--- a/runtime/interpreter/mterp/arm64/header.S
+++ b/runtime/interpreter/mterp/arm64/header.S
@@ -95,6 +95,8 @@ codes.
/* During bringup, we'll use the shadow frame model instead of xFP */
/* single-purpose registers, given names for clarity */
#define xPC x20
+#define CFI_DEX 20 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define xFP x21
#define xSELF x22
#define xINST x23
diff --git a/runtime/interpreter/mterp/cfi_asm_support.h b/runtime/interpreter/mterp/cfi_asm_support.h
index a97e153993..0df4eb4f81 100644
--- a/runtime/interpreter/mterp/cfi_asm_support.h
+++ b/runtime/interpreter/mterp/cfi_asm_support.h
@@ -18,14 +18,30 @@
#define ART_RUNTIME_INTERPRETER_MTERP_CFI_ASM_SUPPORT_H_
/*
- * To keep track of the Dalvik PC, give assign it a magic register number that
- * won't be confused with a pysical register. Then, standard .cfi directives
- * will track the location of it so that it may be extracted during a stack
- * unwind.
+ * Define the DEX PC (memory address of the currently interpreted bytecode)
+ * within the CFI stream of the current function (stored in .eh_frame).
+ * This allows libunwind to detect that the frame is in the interpreter,
+ * and to resolve the memory address into human readable Java method name.
+ * The CFI instruction is recognised by the magic bytes in the expression
+ * (we push magic "DEX1" constant on the DWARF stack and drop it again).
*
- * The Dalvik PC will be in either a physical registor, or the frame.
- * Encoded from the ASCII string " DEX" -> 0x20 0x44 0x45 0x58
+ * As with any other CFI opcode, the expression needs to be associated with
+ * a register. Any caller-save register will do as those are unused in CFI.
+ * Better solution would be to store the expression in Android-specific
+ * DWARF register (CFI registers don't have to correspond to real hardware
+ * registers), however, gdb handles any unknown registers very poorly.
+ * Similarly, we could also use some of the user-defined opcodes defined
+ * in the DWARF specification, but gdb doesn't support those either.
+ *
+ * The DEX PC is generally advanced in the middle of the bytecode handler,
+ * which will result in the reported DEX PC to be off by an instruction.
+ * Therefore the macro allows adding/subtracting an offset to compensate.
+ * TODO: Add the offsets to handlers to get line-accurate DEX PC reporting.
*/
-#define DPC_PSEUDO_REG 0x20444558
+#define CFI_DEFINE_DEX_PC_WITH_OFFSET(tmpReg, dexReg, dexOffset) .cfi_escape \
+ 0x16 /* DW_CFA_val_expression */, tmpReg, 0x09 /* size */, \
+ 0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = "DEX1" */ \
+ 0x13 /* DW_OP_drop */, \
+ 0x92 /* DW_OP_bregx */, dexReg, (dexOffset & 0x7F) /* 1-byte SLEB128 */
#endif // ART_RUNTIME_INTERPRETER_MTERP_CFI_ASM_SUPPORT_H_
diff --git a/runtime/interpreter/mterp/gen_mterp.py b/runtime/interpreter/mterp/gen_mterp.py
index 1c9af30d0a..40d99df037 100755
--- a/runtime/interpreter/mterp/gen_mterp.py
+++ b/runtime/interpreter/mterp/gen_mterp.py
@@ -22,7 +22,7 @@
import sys, string, re, time
from string import Template
-interp_defs_file = "../../dex_instruction_list.h" # need opcode list
+interp_defs_file = "../../dex/dex_instruction_list.h" # need opcode list
kNumPackedOpcodes = 256
splitops = False
diff --git a/runtime/interpreter/mterp/mips/entry.S b/runtime/interpreter/mterp/mips/entry.S
index 41b5d5650d..d342354969 100644
--- a/runtime/interpreter/mterp/mips/entry.S
+++ b/runtime/interpreter/mterp/mips/entry.S
@@ -54,7 +54,7 @@ ExecuteMterpImpl:
EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
EAS1(rPC, a1, a0) # Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC()
diff --git a/runtime/interpreter/mterp/mips/header.S b/runtime/interpreter/mterp/mips/header.S
index 0f7a6f1116..014628f415 100644
--- a/runtime/interpreter/mterp/mips/header.S
+++ b/runtime/interpreter/mterp/mips/header.S
@@ -61,6 +61,8 @@
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rIBASE s3
diff --git a/runtime/interpreter/mterp/mips64/entry.S b/runtime/interpreter/mterp/mips64/entry.S
index 841a817569..ed965aa201 100644
--- a/runtime/interpreter/mterp/mips64/entry.S
+++ b/runtime/interpreter/mterp/mips64/entry.S
@@ -73,7 +73,7 @@ ExecuteMterpImpl:
dlsa rREFS, v0, rFP, 2
lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
dlsa rPC, v0, a1, 1
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/mips64/header.S b/runtime/interpreter/mterp/mips64/header.S
index 2b550cb533..4947aff38e 100644
--- a/runtime/interpreter/mterp/mips64/header.S
+++ b/runtime/interpreter/mterp/mips64/header.S
@@ -90,6 +90,8 @@ The following registers have fixed assignments:
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rINST s3
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index f3c1124ec4..5c1a13b9d6 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -100,6 +100,8 @@ unspecified registers or condition codes.
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC r4
+#define CFI_DEX 4 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define rFP r5
#define rSELF r6
#define rINST r7
@@ -375,7 +377,7 @@ ENTRY ExecuteMterpImpl
VREG_INDEX_TO_ADDR rREFS, r0 @ point to reference array in shadow frame
ldr r0, [r2, #SHADOWFRAME_DEX_PC_OFFSET] @ Get starting dex_pc.
add rPC, r1, r0, lsl #1 @ Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index 347d54f705..72446ba082 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -102,6 +102,8 @@ codes.
/* During bringup, we'll use the shadow frame model instead of xFP */
/* single-purpose registers, given names for clarity */
#define xPC x20
+#define CFI_DEX 20 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define xFP x21
#define xSELF x22
#define xINST x23
@@ -405,7 +407,7 @@ ENTRY ExecuteMterpImpl
add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame
ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc.
add xPC, x1, w0, lsl #1 // Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, xPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S
index 1687afa58a..d5861b28a7 100644
--- a/runtime/interpreter/mterp/out/mterp_mips.S
+++ b/runtime/interpreter/mterp/out/mterp_mips.S
@@ -68,6 +68,8 @@
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rIBASE s3
@@ -788,7 +790,7 @@ ExecuteMterpImpl:
EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
EAS1(rPC, a1, a0) # Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC()
diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S
index 559c72bb0c..5224df92be 100644
--- a/runtime/interpreter/mterp/out/mterp_mips64.S
+++ b/runtime/interpreter/mterp/out/mterp_mips64.S
@@ -97,6 +97,8 @@ The following registers have fixed assignments:
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rINST s3
@@ -408,7 +410,7 @@ ExecuteMterpImpl:
dlsa rREFS, v0, rFP, 2
lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
dlsa rPC, v0, a1, 1
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 0613c9d12e..f98fa5b74f 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -164,6 +164,8 @@ unspecified registers or condition codes.
/* single-purpose registers, given names for clarity */
#define rSELF IN_ARG0(%esp)
#define rPC %esi
+#define CFI_DEX 6 // DWARF register number of the register holding dex-pc (esi).
+#define CFI_TMP 0 // DWARF register number of the first argument register (eax).
#define rFP %edi
#define rINST %ebx
#define rINSTw %bx
@@ -380,7 +382,7 @@ SYMBOL(ExecuteMterpImpl):
leal (rFP, %eax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(%edx), %eax
lea (%ecx, %eax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Set up for backwards branches & osr profiling */
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
index aa91db3b61..d82a2d2eb0 100644
--- a/runtime/interpreter/mterp/out/mterp_x86_64.S
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -164,6 +164,8 @@ unspecified registers or condition codes.
/* single-purpose registers, given names for clarity */
#define rSELF SELF_SPILL(%rsp)
#define rPC %r12
+#define CFI_DEX 12 // DWARF register number of the register holding dex-pc (rPC).
+#define CFI_TMP 5 // DWARF register number of the first argument register (rdi).
#define rFP %r13
#define rINST %ebx
#define rINSTq %rbx
@@ -363,7 +365,7 @@ SYMBOL(ExecuteMterpImpl):
leaq (rFP, %rax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
leaq (IN_ARG1, %rax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/x86/entry.S b/runtime/interpreter/mterp/x86/entry.S
index 10ca8366de..324637bf9a 100644
--- a/runtime/interpreter/mterp/x86/entry.S
+++ b/runtime/interpreter/mterp/x86/entry.S
@@ -61,7 +61,7 @@ SYMBOL(ExecuteMterpImpl):
leal (rFP, %eax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(%edx), %eax
lea (%ecx, %eax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Set up for backwards branches & osr profiling */
diff --git a/runtime/interpreter/mterp/x86/header.S b/runtime/interpreter/mterp/x86/header.S
index 0e585e86f0..2e3bbdf6f7 100644
--- a/runtime/interpreter/mterp/x86/header.S
+++ b/runtime/interpreter/mterp/x86/header.S
@@ -157,6 +157,8 @@ unspecified registers or condition codes.
/* single-purpose registers, given names for clarity */
#define rSELF IN_ARG0(%esp)
#define rPC %esi
+#define CFI_DEX 6 // DWARF register number of the register holding dex-pc (esi).
+#define CFI_TMP 0 // DWARF register number of the first argument register (eax).
#define rFP %edi
#define rINST %ebx
#define rINSTw %bx
diff --git a/runtime/interpreter/mterp/x86_64/entry.S b/runtime/interpreter/mterp/x86_64/entry.S
index d85ef7fe24..2f69226206 100644
--- a/runtime/interpreter/mterp/x86_64/entry.S
+++ b/runtime/interpreter/mterp/x86_64/entry.S
@@ -58,7 +58,7 @@ SYMBOL(ExecuteMterpImpl):
leaq (rFP, %rax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
leaq (IN_ARG1, %rax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/x86_64/header.S b/runtime/interpreter/mterp/x86_64/header.S
index a3ef8953ca..eabaade4e7 100644
--- a/runtime/interpreter/mterp/x86_64/header.S
+++ b/runtime/interpreter/mterp/x86_64/header.S
@@ -157,6 +157,8 @@ unspecified registers or condition codes.
/* single-purpose registers, given names for clarity */
#define rSELF SELF_SPILL(%rsp)
#define rPC %r12
+#define CFI_DEX 12 // DWARF register number of the register holding dex-pc (rPC).
+#define CFI_TMP 5 // DWARF register number of the first argument register (rdi).
#define rFP %r13
#define rINST %ebx
#define rINSTq %rbx
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 85acc71377..f8dd8293ca 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -235,6 +235,20 @@ void UnstartedRuntime::UnstartedClassForNameLong(
UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.forName");
}
+void UnstartedRuntime::UnstartedClassGetPrimitiveClass(
+ Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+ ObjPtr<mirror::String> class_name = GetClassName(self, shadow_frame, arg_offset);
+ ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(class_name);
+ if (UNLIKELY(klass == nullptr)) {
+ DCHECK(self->IsExceptionPending());
+ AbortTransactionOrFail(self,
+ "Class.getPrimitiveClass() failed: %s",
+ self->GetException()->GetDetailMessage()->ToModifiedUtf8().c_str());
+ return;
+ }
+ result->SetL(klass);
+}
+
void UnstartedRuntime::UnstartedClassClassForName(
Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.classForName");
@@ -738,12 +752,6 @@ void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
}
}
-void UnstartedRuntime::UnstartedVoidLookupType(
- Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
- size_t arg_offset ATTRIBUTE_UNUSED) {
- result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
-}
-
// Arraycopy emulation.
// Note: we can't use any fast copy functions, as they are not available under transaction.
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index c029e07432..3cc598aed7 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -23,6 +23,7 @@
V(CharacterToUpperCase, "int java.lang.Character.toUpperCase(int)") \
V(ClassForName, "java.lang.Class java.lang.Class.forName(java.lang.String)") \
V(ClassForNameLong, "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)") \
+ V(ClassGetPrimitiveClass, "java.lang.Class java.lang.Class.getPrimitiveClass(java.lang.String)") \
V(ClassClassForName, "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)") \
V(ClassNewInstance, "java.lang.Object java.lang.Class.newInstance()") \
V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \
@@ -36,7 +37,6 @@
V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \
V(ConstructorNewInstance0, "java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[])") \
V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
- V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \
V(SystemArraycopy, "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") \
V(SystemArraycopyByte, "void java.lang.System.arraycopy(byte[], int, byte[], int, int)") \
V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 8c81c2565d..ac20afecd4 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -225,7 +225,7 @@ class JavaVMExt : public JavaVM {
// Extra checking.
bool check_jni_;
- bool force_copy_;
+ const bool force_copy_;
const bool tracing_enabled_;
// Extra diagnostics.
diff --git a/runtime/jdwp/jdwp_adb.cc b/runtime/jdwp/jdwp_adb.cc
index d68430f3ac..481aff91f8 100644
--- a/runtime/jdwp/jdwp_adb.cc
+++ b/runtime/jdwp/jdwp_adb.cc
@@ -38,8 +38,7 @@
* domain stream socket (@jdwp-control) that is opened by the
* ADB daemon.
*
- * 2/ it then sends the current process PID as a string of 4 hexadecimal
- * chars (no terminating zero)
+ * 2/ it then sends the current process PID as an int32_t.
*
* 3/ then, it uses recvmsg to receive file descriptors from the
* daemon. each incoming file descriptor is a pass-through to
@@ -225,7 +224,6 @@ bool JdwpAdbState::Accept() {
if (ControlSock() == -1) {
int sleep_ms = 500;
const int sleep_max_ms = 2*1000;
- char buff[5];
int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (sock < 0) {
@@ -247,8 +245,7 @@ bool JdwpAdbState::Accept() {
}
}
- snprintf(buff, sizeof(buff), "%04x", getpid());
- buff[4] = 0;
+ int32_t pid = getpid();
for (;;) {
/*
@@ -277,9 +274,9 @@ bool JdwpAdbState::Accept() {
#endif
/* now try to send our pid to the ADB daemon */
- ret = TEMP_FAILURE_RETRY(send(control_sock, buff, 4, 0));
- if (ret == 4) {
- VLOG(jdwp) << StringPrintf("PID sent as '%.*s' to ADB", 4, buff);
+ ret = TEMP_FAILURE_RETRY(send(control_sock, &pid, sizeof(pid), 0));
+ if (ret == sizeof(pid)) {
+ VLOG(jdwp) << "PID " << pid << " sent to ADB";
break;
}
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index de4d02edaf..dcb4a20b5f 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -168,9 +168,10 @@ bool ProfileCompilationInfo::AddMethodIndex(MethodHotness::Flag flags,
return data->AddMethod(flags, method_idx);
}
-bool ProfileCompilationInfo::AddMethods(const std::vector<ProfileMethodInfo>& methods) {
+bool ProfileCompilationInfo::AddMethods(const std::vector<ProfileMethodInfo>& methods,
+ MethodHotness::Flag flags) {
for (const ProfileMethodInfo& method : methods) {
- if (!AddMethod(method)) {
+ if (!AddMethod(method, flags)) {
return false;
}
}
@@ -644,15 +645,26 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location,
uint32_t dex_checksum,
uint16_t method_index,
uint32_t num_method_ids,
- const OfflineProfileMethodInfo& pmi) {
+ const OfflineProfileMethodInfo& pmi,
+ MethodHotness::Flag flags) {
DexFileData* const data = GetOrAddDexFileData(GetProfileDexFileKey(dex_location),
dex_checksum,
num_method_ids);
- if (data == nullptr) { // checksum mismatch
+ if (data == nullptr) {
+ // The data is null if there is a mismatch in the checksum or number of method ids.
return false;
}
+
// Add the method.
InlineCacheMap* inline_cache = data->FindOrAddMethod(method_index);
+ if (inline_cache == nullptr) {
+ // Happens if the method index is outside the range (i.e. is greater then the number
+ // of methods in the dex file). This should not happen during normal execution,
+ // But tools (e.g. boot image aggregation tools) and tests stress this behaviour.
+ return false;
+ }
+
+ data->SetMethodHotness(method_index, flags);
if (pmi.inline_caches == nullptr) {
// If we don't have inline caches return success right away.
@@ -691,12 +703,16 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location,
return true;
}
-bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) {
+bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi, MethodHotness::Flag flags) {
DexFileData* const data = GetOrAddDexFileData(pmi.ref.dex_file);
if (data == nullptr) { // checksum mismatch
return false;
}
InlineCacheMap* inline_cache = data->FindOrAddMethod(pmi.ref.index);
+ if (inline_cache == nullptr) {
+ return false;
+ }
+ data->SetMethodHotness(pmi.ref.index, flags);
for (const ProfileMethodInfo::ProfileInlineCache& cache : pmi.inline_caches) {
if (cache.is_missing_types) {
@@ -811,6 +827,9 @@ bool ProfileCompilationInfo::ReadMethods(SafeBuffer& buffer,
uint16_t method_index = last_method_index + diff_with_last_method_index;
last_method_index = method_index;
InlineCacheMap* inline_cache = data->FindOrAddMethod(method_index);
+ if (inline_cache == nullptr) {
+ return false;
+ }
if (!ReadInlineCache(buffer,
number_of_dex_files,
dex_profile_index_remap,
@@ -1521,6 +1540,9 @@ bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other,
for (const auto& other_method_it : other_dex_data->method_map) {
uint16_t other_method_index = other_method_it.first;
InlineCacheMap* inline_cache = dex_data->FindOrAddMethod(other_method_index);
+ if (inline_cache == nullptr) {
+ return false;
+ }
const auto& other_inline_cache = other_method_it.second;
for (const auto& other_ic_it : other_inline_cache) {
uint16_t other_dex_pc = other_ic_it.first;
@@ -1955,6 +1977,10 @@ bool ProfileCompilationInfo::IsEmpty() const {
ProfileCompilationInfo::InlineCacheMap*
ProfileCompilationInfo::DexFileData::FindOrAddMethod(uint16_t method_index) {
+ if (method_index >= num_method_ids) {
+ LOG(ERROR) << "Invalid method index " << method_index << ". num_method_ids=" << num_method_ids;
+ return nullptr;
+ }
return &(method_map.FindOrAdd(
method_index,
InlineCacheMap(std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)))->second);
@@ -1967,12 +1993,8 @@ bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, s
return false;
}
- if ((flags & MethodHotness::kFlagStartup) != 0) {
- method_bitmap.StoreBit(MethodBitIndex(/*startup*/ true, index), /*value*/ true);
- }
- if ((flags & MethodHotness::kFlagPostStartup) != 0) {
- method_bitmap.StoreBit(MethodBitIndex(/*startup*/ false, index), /*value*/ true);
- }
+ SetMethodHotness(index, flags);
+
if ((flags & MethodHotness::kFlagHot) != 0) {
method_map.FindOrAdd(
index,
@@ -1981,6 +2003,17 @@ bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, s
return true;
}
+void ProfileCompilationInfo::DexFileData::SetMethodHotness(size_t index,
+ MethodHotness::Flag flags) {
+ DCHECK_LT(index, num_method_ids);
+ if ((flags & MethodHotness::kFlagStartup) != 0) {
+ method_bitmap.StoreBit(MethodBitIndex(/*startup*/ true, index), /*value*/ true);
+ }
+ if ((flags & MethodHotness::kFlagPostStartup) != 0) {
+ method_bitmap.StoreBit(MethodBitIndex(/*startup*/ false, index), /*value*/ true);
+ }
+}
+
ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::DexFileData::GetHotnessInfo(
uint32_t dex_method_index) const {
MethodHotness ret;
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index 1973f3f09e..5488a9e81e 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -241,7 +241,7 @@ class ProfileCompilationInfo {
~ProfileCompilationInfo();
// Add the given methods to the current profile object.
- bool AddMethods(const std::vector<ProfileMethodInfo>& methods);
+ bool AddMethods(const std::vector<ProfileMethodInfo>& methods, MethodHotness::Flag flags);
// Add the given classes to the current profile object.
bool AddClasses(const std::set<DexCacheResolvedClasses>& resolved_classes);
@@ -278,7 +278,7 @@ class ProfileCompilationInfo {
bool AddMethodIndex(MethodHotness::Flag flags, const MethodReference& ref);
// Add a method to the profile using its online representation (containing runtime structures).
- bool AddMethod(const ProfileMethodInfo& pmi);
+ bool AddMethod(const ProfileMethodInfo& pmi, MethodHotness::Flag flags);
// Bulk add sampled methods and/or hot methods for a single dex, fast since it only has one
// GetOrAddDexFileData call.
@@ -500,6 +500,7 @@ class ProfileCompilationInfo {
}
}
+ void SetMethodHotness(size_t index, MethodHotness::Flag flags);
MethodHotness GetHotnessInfo(uint32_t dex_method_index) const;
// The allocator used to allocate new inline cache maps.
@@ -559,7 +560,8 @@ class ProfileCompilationInfo {
uint32_t dex_checksum,
uint16_t method_index,
uint32_t num_method_ids,
- const OfflineProfileMethodInfo& pmi);
+ const OfflineProfileMethodInfo& pmi,
+ MethodHotness::Flag flags);
// Add a class index to the profile.
bool AddClassIndex(const std::string& dex_location,
diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc
index 4ac11ee422..e6917956ae 100644
--- a/runtime/jit/profile_compilation_info_test.cc
+++ b/runtime/jit/profile_compilation_info_test.cc
@@ -80,7 +80,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
uint16_t method_index,
const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi,
ProfileCompilationInfo* info) {
- return info->AddMethod(dex_location, checksum, method_index, kMaxMethodIds, pmi);
+ return info->AddMethod(
+ dex_location, checksum, method_index, kMaxMethodIds, pmi, Hotness::kFlagPostStartup);
}
bool AddClass(const std::string& dex_location,
@@ -99,7 +100,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
bool SaveProfilingInfo(
const std::string& filename,
const std::vector<ArtMethod*>& methods,
- const std::set<DexCacheResolvedClasses>& resolved_classes) {
+ const std::set<DexCacheResolvedClasses>& resolved_classes,
+ Hotness::Flag flags) {
ProfileCompilationInfo info;
std::vector<ProfileMethodInfo> profile_methods;
ScopedObjectAccess soa(Thread::Current());
@@ -107,7 +109,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
profile_methods.emplace_back(
MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
}
- if (!info.AddMethods(profile_methods) || !info.AddClasses(resolved_classes)) {
+ if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) {
return false;
}
if (info.GetNumberOfMethods() != profile_methods.size()) {
@@ -130,6 +132,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
bool SaveProfilingInfoWithFakeInlineCaches(
const std::string& filename,
const std::vector<ArtMethod*>& methods,
+ Hotness::Flag flags,
/*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) {
ProfileCompilationInfo info;
std::vector<ProfileMethodInfo> profile_methods;
@@ -170,7 +173,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
profile_methods_map->Put(method, pmi);
}
- if (!info.AddMethods(profile_methods) || info.GetNumberOfMethods() != profile_methods.size()) {
+ if (!info.AddMethods(profile_methods, flags)
+ || info.GetNumberOfMethods() != profile_methods.size()) {
return false;
}
return info.Save(filename, nullptr);
@@ -345,7 +349,8 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
// Save virtual methods from Main.
std::set<DexCacheResolvedClasses> resolved_classes;
std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
- ASSERT_TRUE(SaveProfilingInfo(profile.GetFilename(), main_methods, resolved_classes));
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup));
// Check that what we saved is in the profile.
ProfileCompilationInfo info1;
@@ -354,14 +359,16 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(info1.GetMethodHotness(
- MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot());
+ Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
}
}
// Save virtual methods from Second.
std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
- ASSERT_TRUE(SaveProfilingInfo(profile.GetFilename(), second_methods, resolved_classes));
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup));
// Check that what we saved is in the profile (methods form Main and Second).
ProfileCompilationInfo info2;
@@ -371,12 +378,14 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(
- info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot());
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
}
for (ArtMethod* m : second_methods) {
- ASSERT_TRUE(
- info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot());
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
}
}
}
@@ -730,7 +739,7 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map;
ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches(
- profile.GetFilename(), main_methods, &profile_methods_map));
+ profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map));
// Check that what we saved is in the profile.
ProfileCompilationInfo info;
@@ -739,8 +748,9 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
{
ScopedObjectAccess soa(self);
for (ArtMethod* m : main_methods) {
- ASSERT_TRUE(
- info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot());
+ Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
info.GetMethod(m->GetDexFile()->GetLocation(),
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 8f0ac33594..53f48644f2 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -511,7 +511,7 @@ bool ProfileSaver::ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number
uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
- info.AddMethods(profile_methods);
+ info.AddMethods(profile_methods, ProfileCompilationInfo::MethodHotness::kFlagPostStartup);
auto profile_cache_it = profile_cache_.find(filename);
if (profile_cache_it != profile_cache_.end()) {
info.MergeWith(*(profile_cache_it->second));
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 0e8fd03057..291ac48e86 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -96,6 +96,15 @@ class JNIEnvExt : public JNIEnv {
}
Thread* GetSelf() const { return self_; }
+ uint32_t GetCritical() const { return critical_; }
+ void SetCritical(uint32_t new_critical) { critical_ = new_critical; }
+ uint64_t GetCriticalStartUs() const { return critical_start_us_; }
+ void SetCriticalStartUs(uint64_t new_critical_start_us) {
+ critical_start_us_ = new_critical_start_us;
+ }
+ const JNINativeInterface* GetUncheckedFunctions() const {
+ return unchecked_functions_;
+ }
JavaVMExt* GetVm() const { return vm_; }
bool IsRuntimeDeleted() const { return runtime_deleted_; }
@@ -190,9 +199,7 @@ class JNIEnvExt : public JNIEnv {
// If we are a JNI env for a daemon thread with a deleted runtime.
bool runtime_deleted_;
- friend class CheckJNI;
friend class JNI;
- friend class ScopedCheck;
friend class ScopedJniEnvLocalRefState;
friend class Thread;
ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 666fb98354..cd4d9543be 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -90,7 +90,8 @@ static bool IsCallerInBootClassPath(Thread* self) REQUIRES_SHARED(Locks::mutator
template<typename T>
ALWAYS_INLINE static bool ShouldBlockAccessToMember(T* member, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
- return hiddenapi::ShouldBlockAccessToMember(member, self, IsCallerInBootClassPath);
+ return hiddenapi::ShouldBlockAccessToMember(
+ member, self, IsCallerInBootClassPath, hiddenapi::kJNI);
}
// Helpers to call instrumentation functions for fields. These take jobjects so we don't need to set
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index fac1a7597d..e89beb6d41 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -34,7 +34,9 @@ class Monitor;
/* The lock value itself as stored in mirror::Object::monitor_. The two most significant bits of
* the state. The four possible states are fat locked, thin/unlocked, hash code, and forwarding
- * address. When the lock word is in the "thin" state and its bits are formatted as follows:
+ * address.
+ *
+ * When the lock word is in the "thin" state and its bits are formatted as follows:
*
* |33|2|2|222222221111|1111110000000000|
* |10|9|8|765432109876|5432109876543210|
@@ -59,7 +61,7 @@ class Monitor;
* |11|0| ForwardingAddress |
*
* The `r` bit stores the read barrier state.
- * The `m` bit stores the mark state.
+ * The `m` bit stores the mark bit state.
*/
class LockWord {
public:
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 2701ec66a4..9b21e1d9bf 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -346,7 +346,7 @@ inline bool ConvertAndCopyArgumentsFromCallerFrame(
return false;
}
- ShadowFrameGetter getter(operands, caller_frame);
+ ShadowFrameGetter getter(caller_frame, operands);
ShadowFrameSetter setter(callee_frame, first_dest_reg);
return PerformConversions<ShadowFrameGetter, ShadowFrameSetter>(self,
callsite_type,
diff --git a/runtime/method_handles.h b/runtime/method_handles.h
index 6ffd1a81fc..3b1bf2ee66 100644
--- a/runtime/method_handles.h
+++ b/runtime/method_handles.h
@@ -130,8 +130,10 @@ bool PerformConversions(Thread* self,
// arguments while performing standard argument conversions.
class ShadowFrameGetter {
public:
- ShadowFrameGetter(const InstructionOperands* const operands, const ShadowFrame& shadow_frame)
- : operands_(operands), operand_index_(0), shadow_frame_(shadow_frame) {}
+ ShadowFrameGetter(const ShadowFrame& shadow_frame,
+ const InstructionOperands* const operands,
+ size_t operand_index = 0u)
+ : shadow_frame_(shadow_frame), operands_(operands), operand_index_(operand_index) {}
ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
return shadow_frame_.GetVReg(Next());
@@ -151,26 +153,24 @@ class ShadowFrameGetter {
operand_index_ += 1;
return next;
}
+
uint32_t NextLong() {
const uint32_t next = operands_->GetOperand(operand_index_);
operand_index_ += 2;
return next;
}
- const InstructionOperands* const operands_;
- size_t operand_index_; // the next register operand to read from frame
const ShadowFrame& shadow_frame_;
+ const InstructionOperands* const operands_; // the set of register operands to read
+ size_t operand_index_; // the next register operand to read from frame
};
// A convenience class that allows values to be written to a given shadow frame,
// starting at location |first_dst_reg|.
class ShadowFrameSetter {
public:
- ShadowFrameSetter(ShadowFrame* shadow_frame,
- size_t first_dst_reg) :
- shadow_frame_(shadow_frame),
- arg_index_(first_dst_reg) {
- }
+ ShadowFrameSetter(ShadowFrame* shadow_frame, size_t first_dst_reg)
+ : shadow_frame_(shadow_frame), arg_index_(first_dst_reg) {}
ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
shadow_frame_->SetVReg(arg_index_++, value);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 36388eb3aa..86d538ec80 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -550,7 +550,7 @@ inline bool Class::IsSubClass(ObjPtr<Class> klass) {
current = current->GetSuperClass();
} while (current != nullptr);
- if (kIsDebugBuild) {
+ if (kIsDebugBuild && kBitstringSubtypeCheckEnabled) {
ObjPtr<mirror::Class> dis(this);
SubtypeCheckInfo::Result sc_result = SubtypeCheck<ObjPtr<Class>>::IsSubtypeOf(dis, klass);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 8a7defd362..5d730ce0b0 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -72,6 +72,42 @@ void Class::VisitRoots(RootVisitor* visitor) {
java_lang_Class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
}
+ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
+ const char* expected_name = nullptr;
+ ClassLinker::ClassRoot class_root = ClassLinker::kJavaLangObject; // Invalid.
+ if (name != nullptr && name->GetLength() >= 2) {
+ // Perfect hash for the expected values: from the second letters of the primitive types,
+ // only 'y' has the bit 0x10 set, so use it to change 'b' to 'B'.
+ char hash = name->CharAt(0) ^ ((name->CharAt(1) & 0x10) << 1);
+ switch (hash) {
+ case 'b': expected_name = "boolean"; class_root = ClassLinker::kPrimitiveBoolean; break;
+ case 'B': expected_name = "byte"; class_root = ClassLinker::kPrimitiveByte; break;
+ case 'c': expected_name = "char"; class_root = ClassLinker::kPrimitiveChar; break;
+ case 'd': expected_name = "double"; class_root = ClassLinker::kPrimitiveDouble; break;
+ case 'f': expected_name = "float"; class_root = ClassLinker::kPrimitiveFloat; break;
+ case 'i': expected_name = "int"; class_root = ClassLinker::kPrimitiveInt; break;
+ case 'l': expected_name = "long"; class_root = ClassLinker::kPrimitiveLong; break;
+ case 's': expected_name = "short"; class_root = ClassLinker::kPrimitiveShort; break;
+ case 'v': expected_name = "void"; class_root = ClassLinker::kPrimitiveVoid; break;
+ default: break;
+ }
+ }
+ if (expected_name != nullptr && name->Equals(expected_name)) {
+ ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->GetClassRoot(class_root);
+ DCHECK(klass != nullptr);
+ return klass;
+ } else {
+ Thread* self = Thread::Current();
+ if (name == nullptr) {
+ // Note: ThrowNullPointerException() requires a message which we deliberately want to omit.
+ self->ThrowNewException("Ljava/lang/NullPointerException;", /* msg */ nullptr);
+ } else {
+ self->ThrowNewException("Ljava/lang/ClassNotFoundException;", name->ToModifiedUtf8().c_str());
+ }
+ return nullptr;
+ }
+}
+
ClassExt* Class::EnsureExtDataPresent(Thread* self) {
ObjPtr<ClassExt> existing(GetExtData());
if (!existing.IsNull()) {
@@ -156,9 +192,19 @@ void Class::SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self
self->AssertPendingException();
}
- {
+ if (kBitstringSubtypeCheckEnabled) {
+ // FIXME: This looks broken with respect to aborted transactions.
ObjPtr<mirror::Class> h_this_ptr = h_this.Get();
SubtypeCheck<ObjPtr<mirror::Class>>::WriteStatus(h_this_ptr, new_status);
+ } else {
+ // The ClassStatus is always in the 4 most-significant bits of status_.
+ static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32");
+ uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ h_this->SetField32Volatile<true>(StatusOffset(), new_status_value);
+ } else {
+ h_this->SetField32Volatile<false>(StatusOffset(), new_status_value);
+ }
}
// Setting the object size alloc fast path needs to be after the status write so that if the
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index ced7c7c908..b9a31e54b7 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -81,7 +81,7 @@ class MANAGED Class FINAL : public Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ClassStatus GetStatus() REQUIRES_SHARED(Locks::mutator_lock_) {
// Avoid including "subtype_check_bits_and_status.h" to get the field.
- // The ClassStatus is always in the 4 most-significant of status_.
+ // The ClassStatus is always in the 4 most-significant bits of status_.
return enum_cast<ClassStatus>(
static_cast<uint32_t>(GetField32Volatile<kVerifyFlags>(StatusOffset())) >> (32 - 4));
}
@@ -1134,6 +1134,10 @@ class MANAGED Class FINAL : public Object {
void VisitNativeRoots(Visitor& visitor, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Get one of the primitive classes.
+ static ObjPtr<mirror::Class> GetPrimitiveClass(ObjPtr<mirror::String> name)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// When class is verified, set the kAccSkipAccessChecks flag on each method.
void SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
index 5757992167..5f00c6e9c7 100644
--- a/runtime/mirror/emulated_stack_frame.cc
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -183,7 +183,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs(
}
// Step 4 : Perform argument conversions (if required).
- ShadowFrameGetter getter(operands, caller_frame);
+ ShadowFrameGetter getter(caller_frame, operands);
EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength());
if (!PerformConversions<ShadowFrameGetter, EmulatedStackFrameAccessor>(
self, caller_type, callee_type, &getter, &setter, num_method_params)) {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 6e2a07c9e0..7fdaa32751 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -160,7 +160,8 @@ inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) {
template<VerifyObjectFlags kVerifyFlags>
inline bool Object::InstanceOf(ObjPtr<Class> klass) {
DCHECK(klass != nullptr);
- DCHECK(GetClass<kVerifyNone>() != nullptr);
+ DCHECK(GetClass<kVerifyNone>() != nullptr)
+ << "this=" << std::hex << reinterpret_cast<uintptr_t>(this) << std::dec;
return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
}
@@ -935,6 +936,195 @@ inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier(
return success;
}
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset,
+ ObjPtr<Object> old_value,
+ ObjPtr<Object> new_value) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ if (kVerifyFlags & kVerifyWrites) {
+ VerifyObject(new_value);
+ }
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(old_value);
+ }
+ uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
+ uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
+ bool success = atomic_addr->CompareAndExchangeStrongSequentiallyConsistent(&old_ref, new_ref);
+ ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
+ if (kIsDebugBuild) {
+ // Ensure caller has done read barrier on the reference field so it's in the to-space.
+ ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr());
+ }
+ if (kTransactionActive && success) {
+ Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true);
+ }
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(witness_value);
+ }
+ return witness_value;
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset,
+ ObjPtr<Object> new_value) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ if (kVerifyFlags & kVerifyWrites) {
+ VerifyObject(new_value);
+ }
+ uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
+ uint32_t old_ref = atomic_addr->ExchangeSequentiallyConsistent(new_ref);
+ ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
+ if (kIsDebugBuild) {
+ // Ensure caller has done read barrier on the reference field so it's in the to-space.
+ ReadBarrier::AssertToSpaceInvariant(old_value.Ptr());
+ }
+ if (kTransactionActive) {
+ Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
+ }
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(old_value);
+ }
+ return old_value;
+}
+
+template<typename T, VerifyObjectFlags kVerifyFlags>
+inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) {
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ T* addr = reinterpret_cast<T*>(raw_addr);
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset,
+ Accessor<uint8_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ uint8_t* addr = raw_addr;
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset,
+ Accessor<int8_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ int8_t* addr = reinterpret_cast<int8_t*>(raw_addr);
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset,
+ Accessor<uint16_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr);
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset,
+ Accessor<int16_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ int16_t* addr = reinterpret_cast<int16_t*>(raw_addr);
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset,
+ Accessor<int32_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ int32_t* addr = reinterpret_cast<int32_t*>(raw_addr);
+ accessor->Access(addr);
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset,
+ Accessor<int64_t>* accessor) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ static const bool kIsVolatile = true;
+ int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
+ Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
+ accessor->Access(addr);
+}
+
template<bool kIsStatic,
VerifyObjectFlags kVerifyFlags,
ReadBarrierOption kReadBarrierOption,
diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h
index d81fff0a22..126cb04cf1 100644
--- a/runtime/mirror/object-readbarrier-inl.h
+++ b/runtime/mirror/object-readbarrier-inl.h
@@ -187,7 +187,7 @@ inline bool Object::AtomicSetMarkBit(uint32_t expected_mark_bit, uint32_t mark_b
expected_lw = lw;
new_lw = lw;
new_lw.SetMarkBitState(mark_bit);
- // Since this is only set from the mutator, we can use the non release Cas.
+ // Since this is only set from the mutator, we can use the non-release CAS.
} while (!CasLockWordWeakRelaxed(expected_lw, new_lw));
return true;
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 25b86a527d..816ac69b29 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -347,6 +347,21 @@ class MANAGED LOCKABLE Object {
ObjPtr<Object> old_value,
ObjPtr<Object> new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
+
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ObjPtr<Object> CompareAndExchangeFieldObject(MemberOffset field_offset,
+ ObjPtr<Object> old_value,
+ ObjPtr<Object> new_value)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ObjPtr<Object> ExchangeFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
template<bool kTransactionActive,
bool kCheckTransaction = true,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -592,6 +607,52 @@ class MANAGED LOCKABLE Object {
field_offset, reinterpret_cast64<int64_t>(new_value));
}
}
+
+ // Base class for accessors used to describe accesses performed by VarHandle methods.
+ template <typename T>
+ class Accessor {
+ public:
+ virtual ~Accessor() {
+ static_assert(std::is_arithmetic<T>::value, "unsupported type");
+ }
+ virtual void Access(T* field_address) = 0;
+ };
+
+ // Getter method that exposes the raw address of a primitive value-type field to an Accessor
+ // instance. This are used by VarHandle accessor methods to read fields with a wider range of
+ // memory orderings than usually required.
+ template<typename T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Update methods that expose the raw address of a primitive value-type to an Accessor instance
+ // that will attempt to update the field. These are used by VarHandle accessor methods to
+ // atomically update fields with a wider range of memory orderings than usually required.
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateFieldBooleanViaAccessor(MemberOffset field_offset, Accessor<uint8_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateFieldByteViaAccessor(MemberOffset field_offset, Accessor<int8_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateFieldCharViaAccessor(MemberOffset field_offset, Accessor<uint16_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateFieldShortViaAccessor(MemberOffset field_offset, Accessor<int16_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateField32ViaAccessor(MemberOffset field_offset, Accessor<int32_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void UpdateField64ViaAccessor(MemberOffset field_offset, Accessor<int64_t>* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// TODO fix thread safety analysis broken by the use of template. This should be
// REQUIRES_SHARED(Locks::mutator_lock_).
template <bool kVisitNativeRoots = true,
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index 3f4a28ce9d..85d06f03fe 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -16,14 +16,23 @@
#include "var_handle.h"
+#include "array-inl.h"
+#include "art_field-inl.h"
#include "class-inl.h"
#include "class_linker.h"
#include "gc_root-inl.h"
+#include "jni_internal.h"
+#include "jvalue-inl.h"
+#include "method_handles.h"
#include "method_type.h"
+#include "well_known_classes.h"
namespace art {
namespace mirror {
+static constexpr bool kTransactionActive = true;
+static constexpr bool kTransactionInactive = !kTransactionActive;
+
namespace {
struct VarHandleAccessorToAccessModeEntry {
@@ -158,32 +167,64 @@ AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
}
}
-// Returns the number of parameters associated with an
-// AccessModeTemplate and the supplied coordinate types.
-int32_t GetParameterCount(AccessModeTemplate access_mode_template,
- ObjPtr<Class> coordinateType0,
- ObjPtr<Class> coordinateType1) {
- int32_t index = 0;
- if (!coordinateType0.IsNull()) {
- index++;
- if (!coordinateType1.IsNull()) {
- index++;
- }
- }
-
+int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
switch (access_mode_template) {
case AccessModeTemplate::kGet:
- return index;
+ return 0;
case AccessModeTemplate::kSet:
case AccessModeTemplate::kGetAndUpdate:
- return index + 1;
+ return 1;
case AccessModeTemplate::kCompareAndSet:
case AccessModeTemplate::kCompareAndExchange:
- return index + 2;
+ return 2;
}
UNREACHABLE();
}
+// Returns the number of parameters associated with an
+// AccessModeTemplate and the supplied coordinate types.
+int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template,
+ ObjPtr<Class> coordinateType0,
+ ObjPtr<Class> coordinateType1) {
+ int32_t count = 0;
+ if (!coordinateType0.IsNull()) {
+ count++;
+ if (!coordinateType1.IsNull()) {
+ count++;
+ }
+ }
+ return count + GetNumberOfVarTypeParameters(access_mode_template);
+}
+
+void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ThrowNullPointerException("Attempt to access memory on a null object");
+}
+
+bool CheckElementIndex(Primitive::Type type,
+ int32_t relative_index,
+ int32_t start,
+ int32_t limit) REQUIRES_SHARED(Locks::mutator_lock_) {
+ int64_t index = start + relative_index;
+ int64_t max_index = limit - Primitive::ComponentSize(type);
+ if (index < start || index > max_index) {
+ ThrowIndexOutOfBoundsException(index, limit - start);
+ return false;
+ }
+ return true;
+}
+
+bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t range_limit)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return CheckElementIndex(type, index, 0, range_limit);
+}
+
+// Returns true if access_mode only entails a memory read. False if
+// access_mode may write to memory.
+bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) {
+ AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
+ return access_mode_template == AccessModeTemplate::kGet;
+}
+
// Writes the parameter types associated with the AccessModeTemplate
// into an array. The parameter types are derived from the specified
// variable type and coordinate types. Returns the number of
@@ -248,6 +289,1123 @@ ObjectArray<Class>* NewArrayOfClasses(Thread* self, int count)
return ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, count);
}
+// Method to insert a read barrier for accessors to reference fields.
+inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> obj, MemberOffset field_offset)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kUseReadBarrier) {
+ // We need to ensure that the reference stored in the field is a to-space one before attempting
+ // the CompareAndSet/CompareAndExchange/Exchange operation otherwise it will fail incorrectly
+ // if obj is in the process of being moved.
+ uint8_t* raw_field_addr = reinterpret_cast<uint8_t*>(obj.Ptr()) + field_offset.SizeValue();
+ auto field_addr = reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr);
+ // Note that the read barrier load does NOT need to be volatile.
+ static constexpr bool kIsVolatile = false;
+ static constexpr bool kAlwaysUpdateField = true;
+ ReadBarrier::Barrier<mirror::Object, kIsVolatile, kWithReadBarrier, kAlwaysUpdateField>(
+ obj.Ptr(),
+ MemberOffset(field_offset),
+ field_addr);
+ }
+}
+
+inline MemberOffset GetMemberOffset(jfieldID field_id) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtField* const field = jni::DecodeArtField(field_id);
+ return field->GetOffset();
+}
+
+//
+// Helper methods for storing results from atomic operations into
+// JValue instances.
+//
+
+inline void StoreResult(uint8_t value, JValue* result) {
+ result->SetZ(value);
+}
+
+inline void StoreResult(int8_t value, JValue* result) {
+ result->SetB(value);
+}
+
+inline void StoreResult(uint16_t value, JValue* result) {
+ result->SetC(value);
+}
+
+inline void StoreResult(int16_t value, JValue* result) {
+ result->SetS(value);
+}
+
+inline void StoreResult(int32_t value, JValue* result) {
+ result->SetI(value);
+}
+
+inline void StoreResult(int64_t value, JValue* result) {
+ result->SetJ(value);
+}
+
+inline void StoreResult(float value, JValue* result) {
+ result->SetF(value);
+}
+
+inline void StoreResult(double value, JValue* result) {
+ result->SetD(value);
+}
+
+inline void StoreResult(ObjPtr<Object> value, JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ result->SetL(value);
+}
+
+//
+// Helper class for byte-swapping value that has been stored in a JValue.
+//
+
+template <typename T>
+class JValueByteSwapper FINAL {
+ public:
+ static void ByteSwap(JValue* value);
+ static void MaybeByteSwap(bool byte_swap, JValue* value) {
+ if (byte_swap) {
+ ByteSwap(value);
+ }
+ }
+};
+
+template <>
+void JValueByteSwapper<uint16_t>::ByteSwap(JValue* value) {
+ value->SetC(BSWAP(value->GetC()));
+}
+
+template <>
+void JValueByteSwapper<int16_t>::ByteSwap(JValue* value) {
+ value->SetS(BSWAP(value->GetS()));
+}
+
+template <>
+void JValueByteSwapper<int32_t>::ByteSwap(JValue* value) {
+ value->SetI(BSWAP(value->GetI()));
+}
+
+template <>
+void JValueByteSwapper<int64_t>::ByteSwap(JValue* value) {
+ value->SetJ(BSWAP(value->GetJ()));
+}
+
+//
+// Accessor implementations, shared across all VarHandle types.
+//
+
+template <typename T, std::memory_order MO>
+class AtomicGetAccessor : public Object::Accessor<T> {
+ public:
+ explicit AtomicGetAccessor(JValue* result) : result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ StoreResult(atom->load(MO), result_);
+ }
+
+ private:
+ JValue* result_;
+};
+
+template <typename T, std::memory_order MO>
+class AtomicSetAccessor : public Object::Accessor<T> {
+ public:
+ explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ atom->store(new_value_, MO);
+ }
+
+ private:
+ T new_value_;
+};
+
+template <typename T> using GetAccessor = AtomicGetAccessor<T, std::memory_order_relaxed>;
+
+template <typename T> using SetAccessor = AtomicSetAccessor<T, std::memory_order_relaxed>;
+
+template <typename T>
+using GetVolatileAccessor = AtomicGetAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T>
+using SetVolatileAccessor = AtomicSetAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MOS, std::memory_order MOF>
+class AtomicStrongCompareAndSetAccessor : public Object::Accessor<T> {
+ public:
+ AtomicStrongCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
+ : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ bool success = atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
+ StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
+ }
+
+ private:
+ T expected_value_;
+ T desired_value_;
+ JValue* result_;
+};
+
+template<typename T>
+using CompareAndSetAccessor =
+ AtomicStrongCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MOS, std::memory_order MOF>
+class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor<T> {
+ public:
+ AtomicStrongCompareAndExchangeAccessor(T expected_value, T desired_value, JValue* result)
+ : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
+ StoreResult(expected_value_, result_);
+ }
+
+ private:
+ T expected_value_;
+ T desired_value_;
+ JValue* result_;
+};
+
+template <typename T>
+using CompareAndExchangeAccessor =
+ AtomicStrongCompareAndExchangeAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MOS, std::memory_order MOF>
+class AtomicWeakCompareAndSetAccessor : public Object::Accessor<T> {
+ public:
+ AtomicWeakCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
+ : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ bool success = atom->compare_exchange_weak(expected_value_, desired_value_, MOS, MOF);
+ StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
+ }
+
+ private:
+ T expected_value_;
+ T desired_value_;
+ JValue* result_;
+};
+
+template <typename T>
+using WeakCompareAndSetAccessor =
+ AtomicWeakCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndSetAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T old_value = atom->exchange(new_value_, MO);
+ StoreResult(old_value, result_);
+ }
+
+ private:
+ T new_value_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndSetAccessor = AtomicGetAndSetAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T, bool kIsFloat, std::memory_order MO>
+class AtomicGetAndAddOperator {
+ public:
+ static T Apply(T* addr, T addend) {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ return atom->fetch_add(addend, MO);
+ }
+};
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndAddOperator<T, /* kIsFloat */ true, MO> {
+ public:
+ static T Apply(T* addr, T addend) {
+ // c++11 does not have std::atomic<T>::fetch_and_add for floating
+ // point types, so we effect one with a compare and swap.
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T old_value = atom->load(std::memory_order_relaxed);
+ T new_value;
+ do {
+ new_value = old_value + addend;
+ } while (!atom->compare_exchange_weak(old_value, new_value, MO, std::memory_order_relaxed));
+ return old_value;
+ }
+};
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndAddAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ constexpr bool kIsFloatingPoint = std::is_floating_point<T>::value;
+ T old_value = AtomicGetAndAddOperator<T, kIsFloatingPoint, MO>::Apply(addr, addend_);
+ StoreResult(old_value, result_);
+ }
+
+ private:
+ T addend_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndAddAccessor = AtomicGetAndAddAccessor<T, std::memory_order_seq_cst>;
+
+// Accessor specifically for memory views where the caller can specify
+// the byte-ordering. Addition only works outside of the byte-swapped
+// memory view because of the direction of carries.
+template <typename T, std::memory_order MO>
+class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* const atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T current_value = atom->load(std::memory_order_relaxed);
+ T sum;
+ do {
+ sum = BSWAP(current_value) + value_;
+ // NB current_value is a pass-by-reference argument in the call to
+ // atomic<T>::compare_exchange_weak().
+ } while (!atom->compare_exchange_weak(current_value,
+ BSWAP(sum),
+ MO,
+ std::memory_order_relaxed));
+ StoreResult(BSWAP(current_value), result_);
+ }
+
+ private:
+ T value_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndAddWithByteSwapAccessor =
+ AtomicGetAndAddWithByteSwapAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndBitwiseOrAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T old_value = atom->fetch_or(value_, MO);
+ StoreResult(old_value, result_);
+ }
+
+ private:
+ T value_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndBitwiseAndAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T old_value = atom->fetch_and(value_, MO);
+ StoreResult(old_value, result_);
+ }
+
+ private:
+ T value_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndBitwiseAndAccessor =
+ AtomicGetAndBitwiseAndAccessor<T, std::memory_order_seq_cst>;
+
+template <typename T, std::memory_order MO>
+class AtomicGetAndBitwiseXorAccessor : public Object::Accessor<T> {
+ public:
+ AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {}
+
+ void Access(T* addr) OVERRIDE {
+ std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
+ T old_value = atom->fetch_xor(value_, MO);
+ StoreResult(old_value, result_);
+ }
+
+ private:
+ T value_;
+ JValue* result_;
+};
+
+template <typename T>
+using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor<T, std::memory_order_seq_cst>;
+
+//
+// Unreachable access modes.
+//
+
+NO_RETURN void UnreachableAccessMode(const char* access_mode, const char* type_name) {
+ LOG(FATAL) << "Unreachable access mode :" << access_mode << " for type " << type_name;
+ UNREACHABLE();
+}
+
+#define UNREACHABLE_ACCESS_MODE(ACCESS_MODE, TYPE) \
+template<> void ACCESS_MODE ## Accessor<TYPE>::Access(TYPE*) { \
+ UnreachableAccessMode(#ACCESS_MODE, #TYPE); \
+}
+
+// The boolean primitive type is not numeric (boolean == std::uint8_t).
+UNREACHABLE_ACCESS_MODE(GetAndAdd, uint8_t)
+
+// The floating point types do not support bitwise operations.
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, float)
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, float)
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, float)
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, double)
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, double)
+UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, double)
+
+// A helper class for object field accesses for floats and
+// doubles. The object interface deals with Field32 and Field64. The
+// former is used for both integers and floats, the latter for longs
+// and doubles. This class provides the necessary coercion.
+template <typename T, typename U>
+class TypeAdaptorAccessor : public Object::Accessor<T> {
+ public:
+ explicit TypeAdaptorAccessor(Object::Accessor<U>* inner_accessor)
+ : inner_accessor_(inner_accessor) {}
+
+ void Access(T* addr) OVERRIDE {
+ static_assert(sizeof(T) == sizeof(U), "bad conversion");
+ inner_accessor_->Access(reinterpret_cast<U*>(addr));
+ }
+
+ private:
+ Object::Accessor<U>* inner_accessor_;
+};
+
+template <typename T>
+class FieldAccessViaAccessor {
+ public:
+ typedef Object::Accessor<T> Accessor;
+
+ // Apply an Accessor to get a field in an object.
+ static void Get(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ obj->GetPrimitiveFieldViaAccessor(field_offset, accessor);
+ }
+
+ // Apply an Accessor to update a field in an object.
+ static void Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+};
+
+template <>
+inline void FieldAccessViaAccessor<float>::Get(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
+ obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor);
+}
+
+template <>
+inline void FieldAccessViaAccessor<double>::Get(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
+ obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor);
+}
+
+template <>
+void FieldAccessViaAccessor<uint8_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateFieldBooleanViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateFieldBooleanViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<int8_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateFieldByteViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateFieldByteViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<uint16_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateFieldCharViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateFieldCharViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<int16_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateFieldShortViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateFieldShortViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<int32_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<int64_t>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, accessor);
+ } else {
+ obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<float>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, &float_to_int_accessor);
+ } else {
+ obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, &float_to_int_accessor);
+ }
+}
+
+template <>
+void FieldAccessViaAccessor<double>::Update(ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ Accessor* accessor)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, &double_to_int_accessor);
+ } else {
+ obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, &double_to_int_accessor);
+ }
+}
+
+// Helper class that gets values from a shadow frame with appropriate type coercion.
+template <typename T>
+class ValueGetter {
+ public:
+ static T Get(ShadowFrameGetter* getter) REQUIRES_SHARED(Locks::mutator_lock_) {
+ static_assert(sizeof(T) <= sizeof(uint32_t), "Bad size");
+ uint32_t raw_value = getter->Get();
+ return static_cast<T>(raw_value);
+ }
+};
+
+template <>
+int64_t ValueGetter<int64_t>::Get(ShadowFrameGetter* getter) {
+ return getter->GetLong();
+}
+
+template <>
+float ValueGetter<float>::Get(ShadowFrameGetter* getter) {
+ uint32_t raw_value = getter->Get();
+ return *reinterpret_cast<float*>(&raw_value);
+}
+
+template <>
+double ValueGetter<double>::Get(ShadowFrameGetter* getter) {
+ int64_t raw_value = getter->GetLong();
+ return *reinterpret_cast<double*>(&raw_value);
+}
+
+template <>
+ObjPtr<Object> ValueGetter<ObjPtr<Object>>::Get(ShadowFrameGetter* getter) {
+ return getter->GetReference();
+}
+
+// Class for accessing fields of Object instances
+template <typename T>
+class FieldAccessor {
+ public:
+ static bool Dispatch(VarHandle::AccessMode access_mode,
+ ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ ShadowFrameGetter* getter,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+};
+
+// Dispatch implementation for primitive fields.
+template <typename T>
+bool FieldAccessor<T>::Dispatch(VarHandle::AccessMode access_mode,
+ ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ ShadowFrameGetter* getter,
+ JValue* result) {
+ switch (access_mode) {
+ case VarHandle::AccessMode::kGet: {
+ GetAccessor<T> accessor(result);
+ FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kSet: {
+ T new_value = ValueGetter<T>::Get(getter);
+ SetAccessor<T> accessor(new_value);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAcquire:
+ case VarHandle::AccessMode::kGetOpaque:
+ case VarHandle::AccessMode::kGetVolatile: {
+ GetVolatileAccessor<T> accessor(result);
+ FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kSetOpaque:
+ case VarHandle::AccessMode::kSetRelease:
+ case VarHandle::AccessMode::kSetVolatile: {
+ T new_value = ValueGetter<T>::Get(getter);
+ SetVolatileAccessor<T> accessor(new_value);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndSet: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndExchange:
+ case VarHandle::AccessMode::kCompareAndExchangeAcquire:
+ case VarHandle::AccessMode::kCompareAndExchangeRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kWeakCompareAndSet:
+ case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
+ case VarHandle::AccessMode::kWeakCompareAndSetPlain:
+ case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndSet:
+ case VarHandle::AccessMode::kGetAndSetAcquire:
+ case VarHandle::AccessMode::kGetAndSetRelease: {
+ T new_value = ValueGetter<T>::Get(getter);
+ GetAndSetAccessor<T> accessor(new_value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndAdd:
+ case VarHandle::AccessMode::kGetAndAddAcquire:
+ case VarHandle::AccessMode::kGetAndAddRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndAddAccessor<T> accessor(value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseOr:
+ case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseOrAccessor<T> accessor(value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseAnd:
+ case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseAndAccessor<T> accessor(value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseXor:
+ case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseXorAccessor<T> accessor(value, result);
+ FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
+ break;
+ }
+ }
+ return true;
+}
+
+// Dispatch implementation for reference fields.
+template <>
+bool FieldAccessor<ObjPtr<Object>>::Dispatch(VarHandle::AccessMode access_mode,
+ ObjPtr<Object> obj,
+ MemberOffset field_offset,
+ ShadowFrameGetter* getter,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // To keep things simple, use the minimum strongest existing
+ // field accessor for Object fields. This may be the most
+ // straightforward strategy in general for the interpreter.
+ switch (access_mode) {
+ case VarHandle::AccessMode::kGet: {
+ StoreResult(obj->GetFieldObject<Object>(field_offset), result);
+ break;
+ }
+ case VarHandle::AccessMode::kSet: {
+ ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->SetFieldObject<kTransactionActive>(field_offset, new_value);
+ } else {
+ obj->SetFieldObject<kTransactionInactive>(field_offset, new_value);
+ }
+ break;
+ }
+ case VarHandle::AccessMode::kGetAcquire:
+ case VarHandle::AccessMode::kGetOpaque:
+ case VarHandle::AccessMode::kGetVolatile: {
+ StoreResult(obj->GetFieldObjectVolatile<Object>(field_offset), result);
+ break;
+ }
+ case VarHandle::AccessMode::kSetOpaque:
+ case VarHandle::AccessMode::kSetRelease:
+ case VarHandle::AccessMode::kSetVolatile: {
+ ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ if (Runtime::Current()->IsActiveTransaction()) {
+ obj->SetFieldObjectVolatile<kTransactionActive>(field_offset, new_value);
+ } else {
+ obj->SetFieldObjectVolatile<kTransactionInactive>(field_offset, new_value);
+ }
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndSet: {
+ ReadBarrierForVarHandleAccess(obj, field_offset);
+ ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ bool cas_result;
+ if (Runtime::Current()->IsActiveTransaction()) {
+ cas_result = obj->CasFieldStrongSequentiallyConsistentObject<kTransactionActive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ } else {
+ cas_result = obj->CasFieldStrongSequentiallyConsistentObject<kTransactionInactive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ }
+ StoreResult(cas_result, result);
+ break;
+ }
+ case VarHandle::AccessMode::kWeakCompareAndSet:
+ case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
+ case VarHandle::AccessMode::kWeakCompareAndSetPlain:
+ case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
+ ReadBarrierForVarHandleAccess(obj, field_offset);
+ ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ bool cas_result;
+ if (Runtime::Current()->IsActiveTransaction()) {
+ cas_result = obj->CasFieldWeakSequentiallyConsistentObject<kTransactionActive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ } else {
+ cas_result = obj->CasFieldWeakSequentiallyConsistentObject<kTransactionInactive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ }
+ StoreResult(cas_result, result);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndExchange:
+ case VarHandle::AccessMode::kCompareAndExchangeAcquire:
+ case VarHandle::AccessMode::kCompareAndExchangeRelease: {
+ ReadBarrierForVarHandleAccess(obj, field_offset);
+ ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ ObjPtr<Object> witness_value;
+ if (Runtime::Current()->IsActiveTransaction()) {
+ witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ } else {
+ witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>(
+ field_offset,
+ expected_value,
+ desired_value);
+ }
+ StoreResult(witness_value, result);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndSet:
+ case VarHandle::AccessMode::kGetAndSetAcquire:
+ case VarHandle::AccessMode::kGetAndSetRelease: {
+ ReadBarrierForVarHandleAccess(obj, field_offset);
+ ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
+ ObjPtr<Object> old_value;
+ if (Runtime::Current()->IsActiveTransaction()) {
+ old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value);
+ } else {
+ old_value = obj->ExchangeFieldObject<kTransactionInactive>(field_offset, new_value);
+ }
+ StoreResult(old_value, result);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndAdd:
+ case VarHandle::AccessMode::kGetAndAddAcquire:
+ case VarHandle::AccessMode::kGetAndAddRelease:
+ case VarHandle::AccessMode::kGetAndBitwiseOr:
+ case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
+ case VarHandle::AccessMode::kGetAndBitwiseAnd:
+ case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
+ case VarHandle::AccessMode::kGetAndBitwiseXor:
+ case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
+ size_t index = static_cast<size_t>(access_mode);
+ const char* access_mode_name = kAccessorToAccessMode[index].method_name;
+ UnreachableAccessMode(access_mode_name, "Object");
+ }
+ }
+ return true;
+}
+
+// Class for accessing primitive array elements.
+template <typename T>
+class PrimitiveArrayElementAccessor {
+ public:
+ static T* GetElementAddress(ObjPtr<Array> target_array, int target_element)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array);
+ DCHECK(primitive_array->CheckIsValidIndex(target_element));
+ return &primitive_array->GetData()[target_element];
+ }
+
+ static bool Dispatch(VarHandle::AccessMode access_mode,
+ ObjPtr<Array> target_array,
+ int target_element,
+ ShadowFrameGetter* getter,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ T* element_address = GetElementAddress(target_array, target_element);
+ switch (access_mode) {
+ case VarHandle::AccessMode::kGet: {
+ GetAccessor<T> accessor(result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kSet: {
+ T new_value = ValueGetter<T>::Get(getter);
+ SetAccessor<T> accessor(new_value);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAcquire:
+ case VarHandle::AccessMode::kGetOpaque:
+ case VarHandle::AccessMode::kGetVolatile: {
+ GetVolatileAccessor<T> accessor(result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kSetOpaque:
+ case VarHandle::AccessMode::kSetRelease:
+ case VarHandle::AccessMode::kSetVolatile: {
+ T new_value = ValueGetter<T>::Get(getter);
+ SetVolatileAccessor<T> accessor(new_value);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndSet: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndExchange:
+ case VarHandle::AccessMode::kCompareAndExchangeAcquire:
+ case VarHandle::AccessMode::kCompareAndExchangeRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kWeakCompareAndSet:
+ case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
+ case VarHandle::AccessMode::kWeakCompareAndSetPlain:
+ case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndSet:
+ case VarHandle::AccessMode::kGetAndSetAcquire:
+ case VarHandle::AccessMode::kGetAndSetRelease: {
+ T new_value = ValueGetter<T>::Get(getter);
+ GetAndSetAccessor<T> accessor(new_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndAdd:
+ case VarHandle::AccessMode::kGetAndAddAcquire:
+ case VarHandle::AccessMode::kGetAndAddRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndAddAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseOr:
+ case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseOrAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseAnd:
+ case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseAndAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseXor:
+ case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ GetAndBitwiseXorAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ }
+ return true;
+ }
+};
+
+// Class for accessing primitive array elements.
+template <typename T>
+class ByteArrayViewAccessor {
+ public:
+ static inline bool IsAccessAligned(int8_t* data, int data_index) {
+ static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size");
+ static_assert(std::is_arithmetic<T>::value, "unexpected type");
+ uintptr_t alignment_mask = sizeof(T) - 1;
+ uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index);
+ return (address & alignment_mask) == 0;
+ }
+
+ static inline void MaybeByteSwap(bool byte_swap, T* const value) {
+ if (byte_swap) {
+ *value = BSWAP(*value);
+ }
+ }
+
+ static bool Dispatch(const VarHandle::AccessMode access_mode,
+ int8_t* const data,
+ const int data_index,
+ const bool byte_swap,
+ ShadowFrameGetter* const getter,
+ JValue* const result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const bool is_aligned = IsAccessAligned(data, data_index);
+ if (!is_aligned) {
+ switch (access_mode) {
+ case VarHandle::AccessMode::kGet: {
+ T value;
+ memcpy(&value, data + data_index, sizeof(T));
+ MaybeByteSwap(byte_swap, &value);
+ StoreResult(value, result);
+ return true;
+ }
+ case VarHandle::AccessMode::kSet: {
+ T new_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &new_value);
+ memcpy(data + data_index, &new_value, sizeof(T));
+ return true;
+ }
+ default:
+ // No other access modes support unaligned access.
+ ThrowIllegalStateException("Unaligned access not supported");
+ return false;
+ }
+ }
+
+ T* const element_address = reinterpret_cast<T*>(data + data_index);
+ CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0));
+ switch (access_mode) {
+ case VarHandle::AccessMode::kGet: {
+ GetAccessor<T> accessor(result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kSet: {
+ T new_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &new_value);
+ SetAccessor<T> accessor(new_value);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAcquire:
+ case VarHandle::AccessMode::kGetOpaque:
+ case VarHandle::AccessMode::kGetVolatile: {
+ GetVolatileAccessor<T> accessor(result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kSetOpaque:
+ case VarHandle::AccessMode::kSetRelease:
+ case VarHandle::AccessMode::kSetVolatile: {
+ T new_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &new_value);
+ SetVolatileAccessor<T> accessor(new_value);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndSet: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &expected_value);
+ MaybeByteSwap(byte_swap, &desired_value);
+ CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kCompareAndExchange:
+ case VarHandle::AccessMode::kCompareAndExchangeAcquire:
+ case VarHandle::AccessMode::kCompareAndExchangeRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &expected_value);
+ MaybeByteSwap(byte_swap, &desired_value);
+ CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kWeakCompareAndSet:
+ case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
+ case VarHandle::AccessMode::kWeakCompareAndSetPlain:
+ case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
+ T expected_value = ValueGetter<T>::Get(getter);
+ T desired_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &expected_value);
+ MaybeByteSwap(byte_swap, &desired_value);
+ WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
+ accessor.Access(element_address);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndSet:
+ case VarHandle::AccessMode::kGetAndSetAcquire:
+ case VarHandle::AccessMode::kGetAndSetRelease: {
+ T new_value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &new_value);
+ GetAndSetAccessor<T> accessor(new_value, result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndAdd:
+ case VarHandle::AccessMode::kGetAndAddAcquire:
+ case VarHandle::AccessMode::kGetAndAddRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ if (byte_swap) {
+ GetAndAddWithByteSwapAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ } else {
+ GetAndAddAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ }
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseOr:
+ case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &value);
+ GetAndBitwiseOrAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseAnd:
+ case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &value);
+ GetAndBitwiseAndAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ case VarHandle::AccessMode::kGetAndBitwiseXor:
+ case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
+ case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
+ T value = ValueGetter<T>::Get(getter);
+ MaybeByteSwap(byte_swap, &value);
+ GetAndBitwiseXorAccessor<T> accessor(value, result);
+ accessor.Access(element_address);
+ JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
+ break;
+ }
+ }
+ return true;
+ }
+};
+
} // namespace
Class* VarHandle::GetVarType() {
@@ -267,35 +1425,38 @@ int32_t VarHandle::GetAccessModesBitMask() {
}
bool VarHandle::IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type) {
- ScopedAssertNoThreadSuspension ants(__FUNCTION__);
-
+ StackHandleScope<3> hs(Thread::Current());
+ Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
+ Handle<VarHandle> vh(hs.NewHandle(this));
+ Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
- // Check return types first.
- ObjPtr<Class> var_type = GetVarType();
- ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
- ObjPtr<Class> void_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V');
- ObjPtr<Class> mt_rtype = method_type->GetRType();
-
- // If the mt_rtype is void, the result of the operation will be discarded (okay).
- if (mt_rtype != void_type && mt_rtype != vh_rtype) {
- return false;
+
+ // Check return type first.
+ if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
+ // The result of the operation will be discarded. The return type
+ // of the VarHandle is immaterial.
+ } else {
+ ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
+ if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
+ return false;
+ }
}
// Check the number of parameters matches.
ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
access_mode_template,
- var_type,
+ var_type.Get(),
GetCoordinateType0(),
GetCoordinateType1());
if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
return false;
}
- // Check the parameter types match.
+ // Check the parameter types are compatible.
ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
for (int32_t i = 0; i < vh_ptypes_count; ++i) {
- if (mt_ptypes->Get(i) != vh_ptypes[i].Ptr()) {
+ if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
return false;
}
}
@@ -311,8 +1472,9 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self,
StackHandleScope<3> hs(self);
Handle<VarHandle> vh = hs.NewHandle(var_handle);
Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType()));
- const int32_t ptypes_count =
- GetParameterCount(access_mode_template, vh->GetCoordinateType0(), vh->GetCoordinateType1());
+ const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
+ vh->GetCoordinateType0(),
+ vh->GetCoordinateType1());
Handle<ObjectArray<Class>> ptypes = hs.NewHandle(NewArrayOfClasses(self, ptypes_count));
if (ptypes == nullptr) {
return nullptr;
@@ -334,6 +1496,29 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode acces
return GetMethodTypeForAccessMode(self, this, access_mode);
}
+bool VarHandle::Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result) {
+ Class* klass = GetClass();
+ if (klass == FieldVarHandle::StaticClass()) {
+ auto vh = reinterpret_cast<FieldVarHandle*>(this);
+ return vh->Access(access_mode, shadow_frame, operands, result);
+ } else if (klass == ArrayElementVarHandle::StaticClass()) {
+ auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
+ return vh->Access(access_mode, shadow_frame, operands, result);
+ } else if (klass == ByteArrayViewVarHandle::StaticClass()) {
+ auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
+ return vh->Access(access_mode, shadow_frame, operands, result);
+ } else if (klass == ByteBufferViewVarHandle::StaticClass()) {
+ auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
+ return vh->Access(access_mode, shadow_frame, operands, result);
+ } else {
+ LOG(FATAL) << "Unknown varhandle kind";
+ UNREACHABLE();
+ }
+}
+
const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) {
AccessMode access_mode;
if (!GetAccessModeByMethodName(accessor_name, &access_mode)) {
@@ -369,6 +1554,10 @@ bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* a
return true;
}
+Class* VarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return static_class_.Read();
+}
+
void VarHandle::SetClass(Class* klass) {
CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
CHECK(klass != nullptr);
@@ -391,6 +1580,57 @@ ArtField* FieldVarHandle::GetField() {
return reinterpret_cast<ArtField*>(opaque_field);
}
+bool FieldVarHandle::Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result) {
+ ShadowFrameGetter getter(*shadow_frame, operands);
+ ArtField* field = GetField();
+ ObjPtr<Object> obj;
+ if (field->IsStatic()) {
+ DCHECK_LE(operands->GetNumberOfOperands(),
+ 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
+ obj = field->GetDeclaringClass();
+ } else {
+ DCHECK_GE(operands->GetNumberOfOperands(), 1u);
+ DCHECK_LE(operands->GetNumberOfOperands(),
+ 1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
+ obj = getter.GetReference();
+ if (obj.IsNull()) {
+ ThrowNullPointerExceptionForCoordinate();
+ return false;
+ }
+ }
+ DCHECK(!obj.IsNull());
+
+ const MemberOffset offset = field->GetOffset();
+ const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
+ switch (primitive_type) {
+ case Primitive::Type::kPrimNot:
+ return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimBoolean:
+ return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimByte:
+ return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimChar:
+ return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimShort:
+ return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimInt:
+ return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimFloat:
+ return FieldAccessor<float>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimLong:
+ return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimDouble:
+ return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result);
+ case Primitive::kPrimVoid:
+ break;
+ }
+ LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
+ UNREACHABLE();
+}
+
Class* FieldVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
return static_class_.Read();
}
@@ -412,6 +1652,94 @@ void FieldVarHandle::VisitRoots(RootVisitor* visitor) {
GcRoot<Class> FieldVarHandle::static_class_;
+bool ArrayElementVarHandle::Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result) {
+ ShadowFrameGetter getter(*shadow_frame, operands);
+
+ // The target array is the first co-ordinate type preceeding var type arguments.
+ ObjPtr<Object> raw_array(getter.GetReference());
+ if (raw_array == nullptr) {
+ ThrowNullPointerExceptionForCoordinate();
+ return false;
+ }
+
+ ObjPtr<Array> target_array(raw_array->AsArray());
+
+ // The target array element is the second co-ordinate type preceeding var type arguments.
+ const int target_element = getter.Get();
+ if (!target_array->CheckIsValidIndex(target_element)) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return false;
+ }
+
+ const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
+ switch (primitive_type) {
+ case Primitive::Type::kPrimNot: {
+ MemberOffset target_element_offset =
+ target_array->AsObjectArray<Object>()->OffsetOfElement(target_element);
+ return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode,
+ target_array,
+ target_element_offset,
+ &getter,
+ result);
+ }
+ case Primitive::Type::kPrimBoolean:
+ return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimByte:
+ return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimChar:
+ return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimShort:
+ return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimInt:
+ return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimLong:
+ return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimFloat:
+ return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimDouble:
+ return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode,
+ target_array,
+ target_element,
+ &getter,
+ result);
+ case Primitive::Type::kPrimVoid:
+ break;
+ }
+ LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
+ UNREACHABLE();
+}
+
Class* ArrayElementVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
return static_class_.Read();
}
@@ -437,6 +1765,90 @@ bool ByteArrayViewVarHandle::GetNativeByteOrder() {
return GetFieldBoolean(NativeByteOrderOffset());
}
+bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result) {
+ ShadowFrameGetter getter(*shadow_frame, operands);
+
+ // The byte array is the first co-ordinate type preceeding var type arguments.
+ ObjPtr<Object> raw_byte_array(getter.GetReference());
+ if (raw_byte_array == nullptr) {
+ ThrowNullPointerExceptionForCoordinate();
+ return false;
+ }
+
+ ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray());
+
+ // The offset in the byte array element is the second co-ordinate type.
+ const int32_t data_offset = getter.Get();
+
+ // Bounds check requested access.
+ const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
+ if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) {
+ return false;
+ }
+
+ int8_t* const data = byte_array->GetData();
+ bool byte_swap = !GetNativeByteOrder();
+ switch (primitive_type) {
+ case Primitive::Type::kPrimNot:
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimVoid:
+ // These are not supported for byte array views and not instantiable.
+ break;
+ case Primitive::kPrimChar:
+ return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimShort:
+ return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimInt:
+ return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimFloat:
+ // Treated as a bitwise representation. See javadoc comments for
+ // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
+ return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimLong:
+ return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimDouble:
+ // Treated as a bitwise representation. See javadoc comments for
+ // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
+ return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
+ data,
+ data_offset,
+ byte_swap,
+ &getter,
+ result);
+ }
+ LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
+ UNREACHABLE();
+}
+
Class* ByteArrayViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
return static_class_.Read();
}
@@ -462,6 +1874,122 @@ bool ByteBufferViewVarHandle::GetNativeByteOrder() {
return GetFieldBoolean(NativeByteOrderOffset());
}
+bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result) {
+ ShadowFrameGetter getter(*shadow_frame, operands);
+
+ // The byte buffer is the first co-ordinate argument preceeding var type arguments.
+ ObjPtr<Object> byte_buffer(getter.GetReference());
+ if (byte_buffer == nullptr) {
+ ThrowNullPointerExceptionForCoordinate();
+ return false;
+ }
+
+ // The byte index for access is the second co-ordinate
+ // argument. This is relative to the offset field of the ByteBuffer.
+ const int32_t byte_index = getter.Get();
+
+ // Check access_mode is compatible with ByteBuffer's read-only property.
+ bool is_read_only = byte_buffer->GetFieldBoolean(
+ GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_isReadOnly));
+ if (is_read_only && !IsReadOnlyAccessMode(access_mode)) {
+ ThrowReadOnlyBufferException();
+ return false;
+ }
+
+ // The native_address is only set for ByteBuffer instances backed by native memory.
+ const int64_t native_address =
+ byte_buffer->GetField64(GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_address));
+
+ // Determine offset and limit for accesses.
+ int32_t byte_buffer_offset;
+ if (native_address == 0l) {
+ // Accessing a heap allocated byte buffer.
+ byte_buffer_offset = byte_buffer->GetField32(
+ GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_offset));
+ } else {
+ // Accessing direct memory.
+ byte_buffer_offset = 0;
+ }
+ const int32_t byte_buffer_limit = byte_buffer->GetField32(
+ GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_limit));
+
+ const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
+ if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_limit)) {
+ return false;
+ }
+ const int32_t checked_offset32 = byte_buffer_offset + byte_index;
+
+ int8_t* data;
+ if (native_address == 0) {
+ ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>(
+ GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_hb));
+ data = heap_byte_array->GetData();
+ } else {
+ data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address));
+ }
+
+ bool byte_swap = !GetNativeByteOrder();
+ switch (primitive_type) {
+ case Primitive::kPrimChar:
+ return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimShort:
+ return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimInt:
+ return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimFloat:
+ // Treated as a bitwise representation. See javadoc comments for
+ // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
+ return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimLong:
+ return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::kPrimDouble:
+ // Treated as a bitwise representation. See javadoc comments for
+ // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
+ return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
+ data,
+ checked_offset32,
+ byte_swap,
+ &getter,
+ result);
+ case Primitive::Type::kPrimNot:
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ case Primitive::kPrimVoid:
+ // These are not supported for byte array views and not instantiable.
+ break;
+ }
+ LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
+ UNREACHABLE();
+}
+
Class* ByteBufferViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
return static_class_.Read();
}
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index 7b48669bba..6565af7f06 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -18,18 +18,24 @@
#define ART_RUNTIME_MIRROR_VAR_HANDLE_H_
#include "handle.h"
+#include "interpreter/shadow_frame.h"
#include "gc_root.h"
+#include "jvalue.h"
#include "object.h"
namespace art {
template<class T> class Handle;
+class InstructionOperands;
+
struct VarHandleOffsets;
struct FieldVarHandleOffsets;
struct ArrayElementVarHandleOffsets;
struct ByteArrayViewVarHandleOffsets;
struct ByteBufferViewVarHandleOffsets;
+class ShadowFrameGetter;
+
namespace mirror {
class MethodType;
@@ -44,6 +50,10 @@ class MANAGED VarHandle : public Object {
// (array, index, old, new).
static constexpr int kMaxAccessorParameters = 4;
+ // The maximum number of VarType parameters a VarHandle accessor
+ // method can take.
+ static constexpr size_t kMaxVarTypeParameters = 2;
+
// Enumeration of the possible access modes. This mirrors the enum
// in java.lang.invoke.VarHandle.
enum class AccessMode : uint32_t {
@@ -101,11 +111,16 @@ class MANAGED VarHandle : public Object {
// supported operation so the MethodType can be used when raising a
// WrongMethodTypeException exception.
MethodType* GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
+ REQUIRES_SHARED(Locks::mutator_lock_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
+ bool Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Gets the variable type that is operated on by this VarHandle instance.
+ Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
// Gets the return type descriptor for a named accessor method,
// nullptr if accessor_method is not supported.
@@ -115,12 +130,13 @@ class MANAGED VarHandle : public Object {
// VarHandle access method, such as "setOpaque". Returns false otherwise.
static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
+
+ static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
private:
- Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -163,6 +179,12 @@ class MANAGED VarHandle : public Object {
// The corresponding managed class in libart java.lang.invoke.FieldVarHandle.
class MANAGED FieldVarHandle : public VarHandle {
public:
+ bool Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_);
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -190,6 +212,12 @@ class MANAGED FieldVarHandle : public VarHandle {
// The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle.
class MANAGED ArrayElementVarHandle : public VarHandle {
public:
+ bool Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -207,6 +235,12 @@ class MANAGED ArrayElementVarHandle : public VarHandle {
// The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle.
class MANAGED ByteArrayViewVarHandle : public VarHandle {
public:
+ bool Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -234,10 +268,13 @@ class MANAGED ByteArrayViewVarHandle : public VarHandle {
// The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle.
class MANAGED ByteBufferViewVarHandle : public VarHandle {
public:
- bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
+ bool Access(AccessMode access_mode,
+ ShadowFrame* shadow_frame,
+ InstructionOperands* operands,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
- static ByteBufferViewVarHandle* Create(Thread* const self, bool native_byte_order)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
+ bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -245,6 +282,21 @@ class MANAGED ByteBufferViewVarHandle : public VarHandle {
static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ bool AccessHeapBuffer(AccessMode access_mode,
+ ObjPtr<Object> byte_buffer,
+ int buffer_offset,
+ ObjPtr<ByteArray> heap_byte_array,
+ ShadowFrameGetter* getter,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ bool AccessFixedMemory(AccessMode access_mode,
+ ObjPtr<Object> byte_buffer,
+ int buffer_offset,
+ ShadowFrameGetter* getter,
+ JValue* result)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
static MemberOffset NativeByteOrderOffset() {
return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_));
}
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index e844fd4436..d9fa07f207 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -327,7 +327,7 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) {
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)I")));
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)V")));
EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V")));
+ EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIII)V")));
}
// Check compatibility - "GetAndUpdate" pattern
@@ -336,7 +336,7 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) {
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)I")));
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)V")));
EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
+ EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S")));
}
// Check synthesized method types match expected forms.
@@ -461,8 +461,8 @@ TEST_F(VarHandleTest, StaticFieldVarHandle) {
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)I")));
EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V")));
EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(ID)I")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)D")));
- EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V")));
+ EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S")));
+ EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIJ)V")));
}
// Check compatibility - "GetAndUpdate" pattern
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 6ea9a7ad62..b49209c4cf 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -549,6 +549,55 @@ static jstring DexFile_getDexFileStatus(JNIEnv* env,
return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str());
}
+// Return an array specifying the optimization status of the given file.
+// The array specification is [compiler_filter, compiler_reason].
+static jobjectArray DexFile_getDexFileOptimizationStatus(JNIEnv* env,
+ jclass,
+ jstring javaFilename,
+ jstring javaInstructionSet) {
+ ScopedUtfChars filename(env, javaFilename);
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ ScopedUtfChars instruction_set(env, javaInstructionSet);
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ const InstructionSet target_instruction_set = GetInstructionSetFromString(
+ instruction_set.c_str());
+ if (target_instruction_set == InstructionSet::kNone) {
+ ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
+ std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
+ env->ThrowNew(iae.get(), message.c_str());
+ return nullptr;
+ }
+
+ std::string compilation_filter;
+ std::string compilation_reason;
+ OatFileAssistant::GetOptimizationStatus(
+ filename.c_str(), target_instruction_set, &compilation_filter, &compilation_reason);
+
+ ScopedLocalRef<jstring> j_compilation_filter(env, env->NewStringUTF(compilation_filter.c_str()));
+ if (j_compilation_filter.get() == nullptr) {
+ return nullptr;
+ }
+ ScopedLocalRef<jstring> j_compilation_reason(env, env->NewStringUTF(compilation_reason.c_str()));
+ if (j_compilation_reason.get() == nullptr) {
+ return nullptr;
+ }
+
+ // Now create output array and copy the set into it.
+ jobjectArray result = env->NewObjectArray(2,
+ WellKnownClasses::java_lang_String,
+ nullptr);
+ env->SetObjectArrayElement(result, 0, j_compilation_filter.get());
+ env->SetObjectArrayElement(result, 1, j_compilation_reason.get());
+
+ return result;
+}
+
static jint DexFile_getDexOptNeeded(JNIEnv* env,
jclass,
jstring javaFilename,
@@ -801,7 +850,9 @@ static JNINativeMethod gMethods[] = {
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(DexFile, getDexFileOutputPaths,
"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"),
- NATIVE_METHOD(DexFile, getStaticSizeOfDexFile, "(Ljava/lang/Object;)J")
+ NATIVE_METHOD(DexFile, getStaticSizeOfDexFile, "(Ljava/lang/Object;)J"),
+ NATIVE_METHOD(DexFile, getDexFileOptimizationStatus,
+ "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;")
};
void register_dalvik_system_DexFile(JNIEnv* env) {
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 57a429cf1e..505b745200 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -405,18 +405,15 @@ static void PreloadDexCachesResolveMethod(ObjPtr<mirror::DexCache> dex_cache, ui
}
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
- ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+ ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType(
method_id.class_idx_, dex_cache, /* class_loader */ nullptr);
if (klass == nullptr) {
return;
}
- ArtMethod* method = klass->IsInterface()
- ? klass->FindInterfaceMethod(dex_cache, method_idx, kRuntimePointerSize)
- : klass->FindClassMethod(dex_cache, method_idx, kRuntimePointerSize);
- if (method == nullptr) {
- return;
- }
- dex_cache->SetResolvedMethod(method_idx, method, kRuntimePointerSize);
+ // Call FindResolvedMethod to populate the dex cache.
+ class_linker->FindResolvedMethod(klass, dex_cache, /* class_loader */ nullptr, method_idx);
}
struct DexCacheStats {
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 648a464b6e..12400e26ea 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -173,7 +173,7 @@ enum {
DEBUG_JAVA_DEBUGGABLE = 1 << 8,
DISABLE_VERIFIER = 1 << 9,
ONLY_USE_SYSTEM_OAT_FILES = 1 << 10,
- DISABLE_HIDDEN_API_CHECKS = 1 << 11,
+ ENABLE_HIDDEN_API_CHECKS = 1 << 11,
DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12,
};
@@ -282,7 +282,7 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
// Our system thread ID, etc, has changed so reset Thread state.
thread->InitAfterFork();
runtime_flags = EnableDebugFeatures(runtime_flags);
- bool do_hidden_api_checks = true;
+ bool do_hidden_api_checks = false;
if ((runtime_flags & DISABLE_VERIFIER) != 0) {
Runtime::Current()->DisableVerifier();
@@ -294,9 +294,9 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES;
}
- if ((runtime_flags & DISABLE_HIDDEN_API_CHECKS) != 0) {
- do_hidden_api_checks = false;
- runtime_flags &= ~DISABLE_HIDDEN_API_CHECKS;
+ if ((runtime_flags & ENABLE_HIDDEN_API_CHECKS) != 0) {
+ do_hidden_api_checks = true;
+ runtime_flags &= ~ENABLE_HIDDEN_API_CHECKS;
}
if (runtime_flags != 0) {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 2091a27ffd..e518553292 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -97,7 +97,8 @@ ALWAYS_INLINE static bool ShouldEnforceHiddenApi(Thread* self)
template<typename T>
ALWAYS_INLINE static bool ShouldBlockAccessToMember(T* member, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
- return hiddenapi::ShouldBlockAccessToMember(member, self, IsCallerInBootClassPath);
+ return hiddenapi::ShouldBlockAccessToMember(
+ member, self, IsCallerInBootClassPath, hiddenapi::kReflection);
}
// Returns true if a class member should be discoverable with reflection given
@@ -175,6 +176,12 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean
return soa.AddLocalReference<jclass>(c.Get());
}
+static jclass Class_getPrimitiveClass(JNIEnv* env, jclass, jstring name) {
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(soa.Decode<mirror::String>(name));
+ return soa.AddLocalReference<jclass>(klass);
+}
+
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
@@ -868,6 +875,7 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Class, getInnerClassFlags, "(I)I"),
FAST_NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
FAST_NATIVE_METHOD(Class, getInterfacesInternal, "()[Ljava/lang/Class;"),
+ FAST_NATIVE_METHOD(Class, getPrimitiveClass, "(Ljava/lang/String;)Ljava/lang/Class;"),
FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"),
FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"),
diff --git a/runtime/native/java_lang_Void.cc b/runtime/native/java_lang_Void.cc
deleted file mode 100644
index af83dd1a79..0000000000
--- a/runtime/native/java_lang_Void.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#include "java_lang_Void.h"
-
-#include "nativehelper/jni_macros.h"
-
-#include "class_linker-inl.h"
-#include "jni_internal.h"
-#include "native_util.h"
-#include "runtime.h"
-#include "scoped_fast_native_object_access-inl.h"
-
-namespace art {
-
-static jclass Void_lookupType(JNIEnv* env, jclass) {
- ScopedFastNativeObjectAccess soa(env);
- return soa.AddLocalReference<jclass>(
- Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kPrimitiveVoid));
-}
-
-static JNINativeMethod gMethods[] = {
- FAST_NATIVE_METHOD(Void, lookupType, "()Ljava/lang/Class;"),
-};
-
-void register_java_lang_Void(JNIEnv* env) {
- REGISTER_NATIVE_METHODS("java/lang/Void");
-}
-
-} // namespace art
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 099d77edaa..4d4bab764c 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -345,6 +345,9 @@ void DumpNativeStack(std::ostream& os,
} else {
os << it->map.name;
}
+ if (it->map.offset != 0) {
+ os << StringPrintf(" (offset %" PRIx64 ")", it->map.offset);
+ }
os << " (";
if (!it->func_name.empty()) {
os << it->func_name;
diff --git a/runtime/oat.h b/runtime/oat.h
index 8f81010a06..af14b3e601 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -45,6 +45,7 @@ class PACKED(4) OatHeader {
static constexpr const char* kClassPathKey = "classpath";
static constexpr const char* kBootClassPathKey = "bootclasspath";
static constexpr const char* kConcurrentCopying = "concurrent-copying";
+ static constexpr const char* kCompilationReasonKey = "compilation-reason";
static constexpr const char kTrueValue[] = "true";
static constexpr const char kFalseValue[] = "false";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index dc4bae3415..0852da5644 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -633,6 +633,15 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
const uint8_t* dex_file_pointer = nullptr;
if (UNLIKELY(dex_file_offset == 0U)) {
if (uncompressed_dex_files_ == nullptr) {
+ // Do not support mixed-mode oat files.
+ if (i > 0) {
+ *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
+ "file %zu (%s)",
+ GetLocation().c_str(),
+ i,
+ dex_file_location.c_str());
+ return false;
+ }
uncompressed_dex_files_.reset(new std::vector<std::unique_ptr<const DexFile>>());
// No dex files, load it from location.
const ArtDexFileLoader dex_file_loader;
@@ -652,9 +661,31 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
return false;
}
}
+ // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
+ // here and ensure that at least the number of dex files still matches.
+ // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
+ // done after loading the OatFile.
+ if (uncompressed_dex_files_->size() != dex_file_count) {
+ *error_msg = StringPrintf("In oat file '%s', expected %u uncompressed dex files, but "
+ "found %zu in '%s'",
+ GetLocation().c_str(),
+ dex_file_count,
+ uncompressed_dex_files_->size(),
+ dex_file_location.c_str());
+ return false;
+ }
}
dex_file_pointer = uncompressed_dex_files_.get()->at(i)->Begin();
} else {
+ // Do not support mixed-mode oat files.
+ if (uncompressed_dex_files_ != nullptr) {
+ *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
+ "%zu (%s)",
+ GetLocation().c_str(),
+ i,
+ dex_file_location.c_str());
+ return false;
+ }
if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u of %zu but the size of dex file header is %zu",
@@ -1893,6 +1924,10 @@ std::string OatFile::GetClassLoaderContext() const {
return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
}
+const char* OatFile::GetCompilationReason() const {
+ return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
+}
+
OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
uint16_t class_def_idx,
bool* found) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 46c692e568..802adc3a36 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -130,6 +130,8 @@ class OatFile {
std::string GetClassLoaderContext() const;
+ const char* GetCompilationReason() const;
+
const std::string& GetLocation() const {
return location_;
}
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 15a5954396..0170073e29 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -1262,4 +1262,27 @@ std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFileForUse() {
}
return std::unique_ptr<OatFile>();
}
+
+// TODO(calin): we could provide a more refined status here
+// (e.g. run from uncompressed apk, run with vdex but not oat etc). It will allow us to
+// track more experiments but adds extra complexity.
+void OatFileAssistant::GetOptimizationStatus(
+ const std::string& filename,
+ InstructionSet isa,
+ std::string* out_compilation_filter,
+ std::string* out_compilation_reason) {
+ // Try to load the oat file as we would do at runtime.
+ OatFileAssistant oat_file_assistant(filename.c_str(), isa, true /* load_executable */);
+ std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+
+ if (oat_file == nullptr) {
+ *out_compilation_filter = "run-from-apk";
+ *out_compilation_reason = "unknown";
+ } else {
+ *out_compilation_filter = CompilerFilter::NameOfFilter(oat_file->GetCompilerFilter());
+ const char* reason = oat_file->GetCompilationReason();
+ *out_compilation_reason = reason == nullptr ? "unknown" : reason;
+ }
+}
+
} // namespace art
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index a6140304c2..a184807b73 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -226,6 +226,20 @@ class OatFileAssistant {
// dex file. The returned description is for debugging purposes only.
std::string GetStatusDump();
+ // Computes the optimization status of the given dex file. The result is
+ // returned via the two output parameters.
+ // - out_compilation_filter: the level of optimizations (compiler filter)
+ // - out_compilation_reason: the optimization reason. The reason might
+ // be "unknown" if the compiler artifacts were not annotated during optimizations.
+ //
+ // This method will try to mimic the runtime effect of loading the dex file.
+ // For example, if there is no usable oat file, the compiler filter will be set
+ // to "run-from-apk".
+ static void GetOptimizationStatus(const std::string& filename,
+ InstructionSet isa,
+ std::string* out_compilation_filter,
+ std::string* out_compilation_reason);
+
// Open and returns an image space associated with the oat file.
static std::unique_ptr<gc::space::ImageSpace> OpenImageSpace(const OatFile* oat_file);
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 50f5e7a0d5..72f7d02892 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -43,7 +43,27 @@ namespace art {
static const std::string kSpecialSharedLibrary = "&"; // NOLINT [runtime/string] [4]
static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr;
-class OatFileAssistantTest : public DexoptTest {};
+class OatFileAssistantTest : public DexoptTest {
+ public:
+ void VerifyOptimizationStatus(const std::string& file,
+ const std::string& expected_filter,
+ const std::string& expected_reason) {
+ std::string compilation_filter;
+ std::string compilation_reason;
+ OatFileAssistant::GetOptimizationStatus(
+ file, kRuntimeISA, &compilation_filter, &compilation_reason);
+
+ ASSERT_EQ(expected_filter, compilation_filter);
+ ASSERT_EQ(expected_reason, compilation_reason);
+ }
+
+ void VerifyOptimizationStatus(const std::string& file,
+ CompilerFilter::Filter expected_filter,
+ const std::string& expected_reason) {
+ VerifyOptimizationStatus(
+ file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
+ }
+};
class OatFileAssistantNoDex2OatTest : public DexoptTest {
public:
@@ -107,6 +127,8 @@ TEST_F(OatFileAssistantTest, DexNoOat) {
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+
+ VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
}
// Case: We have no DEX file and no OAT file.
@@ -136,7 +158,7 @@ TEST_F(OatFileAssistantTest, OdexUpToDate) {
std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
Copy(GetDexSrc1(), dex_location);
- GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+ GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
// For the use of oat location by making the dex parent not writable.
OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
@@ -154,6 +176,8 @@ TEST_F(OatFileAssistantTest, OdexUpToDate) {
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+
+ VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
}
// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
@@ -221,6 +245,8 @@ TEST_F(OatFileAssistantTest, OatUpToDate) {
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+
+ VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
}
// Case: Passing valid file descriptors of updated odex/vdex filesalong with
@@ -381,6 +407,8 @@ TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
// Make sure we don't crash in this case when we dump the status. We don't
// care what the actual dumped value is.
oat_file_assistant.GetStatusDump();
+
+ VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
}
// Case: We have a DEX file and empty VDEX and ODEX files.
diff --git a/runtime/oat_file_test.cc b/runtime/oat_file_test.cc
index 8d864018ab..89812f370f 100644
--- a/runtime/oat_file_test.cc
+++ b/runtime/oat_file_test.cc
@@ -88,4 +88,46 @@ TEST_F(OatFileTest, LoadOat) {
EXPECT_EQ(odex_file->GetVdexFile()->Begin(), odex_file->VdexBegin());
}
+TEST_F(OatFileTest, ChangingMultiDexUncompressed) {
+ std::string dex_location = GetScratchDir() + "/MultiDexUncompressed.jar";
+
+ Copy(GetTestDexFileName("MultiDexUncompressed"), dex_location);
+ GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
+
+ std::string oat_location;
+ std::string error_msg;
+ ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
+ dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
+
+ // Ensure we can load that file. Just a precondition.
+ {
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+ oat_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
+ ASSERT_TRUE(odex_file != nullptr);
+ ASSERT_EQ(2u, odex_file->GetOatDexFiles().size());
+ }
+
+ // Now replace the source.
+ Copy(GetTestDexFileName("MainUncompressed"), dex_location);
+
+ // And try to load again.
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
+ oat_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
+ EXPECT_TRUE(odex_file == nullptr);
+ EXPECT_NE(std::string::npos, error_msg.find("expected 2 uncompressed dex files, but found 1"))
+ << error_msg;
+}
+
} // namespace art
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 92eb703338..c7f73d14db 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -330,8 +330,10 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize
.Define("-Xtarget-sdk-version:_")
.WithType<int>()
.IntoKey(M::TargetSdkVersion)
- .Define("-Xno-hidden-api-checks")
- .IntoKey(M::NoHiddenApiChecks)
+ .Define("-Xhidden-api-checks")
+ .IntoKey(M::HiddenApiChecks)
+ .Define("-Xuse-stderr-logger")
+ .IntoKey(M::UseStderrLogger)
.Ignore({
"-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
"-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index b26b09c156..d0aec116a4 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -105,6 +105,7 @@
#include "mirror/method_type.h"
#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
+#include "mirror/var_handle.h"
#include "monitor.h"
#include "native/dalvik_system_DexFile.h"
#include "native/dalvik_system_VMDebug.h"
@@ -119,7 +120,6 @@
#include "native/java_lang_Thread.h"
#include "native/java_lang_Throwable.h"
#include "native/java_lang_VMClassLoader.h"
-#include "native/java_lang_Void.h"
#include "native/java_lang_invoke_MethodHandleImpl.h"
#include "native/java_lang_ref_FinalizerReference.h"
#include "native/java_lang_ref_Reference.h"
@@ -265,7 +265,7 @@ Runtime::Runtime()
oat_file_manager_(nullptr),
is_low_memory_mode_(false),
safe_mode_(false),
- do_hidden_api_checks_(true),
+ do_hidden_api_checks_(false),
pending_hidden_api_warning_(false),
dedupe_hidden_api_warnings_(true),
always_set_hidden_api_warning_flag_(false),
@@ -1082,10 +1082,16 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// Take a snapshot of the environment at the time the runtime was created, for use by Exec, etc.
env_snapshot_.TakeSnapshot();
- RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
+ using Opt = RuntimeArgumentMap;
+ Opt runtime_options(std::move(runtime_options_in));
ScopedTrace trace(__FUNCTION__);
CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
+ // Early override for logging output.
+ if (runtime_options.Exists(Opt::UseStderrLogger)) {
+ android::base::SetLogger(android::base::StderrLogger);
+ }
+
MemMap::Init();
// Try to reserve a dedicated fault page. This is allocated for clobbered registers and sentinels.
@@ -1112,7 +1118,6 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
}
}
- using Opt = RuntimeArgumentMap;
VLOG(startup) << "Runtime::Init -verbose:startup enabled";
QuasiAtomic::Startup();
@@ -1176,14 +1181,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// by default and we only enable them if:
// (a) runtime was started with a flag that enables the checks, or
// (b) Zygote forked a new process that is not exempt (see ZygoteHooks).
- // TODO(dbrazdil): Turn the NoHiddenApiChecks negative flag into a positive one
- // to clean up this logic.
- if (kIsTargetBuild && IsAotCompiler() && !runtime_options.Exists(Opt::NoHiddenApiChecks)) {
- // dex2oat on target without -Xno-hidden-api-checks.
- do_hidden_api_checks_ = !IsCompilingBootImage();
- } else {
- do_hidden_api_checks_ = false;
- }
+ do_hidden_api_checks_ = runtime_options.Exists(Opt::HiddenApiChecks);
DCHECK(!is_zygote_ || !do_hidden_api_checks_)
<< "Zygote should not be started with hidden API checks";
@@ -1747,7 +1745,6 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) {
register_java_lang_Thread(env);
register_java_lang_Throwable(env);
register_java_lang_VMClassLoader(env);
- register_java_lang_Void(env);
register_java_util_concurrent_atomic_AtomicLong(env);
register_libcore_util_CharsetUtils(env);
register_org_apache_harmony_dalvik_ddmc_DdmServer(env);
@@ -1934,6 +1931,11 @@ void Runtime::VisitConstantRoots(RootVisitor* visitor) {
mirror::EmulatedStackFrame::VisitRoots(visitor);
mirror::ClassExt::VisitRoots(visitor);
mirror::CallSite::VisitRoots(visitor);
+ mirror::VarHandle::VisitRoots(visitor);
+ mirror::FieldVarHandle::VisitRoots(visitor);
+ mirror::ArrayElementVarHandle::VisitRoots(visitor);
+ mirror::ByteArrayViewVarHandle::VisitRoots(visitor);
+ mirror::ByteBufferViewVarHandle::VisitRoots(visitor);
// Visit all the primitive array types classes.
mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor); // BooleanArray
mirror::PrimitiveArray<int8_t>::VisitRoots(visitor); // ByteArray
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 7ab9be5c5b..c7f650ea3f 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -325,7 +325,7 @@ class Runtime {
// instead.
void VisitImageRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
- // Visit all of the roots we can do safely do concurrently.
+ // Visit all of the roots we can safely visit concurrently.
void VisitConcurrentRoots(RootVisitor* visitor,
VisitRootFlags flags = kVisitRootFlagAllRoots)
REQUIRES(!Locks::classlinker_classes_lock_, !Locks::trace_lock_)
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index e78d952c1c..dba648e785 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -119,7 +119,7 @@ RUNTIME_OPTIONS_KEY (std::vector<std::string>, \
RUNTIME_OPTIONS_KEY (verifier::VerifyMode, \
Verify, verifier::VerifyMode::kEnable)
RUNTIME_OPTIONS_KEY (int, TargetSdkVersion, Runtime::kUnsetSdkVersion)
-RUNTIME_OPTIONS_KEY (Unit, NoHiddenApiChecks)
+RUNTIME_OPTIONS_KEY (Unit, HiddenApiChecks)
RUNTIME_OPTIONS_KEY (std::string, NativeBridge)
RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10)
RUNTIME_OPTIONS_KEY (Unit, NoDexFileFallback)
@@ -150,5 +150,6 @@ RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullpt
RUNTIME_OPTIONS_KEY (bool, SlowDebug, false)
RUNTIME_OPTIONS_KEY (unsigned int, GlobalRefAllocStackTraceLimit, 0) // 0 = off
+RUNTIME_OPTIONS_KEY (Unit, UseStderrLogger)
#undef RUNTIME_OPTIONS_KEY
diff --git a/runtime/subtype_check.h b/runtime/subtype_check.h
index 54d2f00106..3b1d5f8c4a 100644
--- a/runtime/subtype_check.h
+++ b/runtime/subtype_check.h
@@ -24,6 +24,9 @@
#include "mirror/class.h"
#include "runtime.h"
+// Build flag for the bitstring subtype check runtime hooks.
+constexpr bool kBitstringSubtypeCheckEnabled = false;
+
/**
* Any node in a tree can have its path (from the root to the node) represented as a string by
* concatenating the path of the parent to that of the current node.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 9dc92f3788..2ee7f9deda 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -663,8 +663,8 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
stack_size = FixStackSize(stack_size);
- // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
- // assign it.
+ // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing
+ // to assign it.
env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
reinterpret_cast<jlong>(child_thread));
@@ -839,7 +839,8 @@ Thread* Thread::Attach(const char* thread_name,
if (create_peer) {
self->CreatePeer(thread_name, as_daemon, thread_group);
if (self->IsExceptionPending()) {
- // We cannot keep the exception around, as we're deleting self. Try to be helpful and log it.
+ // We cannot keep the exception around, as we're deleting self. Try to be helpful and log
+ // it.
{
ScopedObjectAccess soa(self);
LOG(ERROR) << "Exception creating thread peer:";
@@ -3435,6 +3436,9 @@ bool Thread::HoldsLock(ObjPtr<mirror::Object> object) const {
return object != nullptr && object->GetLockOwnerThreadId() == GetThreadId();
}
+extern "C" StackReference<mirror::Object>* artQuickGetProxyThisObjectReference(ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// RootVisitor parameters are: (const Object* obj, size_t vreg, const StackVisitor* visitor).
template <typename RootVisitor, bool kPrecise = false>
class ReferenceMapVisitor : public StackVisitor {
@@ -3535,7 +3539,7 @@ class ReferenceMapVisitor : public StackVisitor {
if (!m->IsNative() && !m->IsRuntimeMethod() && (!m->IsProxyMethod() || m->IsConstructor())) {
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
DCHECK(method_header->IsOptimized());
- auto* vreg_base = reinterpret_cast<StackReference<mirror::Object>*>(
+ StackReference<mirror::Object>* vreg_base = reinterpret_cast<StackReference<mirror::Object>*>(
reinterpret_cast<uintptr_t>(cur_quick_frame));
uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
CodeInfo code_info = method_header->GetOptimizedCodeInfo();
@@ -3550,7 +3554,7 @@ class ReferenceMapVisitor : public StackVisitor {
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, map);
for (size_t i = 0; i < number_of_bits; ++i) {
if (stack_mask.LoadBit(i)) {
- auto* ref_addr = vreg_base + i;
+ StackReference<mirror::Object>* ref_addr = vreg_base + i;
mirror::Object* ref = ref_addr->AsMirrorPtr();
if (ref != nullptr) {
mirror::Object* new_ref = ref;
@@ -3579,6 +3583,19 @@ class ReferenceMapVisitor : public StackVisitor {
}
}
}
+ } else if (!m->IsStatic() && !m->IsRuntimeMethod() && m->IsProxyMethod()) {
+ // If this is a non-static proxy method, visit its target (`this` object).
+ DCHECK(!m->IsNative());
+ StackReference<mirror::Object>* ref_addr =
+ artQuickGetProxyThisObjectReference(cur_quick_frame);
+ mirror::Object* ref = ref_addr->AsMirrorPtr();
+ if (ref != nullptr) {
+ mirror::Object* new_ref = ref;
+ visitor_(&new_ref, -1, this);
+ if (ref != new_ref) {
+ ref_addr->Assign(new_ref);
+ }
+ }
}
}
@@ -3773,9 +3790,9 @@ void Thread::VisitRoots(RootVisitor* visitor) {
void Thread::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
if ((flags & VisitRootFlags::kVisitRootFlagPrecise) != 0) {
- VisitRoots<true>(visitor);
+ VisitRoots</* kPrecise */ true>(visitor);
} else {
- VisitRoots<false>(visitor);
+ VisitRoots</* kPrecise */ false>(visitor);
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index afb3224944..66e578f312 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3899,21 +3899,13 @@ ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
}
ObjPtr<mirror::Class> klass = klass_type.GetClass();
const RegType& referrer = GetDeclaringClass();
- auto* cl = Runtime::Current()->GetClassLinker();
- auto pointer_size = cl->GetImagePointerSize();
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ PointerSize pointer_size = class_linker->GetImagePointerSize();
ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
if (res_method == nullptr) {
- // Try to find the method with the appropriate lookup for the klass type (interface or not).
- // If this lookup does not match `method_type`, errors shall be reported below.
- if (klass->IsInterface()) {
- res_method = klass->FindInterfaceMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- } else {
- res_method = klass->FindClassMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- }
- if (res_method != nullptr) {
- dex_cache_->SetResolvedMethod(dex_method_idx, res_method, pointer_size);
- }
+ res_method = class_linker->FindResolvedMethod(
+ klass, dex_cache_.Get(), class_loader_.Get(), dex_method_idx);
}
// Record result of method resolution attempt. The klass resolution has recorded whether
@@ -4432,6 +4424,8 @@ bool MethodVerifier::CheckSignaturePolymorphicMethod(ArtMethod* method) {
expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name);
} else if (klass == mirror::VarHandle::StaticClass()) {
expected_return_descriptor = mirror::VarHandle::GetReturnTypeDescriptor(method_name);
+ // TODO: add compiler support for VarHandle accessor methods (b/71781600)
+ Fail(VERIFY_ERROR_FORCE_INTERPRETER);
} else {
Fail(VERIFY_ERROR_BAD_CLASS_HARD)
<< "Signature polymorphic method in unsuppported class: " << klass->PrettyDescriptor();
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 5564684c4f..30aefede20 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -278,7 +278,7 @@ RegTypeCache::RegTypeCache(bool can_load_classes, ScopedArenaAllocator& allocato
klass_entries_(allocator.Adapter(kArenaAllocVerifier)),
can_load_classes_(can_load_classes),
allocator_(allocator) {
- DCHECK(can_suspend || !can_load_classes) << "Cannot load classes is suspension is disabled!";
+ DCHECK(can_suspend || !can_load_classes) << "Cannot load classes if suspension is disabled!";
if (kIsDebugBuild && can_suspend) {
Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0);
}
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 5fe10f5c12..67ea64be74 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -72,6 +72,7 @@ jclass WellKnownClasses::java_lang_System;
jclass WellKnownClasses::java_lang_Thread;
jclass WellKnownClasses::java_lang_ThreadGroup;
jclass WellKnownClasses::java_lang_Throwable;
+jclass WellKnownClasses::java_nio_ByteBuffer;
jclass WellKnownClasses::java_nio_DirectByteBuffer;
jclass WellKnownClasses::java_util_ArrayList;
jclass WellKnownClasses::java_util_Collections;
@@ -142,6 +143,11 @@ jfieldID WellKnownClasses::java_lang_Throwable_stackState;
jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
jfieldID WellKnownClasses::java_lang_reflect_Executable_artMethod;
jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
+jfieldID WellKnownClasses::java_nio_ByteBuffer_address;
+jfieldID WellKnownClasses::java_nio_ByteBuffer_hb;
+jfieldID WellKnownClasses::java_nio_ByteBuffer_isReadOnly;
+jfieldID WellKnownClasses::java_nio_ByteBuffer_limit;
+jfieldID WellKnownClasses::java_nio_ByteBuffer_offset;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
jfieldID WellKnownClasses::java_util_ArrayList_array;
@@ -277,7 +283,27 @@ uint32_t WellKnownClasses::StringInitToEntryPoint(ArtMethod* string_init) {
}
#undef STRING_INIT_LIST
+class ScopedHiddenApiExemption {
+ public:
+ explicit ScopedHiddenApiExemption(Runtime* runtime)
+ : runtime_(runtime),
+ initially_enabled_(runtime_->AreHiddenApiChecksEnabled()) {
+ runtime_->SetHiddenApiChecksEnabled(false);
+ }
+
+ ~ScopedHiddenApiExemption() {
+ runtime_->SetHiddenApiChecksEnabled(initially_enabled_);
+ }
+
+ private:
+ Runtime* runtime_;
+ const bool initially_enabled_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiExemption);
+};
+
void WellKnownClasses::Init(JNIEnv* env) {
+ ScopedHiddenApiExemption hiddenapi_exemption(Runtime::Current());
+
dalvik_annotation_optimization_CriticalNative =
CacheClass(env, "dalvik/annotation/optimization/CriticalNative");
dalvik_annotation_optimization_FastNative = CacheClass(env, "dalvik/annotation/optimization/FastNative");
@@ -318,6 +344,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Thread = CacheClass(env, "java/lang/Thread");
java_lang_ThreadGroup = CacheClass(env, "java/lang/ThreadGroup");
java_lang_Throwable = CacheClass(env, "java/lang/Throwable");
+ java_nio_ByteBuffer = CacheClass(env, "java/nio/ByteBuffer");
java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer");
java_util_ArrayList = CacheClass(env, "java/util/ArrayList");
java_util_Collections = CacheClass(env, "java/util/Collections");
@@ -379,6 +406,11 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;");
java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
java_lang_reflect_Executable_artMethod = CacheField(env, java_lang_reflect_Executable, false, "artMethod", "J");
+ java_nio_ByteBuffer_address = CacheField(env, java_nio_ByteBuffer, false, "address", "J");
+ java_nio_ByteBuffer_hb = CacheField(env, java_nio_ByteBuffer, false, "hb", "[B");
+ java_nio_ByteBuffer_isReadOnly = CacheField(env, java_nio_ByteBuffer, false, "isReadOnly", "Z");
+ java_nio_ByteBuffer_limit = CacheField(env, java_nio_ByteBuffer, false, "limit", "I");
+ java_nio_ByteBuffer_offset = CacheField(env, java_nio_ByteBuffer, false, "offset", "I");
java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "address", "J");
java_util_ArrayList_array = CacheField(env, java_util_ArrayList, false, "elementData", "[Ljava/lang/Object;");
@@ -462,6 +494,7 @@ void WellKnownClasses::Clear() {
java_lang_Throwable = nullptr;
java_util_ArrayList = nullptr;
java_util_Collections = nullptr;
+ java_nio_ByteBuffer = nullptr;
java_nio_DirectByteBuffer = nullptr;
libcore_reflect_AnnotationFactory = nullptr;
libcore_reflect_AnnotationMember = nullptr;
@@ -530,6 +563,11 @@ void WellKnownClasses::Clear() {
java_lang_Throwable_stackTrace = nullptr;
java_lang_Throwable_stackState = nullptr;
java_lang_Throwable_suppressedExceptions = nullptr;
+ java_nio_ByteBuffer_address = nullptr;
+ java_nio_ByteBuffer_hb = nullptr;
+ java_nio_ByteBuffer_isReadOnly = nullptr;
+ java_nio_ByteBuffer_limit = nullptr;
+ java_nio_ByteBuffer_offset = nullptr;
java_nio_DirectByteBuffer_capacity = nullptr;
java_nio_DirectByteBuffer_effectiveDirectAddress = nullptr;
java_util_ArrayList_array = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 9e0b079b7b..d5d7033132 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -85,6 +85,7 @@ struct WellKnownClasses {
static jclass java_lang_Throwable;
static jclass java_util_ArrayList;
static jclass java_util_Collections;
+ static jclass java_nio_ByteBuffer;
static jclass java_nio_DirectByteBuffer;
static jclass libcore_reflect_AnnotationFactory;
static jclass libcore_reflect_AnnotationMember;
@@ -153,8 +154,14 @@ struct WellKnownClasses {
static jfieldID java_lang_Throwable_stackTrace;
static jfieldID java_lang_Throwable_stackState;
static jfieldID java_lang_Throwable_suppressedExceptions;
+ static jfieldID java_nio_ByteBuffer_address;
+ static jfieldID java_nio_ByteBuffer_hb;
+ static jfieldID java_nio_ByteBuffer_isReadOnly;
+ static jfieldID java_nio_ByteBuffer_limit;
+ static jfieldID java_nio_ByteBuffer_offset;
static jfieldID java_nio_DirectByteBuffer_capacity;
static jfieldID java_nio_DirectByteBuffer_effectiveDirectAddress;
+
static jfieldID java_util_ArrayList_array;
static jfieldID java_util_ArrayList_size;
static jfieldID java_util_Collections_EMPTY_LIST;
diff --git a/test/030-bad-finalizer/expected.txt b/test/030-bad-finalizer/expected.txt
index 74e208c3f9..0aca6f2e93 100644
--- a/test/030-bad-finalizer/expected.txt
+++ b/test/030-bad-finalizer/expected.txt
@@ -2,3 +2,4 @@ About to null reference.
Finalizer started and spinning...
Finalizer done spinning.
Finalizer sleeping forever now.
+exit status: 2
diff --git a/test/911-get-stack-trace/build b/test/030-bad-finalizer/run
index 10ffcc537d..7a0d0d05ab 100644..100755
--- a/test/911-get-stack-trace/build
+++ b/test/030-bad-finalizer/run
@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
+# Squash the exit status and put it in expected
+./default-run "$@"
+echo "exit status:" $?
diff --git a/test/034-call-null/expected.txt b/test/034-call-null/expected.txt
index 4e0281e556..11aefde417 100644
--- a/test/034-call-null/expected.txt
+++ b/test/034-call-null/expected.txt
@@ -1,2 +1,3 @@
Exception in thread "main" java.lang.NullPointerException: Attempt to invoke direct method 'void Main.doStuff(int, int[][], java.lang.String, java.lang.String[][])' on a null object reference
at Main.main(Main.java:26)
+exit status: 1
diff --git a/test/1937-transform-soft-fail/check b/test/034-call-null/run
index 7cee530291..7a0d0d05ab 100755
--- a/test/1937-transform-soft-fail/check
+++ b/test/034-call-null/run
@@ -1,12 +1,12 @@
#!/bin/bash
#
-# Copyright (C) 2017 The Android Open Source Project
+# Copyright 2017 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
+# 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,
@@ -14,6 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-sed -e 's/:.*$//' "$2" > "$2.tmp"
-
-./default-check "$1" "$2.tmp"
+# Squash the exit status and put it in expected
+./default-run "$@"
+echo "exit status:" $?
diff --git a/test/038-inner-null/expected.txt b/test/038-inner-null/expected.txt
index 2e925644e3..d148eff407 100644
--- a/test/038-inner-null/expected.txt
+++ b/test/038-inner-null/expected.txt
@@ -2,3 +2,4 @@ new Special()
Exception in thread "main" java.lang.NullPointerException: Attempt to invoke virtual method 'void Main$Blort.repaint()' on a null object reference
at Main$Special.callInner(Main.java:31)
at Main.main(Main.java:20)
+exit status: 1
diff --git a/test/038-inner-null/run b/test/038-inner-null/run
new file mode 100755
index 0000000000..7a0d0d05ab
--- /dev/null
+++ b/test/038-inner-null/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# Squash the exit status and put it in expected
+./default-run "$@"
+echo "exit status:" $?
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index b8a48ea247..6d6cc132d1 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -232,10 +232,10 @@ public class Main {
field.set(instance, null);
/*
- * Try getDeclaredField on a non-existant field.
+ * Try getDeclaredField on a non-existent field.
*/
try {
- field = target.getDeclaredField("nonExistant");
+ field = target.getDeclaredField("nonExistent");
System.out.println("ERROR: Expected NoSuchFieldException");
} catch (NoSuchFieldException nsfe) {
String msg = nsfe.getMessage();
diff --git a/test/054-uncaught/expected.txt b/test/054-uncaught/expected.txt
index 7d7f03c3a7..878260a07d 100644
--- a/test/054-uncaught/expected.txt
+++ b/test/054-uncaught/expected.txt
@@ -18,3 +18,4 @@ Uncaught exception DEFAULT!
java.lang.NullPointerException: Hi diddly-ho, neighborino.
at Main.catchTheUncaught(Main.java:63)
at Main.main(Main.java:26)
+exit status: 1
diff --git a/test/054-uncaught/run b/test/054-uncaught/run
new file mode 100755
index 0000000000..7a0d0d05ab
--- /dev/null
+++ b/test/054-uncaught/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# Squash the exit status and put it in expected
+./default-run "$@"
+echo "exit status:" $?
diff --git a/test/075-verification-error/src/Main.java b/test/075-verification-error/src/Main.java
index 13aeaee7e4..2519de5132 100644
--- a/test/075-verification-error/src/Main.java
+++ b/test/075-verification-error/src/Main.java
@@ -31,7 +31,7 @@ public class Main {
testBadInterfaceMethod();
}
/**
- * Try to create and invoke a non-existant interface method.
+ * Try to create and invoke a non-existent interface method.
*/
static void testBadInterfaceMethod() {
BadInterface badiface = new BadIfaceImpl();
diff --git a/test/134-nodex2oat-nofallback/run b/test/134-nodex2oat-nofallback/run
index 38b4adb183..33265ac471 100755
--- a/test/134-nodex2oat-nofallback/run
+++ b/test/134-nodex2oat-nofallback/run
@@ -18,3 +18,5 @@ flags="${@}"
# Make sure we cannot run without an oat file without fallback.
${RUN} ${flags} --runtime-option -Xnodex2oat --runtime-option -Xno-dex-file-fallback
+# Suppress the exit value. This isn't expected to be successful.
+echo "Exit status:" $?
diff --git a/test/1917-get-stack-frame/expected.txt b/test/1917-get-stack-frame/expected.txt
index 4c9efcf157..06f5873d76 100644
--- a/test/1917-get-stack-frame/expected.txt
+++ b/test/1917-get-stack-frame/expected.txt
@@ -1,6 +1,6 @@
Recurring 5 times
'private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread)' line: -1
-'public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread)' line: 60
+'public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread)' line: 61
'public void art.Test1917$StackTraceGenerator.run()' line: 82
'public void art.Test1917$RecurCount.doRecur(int)' line: 104
'public void art.Test1917$RecurCount.doRecur(int)' line: 102
@@ -12,7 +12,7 @@ Recurring 5 times
'public static void art.Test1917.run() throws java.lang.Exception' line: 133
Recurring 5 times on another thread
'private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread)' line: -1
-'public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread)' line: 60
+'public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread)' line: 61
'public void art.Test1917$StackTraceGenerator.run()' line: 82
'public void art.Test1917$RecurCount.doRecur(int)' line: 104
'public void art.Test1917$RecurCount.doRecur(int)' line: 102
diff --git a/test/1917-get-stack-frame/src/art/StackTrace.java b/test/1917-get-stack-frame/src/art/StackTrace.java
index b12c3df66b..2ea2f201e8 100644
--- a/test/1917-get-stack-frame/src/art/StackTrace.java
+++ b/test/1917-get-stack-frame/src/art/StackTrace.java
@@ -53,7 +53,8 @@ public class StackTrace {
// consistent we will suspend for the RI.
boolean suspend_thread =
!System.getProperty("java.vm.name").equals("Dalvik") &&
- !thr.equals(Thread.currentThread());
+ !thr.equals(Thread.currentThread()) &&
+ !Suspension.isSuspended(thr);
if (suspend_thread) {
Suspension.suspend(thr);
}
diff --git a/test/1927-exception-event/expected.txt b/test/1927-exception-event/expected.txt
index be8f39c29a..fcdd814977 100644
--- a/test/1927-exception-event/expected.txt
+++ b/test/1927-exception-event/expected.txt
@@ -3,7 +3,7 @@ Running test_J
main: public static void art.Test1927.test_J() @ line = 110 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.test_J() @ line = 110
@@ -12,7 +12,7 @@ main: public static void art.Test1927.test_J() @ line = 110 throws class art.Tes
main: public static void art.Test1927.test_J() @ line = 111 caught class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J() @ line = 111
@@ -24,7 +24,7 @@ Running test_J_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -34,7 +34,7 @@ main: public static void art.Test1927.terminal_J() @ line = 103 throws class art
main: public static void art.Test1927.test_J_J() @ line = 122 caught class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_J() @ line = 122
@@ -44,7 +44,7 @@ Running test_J_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -54,7 +54,7 @@ main: public static native void art.Test1927.terminal_N() @ line = -1 throws cla
main: public static void art.Test1927.test_J_N() @ line = 130 caught class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_N() @ line = 130
@@ -64,7 +64,7 @@ Running test_N_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -76,7 +76,7 @@ Running test_N_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -88,7 +88,7 @@ Running test_J_J_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -99,7 +99,7 @@ main: public static void art.Test1927.terminal_J() @ line = 103 throws class art
main: public static void art.Test1927.test_J_J_J() @ line = 146 caught class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_J_J() @ line = 146
@@ -109,7 +109,7 @@ Running test_J_J_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -120,7 +120,7 @@ main: public static native void art.Test1927.terminal_N() @ line = -1 throws cla
main: public static void art.Test1927.test_J_J_N() @ line = 154 caught class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_J_N() @ line = 154
@@ -130,7 +130,7 @@ Running test_J_N_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -141,7 +141,7 @@ main: public static void art.Test1927.terminal_J() @ line = 103 throws class art
main: public static void art.Test1927.test_J_N_J() @ line = 162 caught class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_N_J() @ line = 162
@@ -151,7 +151,7 @@ Running test_J_N_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -162,7 +162,7 @@ main: public static native void art.Test1927.terminal_N() @ line = -1 throws cla
main: public static void art.Test1927.test_J_N_N() @ line = 170 caught class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 43
public static void art.Test1927.test_J_N_N() @ line = 170
@@ -172,7 +172,7 @@ Running test_N_J_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -185,7 +185,7 @@ Running test_N_J_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -198,7 +198,7 @@ Running test_N_N_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -211,7 +211,7 @@ Running test_N_N_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -224,7 +224,7 @@ Running test_extra_N_J_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -238,7 +238,7 @@ Running test_extra_N_J_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
@@ -252,7 +252,7 @@ Running test_extra_N_N_J()
main: public static void art.Test1927.terminal_J() @ line = 103 throws class art.Test1927$TestException: from java
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static void art.Test1927.terminal_J() @ line = 103
@@ -266,7 +266,7 @@ Running test_extra_N_N_N()
main: public static native void art.Test1927.terminal_N() @ line = -1 throws class art.Test1927$TestException: from native
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1927.PrintStack() @ line = 28
public static void art.Test1927.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 66
public static native void art.Test1927.terminal_N() @ line = -1
diff --git a/test/1927-exception-event/src/art/StackTrace.java b/test/1927-exception-event/src/art/StackTrace.java
index b12c3df66b..2ea2f201e8 100644
--- a/test/1927-exception-event/src/art/StackTrace.java
+++ b/test/1927-exception-event/src/art/StackTrace.java
@@ -53,7 +53,8 @@ public class StackTrace {
// consistent we will suspend for the RI.
boolean suspend_thread =
!System.getProperty("java.vm.name").equals("Dalvik") &&
- !thr.equals(Thread.currentThread());
+ !thr.equals(Thread.currentThread()) &&
+ !Suspension.isSuspended(thr);
if (suspend_thread) {
Suspension.suspend(thr);
}
diff --git a/test/1928-exception-event-exception/expected.txt b/test/1928-exception-event-exception/expected.txt
index 1692d042e4..73c69727aa 100644
--- a/test/1928-exception-event-exception/expected.txt
+++ b/test/1928-exception-event-exception/expected.txt
@@ -2,235 +2,119 @@ Test "art.Test1928$DoThrowClass": Running with handler "art.Test1928$DoNothingHa
main: public static void art.Test1928.doThrow() @ line = 110 throws class art.Test1928$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.doThrow() @ line = 110
public void art.Test1928$DoThrowClass.run() @ line = 114
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
-exception is: art.Test1928$TestException: doThrow
- at art.Test1928.doThrow(Test1928.java:110)
- at art.Test1928$DoThrowClass.run(Test1928.java:114)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Doing nothing!
Test "art.Test1928$DoThrowClass": Caught error art.Test1928$TestException:"doThrow" with handler "art.Test1928$DoNothingHandler"
-art.Test1928$TestException: doThrow
- at art.Test1928.doThrow(Test1928.java:110)
- at art.Test1928$DoThrowClass.run(Test1928.java:114)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowClass": Finished running with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowCatchBaseTestException": Running with handler "art.Test1928$DoNothingHandler"
main: public static void art.Test1928.throwCatchBaseTestException() @ line = 119 throws class art.Test1928$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchBaseTestException() @ line = 119
public void art.Test1928$DoThrowCatchBaseTestException.run() @ line = 129
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.throwCatchBaseTestException() @ line = 120
-exception is: art.Test1928$TestException: throwCatchBaseTestException
- at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
- at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Doing nothing!
Caught art.Test1928$TestException: "throwCatchBaseTestException"
-art.Test1928$TestException: throwCatchBaseTestException
- at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
- at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchBaseTestException": No error caught with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowCatchBaseTestException": Finished running with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowCatchTestException": Running with handler "art.Test1928$DoNothingHandler"
main: public static void art.Test1928.throwCatchTestException() @ line = 134 throws class art.Test1928$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchTestException() @ line = 134
public void art.Test1928$DoThrowCatchTestException.run() @ line = 144
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.throwCatchTestException() @ line = 135
-exception is: art.Test1928$TestException: throwCatchTestException
- at art.Test1928.throwCatchTestException(Test1928.java:134)
- at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Doing nothing!
Caught art.Test1928$TestException: "throwCatchTestException"
-art.Test1928$TestException: throwCatchTestException
- at art.Test1928.throwCatchTestException(Test1928.java:134)
- at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchTestException": No error caught with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowCatchTestException": Finished running with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Running with handler "art.Test1928$DoNothingHandler"
main: public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149 throws class art.Test1928$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
public void art.Test1928$DoThrowCatchTestExceptionNoRethrow.run() @ line = 159
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
-exception is: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
- at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
- at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Doing nothing!
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1928$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1928$DoNothingHandler"
-art.Test1928$TestException: throwCatchTestExceptionNoRethrow
- at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
- at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1928$DoNothingHandler"
Test "art.Test1928$DoThrowClass": Running with handler "art.Test1928$ThrowCatchBase"
main: public static void art.Test1928.doThrow() @ line = 110 throws class art.Test1928$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.doThrow() @ line = 110
public void art.Test1928$DoThrowClass.run() @ line = 114
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
-exception is: art.Test1928$TestException: doThrow
- at art.Test1928.doThrow(Test1928.java:110)
- at art.Test1928$DoThrowClass.run(Test1928.java:114)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Throwing BaseTestException and catching it!
Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.doThrow() @ line = 110"
-art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.doThrow() @ line = 110
- at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
- at art.Test1928.ExceptionEvent(Test1928.java:66)
- at art.Test1928.doThrow(Test1928.java:110)
- at art.Test1928$DoThrowClass.run(Test1928.java:114)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
-Caused by: art.Test1928$TestException: doThrow
- ... 4 more
Test "art.Test1928$DoThrowClass": Caught error art.Test1928$TestException:"doThrow" with handler "art.Test1928$ThrowCatchBase"
-art.Test1928$TestException: doThrow
- at art.Test1928.doThrow(Test1928.java:110)
- at art.Test1928$DoThrowClass.run(Test1928.java:114)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowClass": Finished running with handler "art.Test1928$ThrowCatchBase"
Test "art.Test1928$DoThrowCatchBaseTestException": Running with handler "art.Test1928$ThrowCatchBase"
main: public static void art.Test1928.throwCatchBaseTestException() @ line = 119 throws class art.Test1928$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchBaseTestException() @ line = 119
public void art.Test1928$DoThrowCatchBaseTestException.run() @ line = 129
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.throwCatchBaseTestException() @ line = 120
-exception is: art.Test1928$TestException: throwCatchBaseTestException
- at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
- at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Throwing BaseTestException and catching it!
Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchBaseTestException() @ line = 119"
-art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchBaseTestException() @ line = 119
- at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
- at art.Test1928.ExceptionEvent(Test1928.java:66)
- at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
- at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
-Caused by: art.Test1928$TestException: throwCatchBaseTestException
- ... 4 more
Caught art.Test1928$TestException: "throwCatchBaseTestException"
-art.Test1928$TestException: throwCatchBaseTestException
- at art.Test1928.throwCatchBaseTestException(Test1928.java:119)
- at art.Test1928$DoThrowCatchBaseTestException.run(Test1928.java:129)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchBaseTestException": No error caught with handler "art.Test1928$ThrowCatchBase"
Test "art.Test1928$DoThrowCatchBaseTestException": Finished running with handler "art.Test1928$ThrowCatchBase"
Test "art.Test1928$DoThrowCatchTestException": Running with handler "art.Test1928$ThrowCatchBase"
main: public static void art.Test1928.throwCatchTestException() @ line = 134 throws class art.Test1928$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchTestException() @ line = 134
public void art.Test1928$DoThrowCatchTestException.run() @ line = 144
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.throwCatchTestException() @ line = 135
-exception is: art.Test1928$TestException: throwCatchTestException
- at art.Test1928.throwCatchTestException(Test1928.java:134)
- at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Throwing BaseTestException and catching it!
Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestException() @ line = 134"
-art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestException() @ line = 134
- at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
- at art.Test1928.ExceptionEvent(Test1928.java:66)
- at art.Test1928.throwCatchTestException(Test1928.java:134)
- at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
-Caused by: art.Test1928$TestException: throwCatchTestException
- ... 4 more
Caught art.Test1928$TestException: "throwCatchTestException"
-art.Test1928$TestException: throwCatchTestException
- at art.Test1928.throwCatchTestException(Test1928.java:134)
- at art.Test1928$DoThrowCatchTestException.run(Test1928.java:144)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchTestException": No error caught with handler "art.Test1928$ThrowCatchBase"
Test "art.Test1928$DoThrowCatchTestException": Finished running with handler "art.Test1928$ThrowCatchBase"
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Running with handler "art.Test1928$ThrowCatchBase"
main: public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149 throws class art.Test1928$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1928.PrintStack() @ line = 35
public static void art.Test1928.ExceptionEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable,java.lang.reflect.Executable,long) @ line = 59
public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
public void art.Test1928$DoThrowCatchTestExceptionNoRethrow.run() @ line = 159
public static void art.Test1928.run() throws java.lang.Exception @ line = 196
Will be caught by: public static void art.Test1928.run() throws java.lang.Exception @ line = 199
-exception is: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
- at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
- at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Throwing BaseTestException and catching it!
Caught art.Test1928$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149"
-art.Test1928$BaseTestException: ThrowBaseHandler during throw from public static void art.Test1928.throwCatchTestExceptionNoRethrow() @ line = 149
- at art.Test1928$ThrowCatchBase.exceptionOccurred(Test1928.java:99)
- at art.Test1928.ExceptionEvent(Test1928.java:66)
- at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
- at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
-Caused by: art.Test1928$TestException: throwCatchTestExceptionNoRethrow
- ... 4 more
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1928$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1928$ThrowCatchBase"
-art.Test1928$TestException: throwCatchTestExceptionNoRethrow
- at art.Test1928.throwCatchTestExceptionNoRethrow(Test1928.java:149)
- at art.Test1928$DoThrowCatchTestExceptionNoRethrow.run(Test1928.java:159)
- at art.Test1928.run(Test1928.java:196)
- at Main.main(Main.java:19)
Test "art.Test1928$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1928$ThrowCatchBase"
diff --git a/test/1928-exception-event-exception/src/art/StackTrace.java b/test/1928-exception-event-exception/src/art/StackTrace.java
index b12c3df66b..2ea2f201e8 100644
--- a/test/1928-exception-event-exception/src/art/StackTrace.java
+++ b/test/1928-exception-event-exception/src/art/StackTrace.java
@@ -53,7 +53,8 @@ public class StackTrace {
// consistent we will suspend for the RI.
boolean suspend_thread =
!System.getProperty("java.vm.name").equals("Dalvik") &&
- !thr.equals(Thread.currentThread());
+ !thr.equals(Thread.currentThread()) &&
+ !Suspension.isSuspended(thr);
if (suspend_thread) {
Suspension.suspend(thr);
}
diff --git a/test/1928-exception-event-exception/src/art/Test1928.java b/test/1928-exception-event-exception/src/art/Test1928.java
index aec88a4079..864de8ea4d 100644
--- a/test/1928-exception-event-exception/src/art/Test1928.java
+++ b/test/1928-exception-event-exception/src/art/Test1928.java
@@ -22,7 +22,7 @@ import java.lang.reflect.Executable;
import java.lang.reflect.Method;
public class Test1928 {
- public static boolean PRINT_FULL_EXCEPTION = true;
+ public static boolean PRINT_FULL_EXCEPTION = false;
public static ExceptionHandler HANDLER = null;
public static interface ExceptionHandler {
diff --git a/test/1929-exception-catch-exception/expected.txt b/test/1929-exception-catch-exception/expected.txt
index 7c23a31439..bc5608ac4e 100644
--- a/test/1929-exception-catch-exception/expected.txt
+++ b/test/1929-exception-catch-exception/expected.txt
@@ -2,7 +2,7 @@ Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -12,7 +12,7 @@ Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handl
main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
@@ -26,7 +26,7 @@ Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with
main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
@@ -40,7 +40,7 @@ Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "
main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchTestException() @ line = 207
@@ -54,7 +54,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with hand
main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
@@ -68,7 +68,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -78,7 +78,7 @@ Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -88,7 +88,7 @@ Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handl
main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
@@ -103,7 +103,7 @@ Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with
main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
@@ -117,7 +117,7 @@ Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "
main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchTestException() @ line = 207
@@ -132,7 +132,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with hand
main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
@@ -146,7 +146,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -156,7 +156,7 @@ Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -166,7 +166,7 @@ Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handl
main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
@@ -179,7 +179,7 @@ Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with
main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
@@ -193,7 +193,7 @@ Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "
main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchTestException() @ line = 207
@@ -206,7 +206,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with hand
main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
@@ -220,7 +220,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -230,7 +230,7 @@ Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
@@ -240,7 +240,7 @@ Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handl
main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140 caught class art.Test1929$TestException: throwCatchBaseTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
@@ -253,7 +253,7 @@ Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with
main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
@@ -267,7 +267,7 @@ Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "
main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchTestException() @ line = 207
@@ -280,7 +280,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with hand
main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
@@ -294,7 +294,7 @@ Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with
main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
- public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 60
+ public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.run() throws java.lang.Exception @ line = 283
diff --git a/test/1929-exception-catch-exception/src/art/StackTrace.java b/test/1929-exception-catch-exception/src/art/StackTrace.java
index b12c3df66b..2ea2f201e8 100644
--- a/test/1929-exception-catch-exception/src/art/StackTrace.java
+++ b/test/1929-exception-catch-exception/src/art/StackTrace.java
@@ -53,7 +53,8 @@ public class StackTrace {
// consistent we will suspend for the RI.
boolean suspend_thread =
!System.getProperty("java.vm.name").equals("Dalvik") &&
- !thr.equals(Thread.currentThread());
+ !thr.equals(Thread.currentThread()) &&
+ !Suspension.isSuspended(thr);
if (suspend_thread) {
Suspension.suspend(thr);
}
diff --git a/test/1937-transform-soft-fail/src/art/Test1937.java b/test/1937-transform-soft-fail/src/art/Test1937.java
index 7255a5ef96..19fa24e3f8 100644
--- a/test/1937-transform-soft-fail/src/art/Test1937.java
+++ b/test/1937-transform-soft-fail/src/art/Test1937.java
@@ -19,6 +19,8 @@ package art;
import java.util.Base64;
public class Test1937 {
+ private static final boolean PRINT_MESSAGE = false;
+
static class Transform {
public void sayHi() {
// Use lower 'h' to make sure the string will have a different string id
@@ -83,7 +85,10 @@ public class Test1937 {
try {
t.sayHi();
} catch (Throwable e) {
- System.out.println("Caught exception " + e.getClass().getName() + ": " + e.getMessage());
+ System.out.println("Caught exception " + e.getClass().getName());
+ if (PRINT_MESSAGE) {
+ System.out.println("Message: " + e.getMessage());
+ }
}
}
}
diff --git a/test/1939-proxy-frames/expected.txt b/test/1939-proxy-frames/expected.txt
index a4c97c9bbe..3aafd16a08 100644
--- a/test/1939-proxy-frames/expected.txt
+++ b/test/1939-proxy-frames/expected.txt
@@ -5,4 +5,4 @@ Running public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Run
Running public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Runnable) with "GetProxyFrameLocation" on remote thread.
"GetProxyFrameLocation" on public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Runnable) got value: -1
Running public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Runnable) with "GetProxyFrameMethod" on remote thread.
-"GetProxyFrameMethod" on public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Runnable) got value: public final void $Proxy0.InterfaceProxyMethod(java.lang.Runnable)
+"GetProxyFrameMethod" on public abstract void art.Test1939$Foo.InterfaceProxyMethod(java.lang.Runnable) got value: public final void $__PROXY__.InterfaceProxyMethod(java.lang.Runnable)
diff --git a/test/1939-proxy-frames/src/art/Test1939.java b/test/1939-proxy-frames/src/art/Test1939.java
index 83d0d2ca4b..5e86e54c0d 100644
--- a/test/1939-proxy-frames/src/art/Test1939.java
+++ b/test/1939-proxy-frames/src/art/Test1939.java
@@ -44,12 +44,22 @@ public class Test1939 {
public Object GetVar(Thread t, int depth);
}
+ public static String SafeToString(Object o) {
+ if (o instanceof Method && Proxy.isProxyClass(((Method)o).getDeclaringClass())) {
+ // TODO This currently only really works on ART. It would be good if we could make it work for
+ // the RI as well.
+ return o.toString().replaceFirst("Proxy[0-9]+", "__PROXY__");
+ } else {
+ return o.toString();
+ }
+ }
+
public static SafepointFunction NamedGet(final String type, final GetterFunction get) {
return new SafepointFunction() {
public void invoke(Thread t, Method method, int depth) {
try {
Object res = get.GetVar(t, depth);
- System.out.println(this + " on " + method + " got value: " + res);
+ System.out.println(this + " on " + method + " got value: " + SafeToString(res));
} catch (Exception e) {
System.out.println(this + " on " + method + " failed due to " + e.getMessage());
}
diff --git a/test/1944-sudden-exit/check b/test/1944-sudden-exit/check
new file mode 100755
index 0000000000..591fbb87ee
--- /dev/null
+++ b/test/1944-sudden-exit/check
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# 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.
+
+# The number of paused background threads (and therefore InterruptedExceptions)
+# can change so we will just delete their lines from the log.
+
+# Pure virtual function can be printed because sudden exits are not really
+# supported. It is an error message but the test is to make sure that we exit
+# with the right exit code.
+cat "$2" \
+ | sed "/Pure virtual function called!/d" \
+ | diff --strip-trailing-cr -q "$1" - >/dev/null
diff --git a/test/1944-sudden-exit/expected.txt b/test/1944-sudden-exit/expected.txt
new file mode 100644
index 0000000000..4c6eb47fa7
--- /dev/null
+++ b/test/1944-sudden-exit/expected.txt
@@ -0,0 +1,3 @@
+All threads started
+Exiting suddenly
+exit status: 12
diff --git a/test/1944-sudden-exit/info.txt b/test/1944-sudden-exit/info.txt
new file mode 100644
index 0000000000..d575ce5864
--- /dev/null
+++ b/test/1944-sudden-exit/info.txt
@@ -0,0 +1,5 @@
+Test to make sure the runtime will not crash if an agent calls exit(3) while
+other threads are performing operations.
+
+In this case we have multiple threads all performing single stepping when we
+call exit(3).
diff --git a/test/1944-sudden-exit/run b/test/1944-sudden-exit/run
new file mode 100755
index 0000000000..eb601fd348
--- /dev/null
+++ b/test/1944-sudden-exit/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
+echo "exit status: " $?
diff --git a/runtime/native/java_lang_Void.h b/test/1944-sudden-exit/src/Main.java
index 8777d8068c..1644c6ef0c 100644
--- a/runtime/native/java_lang_Void.h
+++ b/test/1944-sudden-exit/src/Main.java
@@ -14,15 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_
-
-#include <jni.h>
-
-namespace art {
-
-void register_java_lang_Void(JNIEnv* env);
-
-} // namespace art
-
-#endif // ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_
+public class Main {
+ public static void main(String[] args) throws Exception {
+ art.Test1944.run();
+ }
+}
diff --git a/test/1944-sudden-exit/src/art/Test1944.java b/test/1944-sudden-exit/src/art/Test1944.java
new file mode 100644
index 0000000000..36cbb2b390
--- /dev/null
+++ b/test/1944-sudden-exit/src/art/Test1944.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package art;
+
+import java.util.Arrays;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.concurrent.Semaphore;
+
+public class Test1944 {
+ // Just calculate fib forever.
+ public static void fib(Semaphore started) {
+ started.release();
+ long a = 1;
+ long b = 1;
+ while (true) {
+ long c = a + b;
+ a = b;
+ b = c;
+ }
+ }
+
+ // Don't bother actually doing anything.
+ public static void notifySingleStep(Thread thr, Executable e, long loc) { }
+
+ public static native void exitNow();
+
+ private static int num_threads = 10;
+
+ public static void run() throws Exception {
+ final Semaphore started = new Semaphore(-(num_threads - 1));
+
+ Trace.enableSingleStepTracing(Test1944.class,
+ Test1944.class.getDeclaredMethod(
+ "notifySingleStep", Thread.class, Executable.class, Long.TYPE),
+ null);
+
+ Thread[] threads = new Thread[num_threads];
+ for (int i = 0; i < num_threads; i++) {
+ threads[i] = new Thread(() -> { fib(started); });
+ // Make half daemons.
+ threads[i].setDaemon(i % 2 == 0);
+ threads[i].start();
+ }
+ // Wait for all threads to start.
+ started.acquire();
+ System.out.println("All threads started");
+ // sleep a little
+ Thread.sleep(10);
+ // Die.
+ System.out.println("Exiting suddenly");
+ exitNow();
+ System.out.println("FAILED: Should not reach here!");
+ }
+}
diff --git a/test/1944-sudden-exit/src/art/Trace.java b/test/1944-sudden-exit/src/art/Trace.java
new file mode 100644
index 0000000000..8999bb1368
--- /dev/null
+++ b/test/1944-sudden-exit/src/art/Trace.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Trace {
+ public static native void enableTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Thread thr);
+ public static native void disableTracing(Thread thr);
+
+ public static void enableFieldTracing(Class<?> methodClass,
+ Method fieldAccess,
+ Method fieldModify,
+ Thread thr) {
+ enableTracing(methodClass, null, null, fieldAccess, fieldModify, null, thr);
+ }
+
+ public static void enableMethodTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Thread thr) {
+ enableTracing(methodClass, entryMethod, exitMethod, null, null, null, thr);
+ }
+
+ public static void enableSingleStepTracing(Class<?> methodClass,
+ Method singleStep,
+ Thread thr) {
+ enableTracing(methodClass, null, null, null, null, singleStep, thr);
+ }
+
+ public static native void watchFieldAccess(Field f);
+ public static native void watchFieldModification(Field f);
+ public static native void watchAllFieldAccesses();
+ public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
+}
diff --git a/test/983-source-transform-verify/source_transform.h b/test/1944-sudden-exit/sudden_exit.cc
index db9415aec1..e0a076efac 100644
--- a/test/983-source-transform-verify/source_transform.h
+++ b/test/1944-sudden-exit/sudden_exit.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-#ifndef ART_TEST_983_SOURCE_TRANSFORM_VERIFY_SOURCE_TRANSFORM_H_
-#define ART_TEST_983_SOURCE_TRANSFORM_VERIFY_SOURCE_TRANSFORM_H_
-
-#include <jni.h>
+#include <stdlib.h>
+#include "jni.h"
namespace art {
-namespace Test983SourceTransformVerify {
+namespace Test1944SuddenExit {
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1944_exitNow(JNIEnv*, jclass)
+ __attribute__((noreturn));
-jint OnLoad(JavaVM* vm, char* options, void* reserved);
+extern "C" JNIEXPORT void JNICALL Java_art_Test1944_exitNow(JNIEnv*, jclass) {
+ exit(12);
+}
-} // namespace Test983SourceTransformVerify
+} // namespace Test1944SuddenExit
} // namespace art
-#endif // ART_TEST_983_SOURCE_TRANSFORM_VERIFY_SOURCE_TRANSFORM_H_
diff --git a/test/670-bitstring-type-check/build b/test/670-bitstring-type-check/build
new file mode 100644
index 0000000000..38307f2c0f
--- /dev/null
+++ b/test/670-bitstring-type-check/build
@@ -0,0 +1,216 @@
+#!/bin/bash
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# Write out the source file.
+
+mkdir src
+cat >src/Main.java <<EOF
+/*
+ * 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.
+ */
+
+EOF
+
+for i in {0..8192}; do echo "class Level1Class$i { }" >>src/Main.java; done
+for i in {0..1024}; do echo "class Level2Class$i extends Level1Class0 { }" >>src/Main.java; done
+
+cat >>src/Main.java <<EOF
+class Level3Class0 extends Level2Class0 { }
+class Level4Class0 extends Level3Class0 { }
+class Level5Class0 extends Level4Class0 { }
+class Level6Class0 extends Level5Class0 { }
+class Level7Class0 extends Level6Class0 { }
+class Level8Class0 extends Level7Class0 { }
+class Level9Class0 extends Level8Class0 { }
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ // 8193 classes at level 1 make sure we shall have an overflow if there are 13 or
+ // less bits for the level 1 character. 1025 classes at level 2 similarly guarantees
+ // an overflow if the number of bits for level 2 character is 10 or less. To test
+ // type checks also for the depth overflow, we provide a hierarchy 9 levels deep.
+
+ // Make sure the bitstrings are initialized.
+ for (int i = 0; i <= 8192; ++i) {
+ Class.forName("Level1Class" + i).newInstance();
+ }
+ for (int i = 0; i <= 1024; ++i) {
+ Class.forName("Level2Class" + i).newInstance();
+ }
+
+ // Note: Using a different class for tests so that verification of Main.main() does
+ // not try to resolve classes used by the tests. This guarantees uninitialized type
+ // check bitstrings when we enter Main.main() and start initializing them above.
+ Helper.testInstanceOf();
+ Helper.testCheckCast();
+ }
+}
+
+class Helper {
+ public static void testInstanceOf() throws Exception {
+ for (int i = 1; i <= 9; ++i) {
+ Object o = createInstance("Level" + i + "Class0");
+ assertTrue(o instanceof Level1Class0);
+ if (o instanceof Level2Class0) {
+ assertFalse(i < 2);
+ } else {
+ assertTrue(i < 2);
+ }
+ if (o instanceof Level3Class0) {
+ assertFalse(i < 3);
+ } else {
+ assertTrue(i < 3);
+ }
+ if (o instanceof Level4Class0) {
+ assertFalse(i < 4);
+ } else {
+ assertTrue(i < 4);
+ }
+ if (o instanceof Level5Class0) {
+ assertFalse(i < 5);
+ } else {
+ assertTrue(i < 5);
+ }
+ if (o instanceof Level6Class0) {
+ assertFalse(i < 6);
+ } else {
+ assertTrue(i < 6);
+ }
+ if (o instanceof Level7Class0) {
+ assertFalse(i < 7);
+ } else {
+ assertTrue(i < 7);
+ }
+ if (o instanceof Level8Class0) {
+ assertFalse(i < 8);
+ } else {
+ assertTrue(i < 8);
+ }
+ if (o instanceof Level9Class0) {
+ assertFalse(i < 9);
+ } else {
+ assertTrue(i < 9);
+ }
+ }
+
+ assertTrue(createInstance("Level1Class8192") instanceof Level1Class8192);
+ assertFalse(createInstance("Level1Class8192") instanceof Level1Class0);
+ assertTrue(createInstance("Level2Class1024") instanceof Level2Class1024);
+ assertTrue(createInstance("Level2Class1024") instanceof Level1Class0);
+ assertFalse(createInstance("Level2Class1024") instanceof Level2Class0);
+ }
+
+ public static void testCheckCast() throws Exception {
+ for (int i = 1; i <= 9; ++i) {
+ Object o = createInstance("Level" + i + "Class0");
+ Level1Class0 l1c0 = (Level1Class0) o;
+ try {
+ Level2Class0 l2c0 = (Level2Class0) o;
+ assertFalse(i < 2);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 2);
+ }
+ try {
+ Level3Class0 l3c0 = (Level3Class0) o;
+ assertFalse(i < 3);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 3);
+ }
+ try {
+ Level4Class0 l4c0 = (Level4Class0) o;
+ assertFalse(i < 4);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 4);
+ }
+ try {
+ Level5Class0 l5c0 = (Level5Class0) o;
+ assertFalse(i < 5);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 5);
+ }
+ try {
+ Level6Class0 l6c0 = (Level6Class0) o;
+ assertFalse(i < 6);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 6);
+ }
+ try {
+ Level7Class0 l7c0 = (Level7Class0) o;
+ assertFalse(i < 7);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 7);
+ }
+ try {
+ Level8Class0 l8c0 = (Level8Class0) o;
+ assertFalse(i < 8);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 8);
+ }
+ try {
+ Level9Class0 l9c0 = (Level9Class0) o;
+ assertFalse(i < 9);
+ } catch (ClassCastException cce) {
+ assertTrue(i < 9);
+ }
+ }
+
+ Level1Class8192 l1c8192 = (Level1Class8192) createInstance("Level1Class8192");
+ try {
+ Level1Class0 l1c0 = (Level1Class0) createInstance("Level1Class8192");
+ throw new AssertionError("Unexpected");
+ } catch (ClassCastException expected) {}
+ Level2Class1024 l2c1024 = (Level2Class1024) createInstance("Level2Class1024");
+ Level1Class0 l1c0 = (Level1Class0) createInstance("Level2Class1024");
+ try {
+ Level2Class0 l2c0 = (Level2Class0) createInstance("Level2Class1024");
+ throw new AssertionError("Unexpected");
+ } catch (ClassCastException expected) {}
+ }
+
+ public static Object createInstance(String className) throws Exception {
+ return Class.forName(className).newInstance();
+ }
+
+ public static void assertTrue(boolean value) throws Exception {
+ if (!value) {
+ throw new AssertionError();
+ }
+ }
+
+ public static void assertFalse(boolean value) throws Exception {
+ if (value) {
+ throw new AssertionError();
+ }
+ }
+}
+EOF
+
+./default-build "$@"
diff --git a/test/670-bitstring-type-check/expected.txt b/test/670-bitstring-type-check/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/670-bitstring-type-check/expected.txt
diff --git a/test/670-bitstring-type-check/info.txt b/test/670-bitstring-type-check/info.txt
new file mode 100644
index 0000000000..a34ba86171
--- /dev/null
+++ b/test/670-bitstring-type-check/info.txt
@@ -0,0 +1 @@
+Tests for the bitstring type checks.
diff --git a/test/712-varhandle-invocations/build b/test/712-varhandle-invocations/build
new file mode 100755
index 0000000000..253765be91
--- /dev/null
+++ b/test/712-varhandle-invocations/build
@@ -0,0 +1,39 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+# Make us exit on a failure
+set -e
+
+# Set variables for source directories. Using src-art so we use
+# VarHandles in the bootclasspath and can compile with the Java 8
+# compiler.
+MANUAL_SRC=src
+GENERATED_SRC=src2
+
+# Build the Java files
+mkdir -p src2
+
+# Collate list of manual test classes
+MANUAL_TESTS=$(cd "${MANUAL_SRC}" && find . -name 'Var*Tests.java' | sed -e 's@.*\(Var.*Tests\).*@\1@g' | sort)
+
+# Generate tests and Main that covers both the generated tests and manual tests
+python3 ./util-src/generate_java.py "${GENERATED_SRC}" ${MANUAL_TESTS}
+
+# Desugar is not happy with our Java 9 byte code, it shouldn't be necessary here anyway.
+export USE_DESUGAR=false
+
+# Invoke default build with increased heap size for dx
+./default-build "$@" --experimental var-handles --dx-vm-option -JXmx384m
diff --git a/test/712-varhandle-invocations/expected.txt b/test/712-varhandle-invocations/expected.txt
new file mode 100644
index 0000000000..af921901f8
--- /dev/null
+++ b/test/712-varhandle-invocations/expected.txt
@@ -0,0 +1,3183 @@
+FieldGetBoolean...OK
+FieldGetByte...OK
+FieldGetShort...OK
+FieldGetChar...OK
+FieldGetInt...OK
+FieldGetLong...OK
+FieldGetFloat...OK
+FieldGetDouble...OK
+FieldSetBoolean...OK
+FieldSetByte...OK
+FieldSetShort...OK
+FieldSetChar...OK
+FieldSetInt...OK
+FieldSetLong...OK
+FieldSetFloat...OK
+FieldSetDouble...OK
+FieldGetVolatileBoolean...OK
+FieldGetVolatileByte...OK
+FieldGetVolatileShort...OK
+FieldGetVolatileChar...OK
+FieldGetVolatileInt...OK
+FieldGetVolatileLong...OK
+FieldGetVolatileFloat...OK
+FieldGetVolatileDouble...OK
+FieldSetVolatileBoolean...OK
+FieldSetVolatileByte...OK
+FieldSetVolatileShort...OK
+FieldSetVolatileChar...OK
+FieldSetVolatileInt...OK
+FieldSetVolatileLong...OK
+FieldSetVolatileFloat...OK
+FieldSetVolatileDouble...OK
+FieldGetAcquireBoolean...OK
+FieldGetAcquireByte...OK
+FieldGetAcquireShort...OK
+FieldGetAcquireChar...OK
+FieldGetAcquireInt...OK
+FieldGetAcquireLong...OK
+FieldGetAcquireFloat...OK
+FieldGetAcquireDouble...OK
+FieldSetReleaseBoolean...OK
+FieldSetReleaseByte...OK
+FieldSetReleaseShort...OK
+FieldSetReleaseChar...OK
+FieldSetReleaseInt...OK
+FieldSetReleaseLong...OK
+FieldSetReleaseFloat...OK
+FieldSetReleaseDouble...OK
+FieldGetOpaqueBoolean...OK
+FieldGetOpaqueByte...OK
+FieldGetOpaqueShort...OK
+FieldGetOpaqueChar...OK
+FieldGetOpaqueInt...OK
+FieldGetOpaqueLong...OK
+FieldGetOpaqueFloat...OK
+FieldGetOpaqueDouble...OK
+FieldSetOpaqueBoolean...OK
+FieldSetOpaqueByte...OK
+FieldSetOpaqueShort...OK
+FieldSetOpaqueChar...OK
+FieldSetOpaqueInt...OK
+FieldSetOpaqueLong...OK
+FieldSetOpaqueFloat...OK
+FieldSetOpaqueDouble...OK
+FieldCompareAndSetBoolean...OK
+FieldCompareAndSetByte...OK
+FieldCompareAndSetShort...OK
+FieldCompareAndSetChar...OK
+FieldCompareAndSetInt...OK
+FieldCompareAndSetLong...OK
+FieldCompareAndSetFloat...OK
+FieldCompareAndSetDouble...OK
+FieldCompareAndExchangeBoolean...OK
+FieldCompareAndExchangeByte...OK
+FieldCompareAndExchangeShort...OK
+FieldCompareAndExchangeChar...OK
+FieldCompareAndExchangeInt...OK
+FieldCompareAndExchangeLong...OK
+FieldCompareAndExchangeFloat...OK
+FieldCompareAndExchangeDouble...OK
+FieldCompareAndExchangeAcquireBoolean...OK
+FieldCompareAndExchangeAcquireByte...OK
+FieldCompareAndExchangeAcquireShort...OK
+FieldCompareAndExchangeAcquireChar...OK
+FieldCompareAndExchangeAcquireInt...OK
+FieldCompareAndExchangeAcquireLong...OK
+FieldCompareAndExchangeAcquireFloat...OK
+FieldCompareAndExchangeAcquireDouble...OK
+FieldCompareAndExchangeReleaseBoolean...OK
+FieldCompareAndExchangeReleaseByte...OK
+FieldCompareAndExchangeReleaseShort...OK
+FieldCompareAndExchangeReleaseChar...OK
+FieldCompareAndExchangeReleaseInt...OK
+FieldCompareAndExchangeReleaseLong...OK
+FieldCompareAndExchangeReleaseFloat...OK
+FieldCompareAndExchangeReleaseDouble...OK
+FieldWeakCompareAndSetPlainBoolean...OK
+FieldWeakCompareAndSetPlainByte...OK
+FieldWeakCompareAndSetPlainShort...OK
+FieldWeakCompareAndSetPlainChar...OK
+FieldWeakCompareAndSetPlainInt...OK
+FieldWeakCompareAndSetPlainLong...OK
+FieldWeakCompareAndSetPlainFloat...OK
+FieldWeakCompareAndSetPlainDouble...OK
+FieldWeakCompareAndSetBoolean...OK
+FieldWeakCompareAndSetByte...OK
+FieldWeakCompareAndSetShort...OK
+FieldWeakCompareAndSetChar...OK
+FieldWeakCompareAndSetInt...OK
+FieldWeakCompareAndSetLong...OK
+FieldWeakCompareAndSetFloat...OK
+FieldWeakCompareAndSetDouble...OK
+FieldWeakCompareAndSetAcquireBoolean...OK
+FieldWeakCompareAndSetAcquireByte...OK
+FieldWeakCompareAndSetAcquireShort...OK
+FieldWeakCompareAndSetAcquireChar...OK
+FieldWeakCompareAndSetAcquireInt...OK
+FieldWeakCompareAndSetAcquireLong...OK
+FieldWeakCompareAndSetAcquireFloat...OK
+FieldWeakCompareAndSetAcquireDouble...OK
+FieldWeakCompareAndSetReleaseBoolean...OK
+FieldWeakCompareAndSetReleaseByte...OK
+FieldWeakCompareAndSetReleaseShort...OK
+FieldWeakCompareAndSetReleaseChar...OK
+FieldWeakCompareAndSetReleaseInt...OK
+FieldWeakCompareAndSetReleaseLong...OK
+FieldWeakCompareAndSetReleaseFloat...OK
+FieldWeakCompareAndSetReleaseDouble...OK
+FieldGetAndSetBoolean...OK
+FieldGetAndSetByte...OK
+FieldGetAndSetShort...OK
+FieldGetAndSetChar...OK
+FieldGetAndSetInt...OK
+FieldGetAndSetLong...OK
+FieldGetAndSetFloat...OK
+FieldGetAndSetDouble...OK
+FieldGetAndSetAcquireBoolean...OK
+FieldGetAndSetAcquireByte...OK
+FieldGetAndSetAcquireShort...OK
+FieldGetAndSetAcquireChar...OK
+FieldGetAndSetAcquireInt...OK
+FieldGetAndSetAcquireLong...OK
+FieldGetAndSetAcquireFloat...OK
+FieldGetAndSetAcquireDouble...OK
+FieldGetAndSetReleaseBoolean...OK
+FieldGetAndSetReleaseByte...OK
+FieldGetAndSetReleaseShort...OK
+FieldGetAndSetReleaseChar...OK
+FieldGetAndSetReleaseInt...OK
+FieldGetAndSetReleaseLong...OK
+FieldGetAndSetReleaseFloat...OK
+FieldGetAndSetReleaseDouble...OK
+FieldGetAndAddBoolean...OK
+FieldGetAndAddByte...OK
+FieldGetAndAddShort...OK
+FieldGetAndAddChar...OK
+FieldGetAndAddInt...OK
+FieldGetAndAddLong...OK
+FieldGetAndAddFloat...OK
+FieldGetAndAddDouble...OK
+FieldGetAndAddAcquireBoolean...OK
+FieldGetAndAddAcquireByte...OK
+FieldGetAndAddAcquireShort...OK
+FieldGetAndAddAcquireChar...OK
+FieldGetAndAddAcquireInt...OK
+FieldGetAndAddAcquireLong...OK
+FieldGetAndAddAcquireFloat...OK
+FieldGetAndAddAcquireDouble...OK
+FieldGetAndAddReleaseBoolean...OK
+FieldGetAndAddReleaseByte...OK
+FieldGetAndAddReleaseShort...OK
+FieldGetAndAddReleaseChar...OK
+FieldGetAndAddReleaseInt...OK
+FieldGetAndAddReleaseLong...OK
+FieldGetAndAddReleaseFloat...OK
+FieldGetAndAddReleaseDouble...OK
+FieldGetAndBitwiseOrBoolean...OK
+FieldGetAndBitwiseOrByte...OK
+FieldGetAndBitwiseOrShort...OK
+FieldGetAndBitwiseOrChar...OK
+FieldGetAndBitwiseOrInt...OK
+FieldGetAndBitwiseOrLong...OK
+FieldGetAndBitwiseOrFloat...OK
+FieldGetAndBitwiseOrDouble...OK
+FieldGetAndBitwiseOrReleaseBoolean...OK
+FieldGetAndBitwiseOrReleaseByte...OK
+FieldGetAndBitwiseOrReleaseShort...OK
+FieldGetAndBitwiseOrReleaseChar...OK
+FieldGetAndBitwiseOrReleaseInt...OK
+FieldGetAndBitwiseOrReleaseLong...OK
+FieldGetAndBitwiseOrReleaseFloat...OK
+FieldGetAndBitwiseOrReleaseDouble...OK
+FieldGetAndBitwiseOrAcquireBoolean...OK
+FieldGetAndBitwiseOrAcquireByte...OK
+FieldGetAndBitwiseOrAcquireShort...OK
+FieldGetAndBitwiseOrAcquireChar...OK
+FieldGetAndBitwiseOrAcquireInt...OK
+FieldGetAndBitwiseOrAcquireLong...OK
+FieldGetAndBitwiseOrAcquireFloat...OK
+FieldGetAndBitwiseOrAcquireDouble...OK
+FieldGetAndBitwiseAndBoolean...OK
+FieldGetAndBitwiseAndByte...OK
+FieldGetAndBitwiseAndShort...OK
+FieldGetAndBitwiseAndChar...OK
+FieldGetAndBitwiseAndInt...OK
+FieldGetAndBitwiseAndLong...OK
+FieldGetAndBitwiseAndFloat...OK
+FieldGetAndBitwiseAndDouble...OK
+FieldGetAndBitwiseAndReleaseBoolean...OK
+FieldGetAndBitwiseAndReleaseByte...OK
+FieldGetAndBitwiseAndReleaseShort...OK
+FieldGetAndBitwiseAndReleaseChar...OK
+FieldGetAndBitwiseAndReleaseInt...OK
+FieldGetAndBitwiseAndReleaseLong...OK
+FieldGetAndBitwiseAndReleaseFloat...OK
+FieldGetAndBitwiseAndReleaseDouble...OK
+FieldGetAndBitwiseAndAcquireBoolean...OK
+FieldGetAndBitwiseAndAcquireByte...OK
+FieldGetAndBitwiseAndAcquireShort...OK
+FieldGetAndBitwiseAndAcquireChar...OK
+FieldGetAndBitwiseAndAcquireInt...OK
+FieldGetAndBitwiseAndAcquireLong...OK
+FieldGetAndBitwiseAndAcquireFloat...OK
+FieldGetAndBitwiseAndAcquireDouble...OK
+FieldGetAndBitwiseXorBoolean...OK
+FieldGetAndBitwiseXorByte...OK
+FieldGetAndBitwiseXorShort...OK
+FieldGetAndBitwiseXorChar...OK
+FieldGetAndBitwiseXorInt...OK
+FieldGetAndBitwiseXorLong...OK
+FieldGetAndBitwiseXorFloat...OK
+FieldGetAndBitwiseXorDouble...OK
+FieldGetAndBitwiseXorReleaseBoolean...OK
+FieldGetAndBitwiseXorReleaseByte...OK
+FieldGetAndBitwiseXorReleaseShort...OK
+FieldGetAndBitwiseXorReleaseChar...OK
+FieldGetAndBitwiseXorReleaseInt...OK
+FieldGetAndBitwiseXorReleaseLong...OK
+FieldGetAndBitwiseXorReleaseFloat...OK
+FieldGetAndBitwiseXorReleaseDouble...OK
+FieldGetAndBitwiseXorAcquireBoolean...OK
+FieldGetAndBitwiseXorAcquireByte...OK
+FieldGetAndBitwiseXorAcquireShort...OK
+FieldGetAndBitwiseXorAcquireChar...OK
+FieldGetAndBitwiseXorAcquireInt...OK
+FieldGetAndBitwiseXorAcquireLong...OK
+FieldGetAndBitwiseXorAcquireFloat...OK
+FieldGetAndBitwiseXorAcquireDouble...OK
+FinalFieldGetBoolean...OK
+FinalFieldGetByte...OK
+FinalFieldGetShort...OK
+FinalFieldGetChar...OK
+FinalFieldGetInt...OK
+FinalFieldGetLong...OK
+FinalFieldGetFloat...OK
+FinalFieldGetDouble...OK
+FinalFieldSetBoolean...OK
+FinalFieldSetByte...OK
+FinalFieldSetShort...OK
+FinalFieldSetChar...OK
+FinalFieldSetInt...OK
+FinalFieldSetLong...OK
+FinalFieldSetFloat...OK
+FinalFieldSetDouble...OK
+FinalFieldGetVolatileBoolean...OK
+FinalFieldGetVolatileByte...OK
+FinalFieldGetVolatileShort...OK
+FinalFieldGetVolatileChar...OK
+FinalFieldGetVolatileInt...OK
+FinalFieldGetVolatileLong...OK
+FinalFieldGetVolatileFloat...OK
+FinalFieldGetVolatileDouble...OK
+FinalFieldSetVolatileBoolean...OK
+FinalFieldSetVolatileByte...OK
+FinalFieldSetVolatileShort...OK
+FinalFieldSetVolatileChar...OK
+FinalFieldSetVolatileInt...OK
+FinalFieldSetVolatileLong...OK
+FinalFieldSetVolatileFloat...OK
+FinalFieldSetVolatileDouble...OK
+FinalFieldGetAcquireBoolean...OK
+FinalFieldGetAcquireByte...OK
+FinalFieldGetAcquireShort...OK
+FinalFieldGetAcquireChar...OK
+FinalFieldGetAcquireInt...OK
+FinalFieldGetAcquireLong...OK
+FinalFieldGetAcquireFloat...OK
+FinalFieldGetAcquireDouble...OK
+FinalFieldSetReleaseBoolean...OK
+FinalFieldSetReleaseByte...OK
+FinalFieldSetReleaseShort...OK
+FinalFieldSetReleaseChar...OK
+FinalFieldSetReleaseInt...OK
+FinalFieldSetReleaseLong...OK
+FinalFieldSetReleaseFloat...OK
+FinalFieldSetReleaseDouble...OK
+FinalFieldGetOpaqueBoolean...OK
+FinalFieldGetOpaqueByte...OK
+FinalFieldGetOpaqueShort...OK
+FinalFieldGetOpaqueChar...OK
+FinalFieldGetOpaqueInt...OK
+FinalFieldGetOpaqueLong...OK
+FinalFieldGetOpaqueFloat...OK
+FinalFieldGetOpaqueDouble...OK
+FinalFieldSetOpaqueBoolean...OK
+FinalFieldSetOpaqueByte...OK
+FinalFieldSetOpaqueShort...OK
+FinalFieldSetOpaqueChar...OK
+FinalFieldSetOpaqueInt...OK
+FinalFieldSetOpaqueLong...OK
+FinalFieldSetOpaqueFloat...OK
+FinalFieldSetOpaqueDouble...OK
+FinalFieldCompareAndSetBoolean...OK
+FinalFieldCompareAndSetByte...OK
+FinalFieldCompareAndSetShort...OK
+FinalFieldCompareAndSetChar...OK
+FinalFieldCompareAndSetInt...OK
+FinalFieldCompareAndSetLong...OK
+FinalFieldCompareAndSetFloat...OK
+FinalFieldCompareAndSetDouble...OK
+FinalFieldCompareAndExchangeBoolean...OK
+FinalFieldCompareAndExchangeByte...OK
+FinalFieldCompareAndExchangeShort...OK
+FinalFieldCompareAndExchangeChar...OK
+FinalFieldCompareAndExchangeInt...OK
+FinalFieldCompareAndExchangeLong...OK
+FinalFieldCompareAndExchangeFloat...OK
+FinalFieldCompareAndExchangeDouble...OK
+FinalFieldCompareAndExchangeAcquireBoolean...OK
+FinalFieldCompareAndExchangeAcquireByte...OK
+FinalFieldCompareAndExchangeAcquireShort...OK
+FinalFieldCompareAndExchangeAcquireChar...OK
+FinalFieldCompareAndExchangeAcquireInt...OK
+FinalFieldCompareAndExchangeAcquireLong...OK
+FinalFieldCompareAndExchangeAcquireFloat...OK
+FinalFieldCompareAndExchangeAcquireDouble...OK
+FinalFieldCompareAndExchangeReleaseBoolean...OK
+FinalFieldCompareAndExchangeReleaseByte...OK
+FinalFieldCompareAndExchangeReleaseShort...OK
+FinalFieldCompareAndExchangeReleaseChar...OK
+FinalFieldCompareAndExchangeReleaseInt...OK
+FinalFieldCompareAndExchangeReleaseLong...OK
+FinalFieldCompareAndExchangeReleaseFloat...OK
+FinalFieldCompareAndExchangeReleaseDouble...OK
+FinalFieldWeakCompareAndSetPlainBoolean...OK
+FinalFieldWeakCompareAndSetPlainByte...OK
+FinalFieldWeakCompareAndSetPlainShort...OK
+FinalFieldWeakCompareAndSetPlainChar...OK
+FinalFieldWeakCompareAndSetPlainInt...OK
+FinalFieldWeakCompareAndSetPlainLong...OK
+FinalFieldWeakCompareAndSetPlainFloat...OK
+FinalFieldWeakCompareAndSetPlainDouble...OK
+FinalFieldWeakCompareAndSetBoolean...OK
+FinalFieldWeakCompareAndSetByte...OK
+FinalFieldWeakCompareAndSetShort...OK
+FinalFieldWeakCompareAndSetChar...OK
+FinalFieldWeakCompareAndSetInt...OK
+FinalFieldWeakCompareAndSetLong...OK
+FinalFieldWeakCompareAndSetFloat...OK
+FinalFieldWeakCompareAndSetDouble...OK
+FinalFieldWeakCompareAndSetAcquireBoolean...OK
+FinalFieldWeakCompareAndSetAcquireByte...OK
+FinalFieldWeakCompareAndSetAcquireShort...OK
+FinalFieldWeakCompareAndSetAcquireChar...OK
+FinalFieldWeakCompareAndSetAcquireInt...OK
+FinalFieldWeakCompareAndSetAcquireLong...OK
+FinalFieldWeakCompareAndSetAcquireFloat...OK
+FinalFieldWeakCompareAndSetAcquireDouble...OK
+FinalFieldWeakCompareAndSetReleaseBoolean...OK
+FinalFieldWeakCompareAndSetReleaseByte...OK
+FinalFieldWeakCompareAndSetReleaseShort...OK
+FinalFieldWeakCompareAndSetReleaseChar...OK
+FinalFieldWeakCompareAndSetReleaseInt...OK
+FinalFieldWeakCompareAndSetReleaseLong...OK
+FinalFieldWeakCompareAndSetReleaseFloat...OK
+FinalFieldWeakCompareAndSetReleaseDouble...OK
+FinalFieldGetAndSetBoolean...OK
+FinalFieldGetAndSetByte...OK
+FinalFieldGetAndSetShort...OK
+FinalFieldGetAndSetChar...OK
+FinalFieldGetAndSetInt...OK
+FinalFieldGetAndSetLong...OK
+FinalFieldGetAndSetFloat...OK
+FinalFieldGetAndSetDouble...OK
+FinalFieldGetAndSetAcquireBoolean...OK
+FinalFieldGetAndSetAcquireByte...OK
+FinalFieldGetAndSetAcquireShort...OK
+FinalFieldGetAndSetAcquireChar...OK
+FinalFieldGetAndSetAcquireInt...OK
+FinalFieldGetAndSetAcquireLong...OK
+FinalFieldGetAndSetAcquireFloat...OK
+FinalFieldGetAndSetAcquireDouble...OK
+FinalFieldGetAndSetReleaseBoolean...OK
+FinalFieldGetAndSetReleaseByte...OK
+FinalFieldGetAndSetReleaseShort...OK
+FinalFieldGetAndSetReleaseChar...OK
+FinalFieldGetAndSetReleaseInt...OK
+FinalFieldGetAndSetReleaseLong...OK
+FinalFieldGetAndSetReleaseFloat...OK
+FinalFieldGetAndSetReleaseDouble...OK
+FinalFieldGetAndAddBoolean...OK
+FinalFieldGetAndAddByte...OK
+FinalFieldGetAndAddShort...OK
+FinalFieldGetAndAddChar...OK
+FinalFieldGetAndAddInt...OK
+FinalFieldGetAndAddLong...OK
+FinalFieldGetAndAddFloat...OK
+FinalFieldGetAndAddDouble...OK
+FinalFieldGetAndAddAcquireBoolean...OK
+FinalFieldGetAndAddAcquireByte...OK
+FinalFieldGetAndAddAcquireShort...OK
+FinalFieldGetAndAddAcquireChar...OK
+FinalFieldGetAndAddAcquireInt...OK
+FinalFieldGetAndAddAcquireLong...OK
+FinalFieldGetAndAddAcquireFloat...OK
+FinalFieldGetAndAddAcquireDouble...OK
+FinalFieldGetAndAddReleaseBoolean...OK
+FinalFieldGetAndAddReleaseByte...OK
+FinalFieldGetAndAddReleaseShort...OK
+FinalFieldGetAndAddReleaseChar...OK
+FinalFieldGetAndAddReleaseInt...OK
+FinalFieldGetAndAddReleaseLong...OK
+FinalFieldGetAndAddReleaseFloat...OK
+FinalFieldGetAndAddReleaseDouble...OK
+FinalFieldGetAndBitwiseOrBoolean...OK
+FinalFieldGetAndBitwiseOrByte...OK
+FinalFieldGetAndBitwiseOrShort...OK
+FinalFieldGetAndBitwiseOrChar...OK
+FinalFieldGetAndBitwiseOrInt...OK
+FinalFieldGetAndBitwiseOrLong...OK
+FinalFieldGetAndBitwiseOrFloat...OK
+FinalFieldGetAndBitwiseOrDouble...OK
+FinalFieldGetAndBitwiseOrReleaseBoolean...OK
+FinalFieldGetAndBitwiseOrReleaseByte...OK
+FinalFieldGetAndBitwiseOrReleaseShort...OK
+FinalFieldGetAndBitwiseOrReleaseChar...OK
+FinalFieldGetAndBitwiseOrReleaseInt...OK
+FinalFieldGetAndBitwiseOrReleaseLong...OK
+FinalFieldGetAndBitwiseOrReleaseFloat...OK
+FinalFieldGetAndBitwiseOrReleaseDouble...OK
+FinalFieldGetAndBitwiseOrAcquireBoolean...OK
+FinalFieldGetAndBitwiseOrAcquireByte...OK
+FinalFieldGetAndBitwiseOrAcquireShort...OK
+FinalFieldGetAndBitwiseOrAcquireChar...OK
+FinalFieldGetAndBitwiseOrAcquireInt...OK
+FinalFieldGetAndBitwiseOrAcquireLong...OK
+FinalFieldGetAndBitwiseOrAcquireFloat...OK
+FinalFieldGetAndBitwiseOrAcquireDouble...OK
+FinalFieldGetAndBitwiseAndBoolean...OK
+FinalFieldGetAndBitwiseAndByte...OK
+FinalFieldGetAndBitwiseAndShort...OK
+FinalFieldGetAndBitwiseAndChar...OK
+FinalFieldGetAndBitwiseAndInt...OK
+FinalFieldGetAndBitwiseAndLong...OK
+FinalFieldGetAndBitwiseAndFloat...OK
+FinalFieldGetAndBitwiseAndDouble...OK
+FinalFieldGetAndBitwiseAndReleaseBoolean...OK
+FinalFieldGetAndBitwiseAndReleaseByte...OK
+FinalFieldGetAndBitwiseAndReleaseShort...OK
+FinalFieldGetAndBitwiseAndReleaseChar...OK
+FinalFieldGetAndBitwiseAndReleaseInt...OK
+FinalFieldGetAndBitwiseAndReleaseLong...OK
+FinalFieldGetAndBitwiseAndReleaseFloat...OK
+FinalFieldGetAndBitwiseAndReleaseDouble...OK
+FinalFieldGetAndBitwiseAndAcquireBoolean...OK
+FinalFieldGetAndBitwiseAndAcquireByte...OK
+FinalFieldGetAndBitwiseAndAcquireShort...OK
+FinalFieldGetAndBitwiseAndAcquireChar...OK
+FinalFieldGetAndBitwiseAndAcquireInt...OK
+FinalFieldGetAndBitwiseAndAcquireLong...OK
+FinalFieldGetAndBitwiseAndAcquireFloat...OK
+FinalFieldGetAndBitwiseAndAcquireDouble...OK
+FinalFieldGetAndBitwiseXorBoolean...OK
+FinalFieldGetAndBitwiseXorByte...OK
+FinalFieldGetAndBitwiseXorShort...OK
+FinalFieldGetAndBitwiseXorChar...OK
+FinalFieldGetAndBitwiseXorInt...OK
+FinalFieldGetAndBitwiseXorLong...OK
+FinalFieldGetAndBitwiseXorFloat...OK
+FinalFieldGetAndBitwiseXorDouble...OK
+FinalFieldGetAndBitwiseXorReleaseBoolean...OK
+FinalFieldGetAndBitwiseXorReleaseByte...OK
+FinalFieldGetAndBitwiseXorReleaseShort...OK
+FinalFieldGetAndBitwiseXorReleaseChar...OK
+FinalFieldGetAndBitwiseXorReleaseInt...OK
+FinalFieldGetAndBitwiseXorReleaseLong...OK
+FinalFieldGetAndBitwiseXorReleaseFloat...OK
+FinalFieldGetAndBitwiseXorReleaseDouble...OK
+FinalFieldGetAndBitwiseXorAcquireBoolean...OK
+FinalFieldGetAndBitwiseXorAcquireByte...OK
+FinalFieldGetAndBitwiseXorAcquireShort...OK
+FinalFieldGetAndBitwiseXorAcquireChar...OK
+FinalFieldGetAndBitwiseXorAcquireInt...OK
+FinalFieldGetAndBitwiseXorAcquireLong...OK
+FinalFieldGetAndBitwiseXorAcquireFloat...OK
+FinalFieldGetAndBitwiseXorAcquireDouble...OK
+StaticFieldGetBoolean...OK
+StaticFieldGetByte...OK
+StaticFieldGetShort...OK
+StaticFieldGetChar...OK
+StaticFieldGetInt...OK
+StaticFieldGetLong...OK
+StaticFieldGetFloat...OK
+StaticFieldGetDouble...OK
+StaticFieldSetBoolean...OK
+StaticFieldSetByte...OK
+StaticFieldSetShort...OK
+StaticFieldSetChar...OK
+StaticFieldSetInt...OK
+StaticFieldSetLong...OK
+StaticFieldSetFloat...OK
+StaticFieldSetDouble...OK
+StaticFieldGetVolatileBoolean...OK
+StaticFieldGetVolatileByte...OK
+StaticFieldGetVolatileShort...OK
+StaticFieldGetVolatileChar...OK
+StaticFieldGetVolatileInt...OK
+StaticFieldGetVolatileLong...OK
+StaticFieldGetVolatileFloat...OK
+StaticFieldGetVolatileDouble...OK
+StaticFieldSetVolatileBoolean...OK
+StaticFieldSetVolatileByte...OK
+StaticFieldSetVolatileShort...OK
+StaticFieldSetVolatileChar...OK
+StaticFieldSetVolatileInt...OK
+StaticFieldSetVolatileLong...OK
+StaticFieldSetVolatileFloat...OK
+StaticFieldSetVolatileDouble...OK
+StaticFieldGetAcquireBoolean...OK
+StaticFieldGetAcquireByte...OK
+StaticFieldGetAcquireShort...OK
+StaticFieldGetAcquireChar...OK
+StaticFieldGetAcquireInt...OK
+StaticFieldGetAcquireLong...OK
+StaticFieldGetAcquireFloat...OK
+StaticFieldGetAcquireDouble...OK
+StaticFieldSetReleaseBoolean...OK
+StaticFieldSetReleaseByte...OK
+StaticFieldSetReleaseShort...OK
+StaticFieldSetReleaseChar...OK
+StaticFieldSetReleaseInt...OK
+StaticFieldSetReleaseLong...OK
+StaticFieldSetReleaseFloat...OK
+StaticFieldSetReleaseDouble...OK
+StaticFieldGetOpaqueBoolean...OK
+StaticFieldGetOpaqueByte...OK
+StaticFieldGetOpaqueShort...OK
+StaticFieldGetOpaqueChar...OK
+StaticFieldGetOpaqueInt...OK
+StaticFieldGetOpaqueLong...OK
+StaticFieldGetOpaqueFloat...OK
+StaticFieldGetOpaqueDouble...OK
+StaticFieldSetOpaqueBoolean...OK
+StaticFieldSetOpaqueByte...OK
+StaticFieldSetOpaqueShort...OK
+StaticFieldSetOpaqueChar...OK
+StaticFieldSetOpaqueInt...OK
+StaticFieldSetOpaqueLong...OK
+StaticFieldSetOpaqueFloat...OK
+StaticFieldSetOpaqueDouble...OK
+StaticFieldCompareAndSetBoolean...OK
+StaticFieldCompareAndSetByte...OK
+StaticFieldCompareAndSetShort...OK
+StaticFieldCompareAndSetChar...OK
+StaticFieldCompareAndSetInt...OK
+StaticFieldCompareAndSetLong...OK
+StaticFieldCompareAndSetFloat...OK
+StaticFieldCompareAndSetDouble...OK
+StaticFieldCompareAndExchangeBoolean...OK
+StaticFieldCompareAndExchangeByte...OK
+StaticFieldCompareAndExchangeShort...OK
+StaticFieldCompareAndExchangeChar...OK
+StaticFieldCompareAndExchangeInt...OK
+StaticFieldCompareAndExchangeLong...OK
+StaticFieldCompareAndExchangeFloat...OK
+StaticFieldCompareAndExchangeDouble...OK
+StaticFieldCompareAndExchangeAcquireBoolean...OK
+StaticFieldCompareAndExchangeAcquireByte...OK
+StaticFieldCompareAndExchangeAcquireShort...OK
+StaticFieldCompareAndExchangeAcquireChar...OK
+StaticFieldCompareAndExchangeAcquireInt...OK
+StaticFieldCompareAndExchangeAcquireLong...OK
+StaticFieldCompareAndExchangeAcquireFloat...OK
+StaticFieldCompareAndExchangeAcquireDouble...OK
+StaticFieldCompareAndExchangeReleaseBoolean...OK
+StaticFieldCompareAndExchangeReleaseByte...OK
+StaticFieldCompareAndExchangeReleaseShort...OK
+StaticFieldCompareAndExchangeReleaseChar...OK
+StaticFieldCompareAndExchangeReleaseInt...OK
+StaticFieldCompareAndExchangeReleaseLong...OK
+StaticFieldCompareAndExchangeReleaseFloat...OK
+StaticFieldCompareAndExchangeReleaseDouble...OK
+StaticFieldWeakCompareAndSetPlainBoolean...OK
+StaticFieldWeakCompareAndSetPlainByte...OK
+StaticFieldWeakCompareAndSetPlainShort...OK
+StaticFieldWeakCompareAndSetPlainChar...OK
+StaticFieldWeakCompareAndSetPlainInt...OK
+StaticFieldWeakCompareAndSetPlainLong...OK
+StaticFieldWeakCompareAndSetPlainFloat...OK
+StaticFieldWeakCompareAndSetPlainDouble...OK
+StaticFieldWeakCompareAndSetBoolean...OK
+StaticFieldWeakCompareAndSetByte...OK
+StaticFieldWeakCompareAndSetShort...OK
+StaticFieldWeakCompareAndSetChar...OK
+StaticFieldWeakCompareAndSetInt...OK
+StaticFieldWeakCompareAndSetLong...OK
+StaticFieldWeakCompareAndSetFloat...OK
+StaticFieldWeakCompareAndSetDouble...OK
+StaticFieldWeakCompareAndSetAcquireBoolean...OK
+StaticFieldWeakCompareAndSetAcquireByte...OK
+StaticFieldWeakCompareAndSetAcquireShort...OK
+StaticFieldWeakCompareAndSetAcquireChar...OK
+StaticFieldWeakCompareAndSetAcquireInt...OK
+StaticFieldWeakCompareAndSetAcquireLong...OK
+StaticFieldWeakCompareAndSetAcquireFloat...OK
+StaticFieldWeakCompareAndSetAcquireDouble...OK
+StaticFieldWeakCompareAndSetReleaseBoolean...OK
+StaticFieldWeakCompareAndSetReleaseByte...OK
+StaticFieldWeakCompareAndSetReleaseShort...OK
+StaticFieldWeakCompareAndSetReleaseChar...OK
+StaticFieldWeakCompareAndSetReleaseInt...OK
+StaticFieldWeakCompareAndSetReleaseLong...OK
+StaticFieldWeakCompareAndSetReleaseFloat...OK
+StaticFieldWeakCompareAndSetReleaseDouble...OK
+StaticFieldGetAndSetBoolean...OK
+StaticFieldGetAndSetByte...OK
+StaticFieldGetAndSetShort...OK
+StaticFieldGetAndSetChar...OK
+StaticFieldGetAndSetInt...OK
+StaticFieldGetAndSetLong...OK
+StaticFieldGetAndSetFloat...OK
+StaticFieldGetAndSetDouble...OK
+StaticFieldGetAndSetAcquireBoolean...OK
+StaticFieldGetAndSetAcquireByte...OK
+StaticFieldGetAndSetAcquireShort...OK
+StaticFieldGetAndSetAcquireChar...OK
+StaticFieldGetAndSetAcquireInt...OK
+StaticFieldGetAndSetAcquireLong...OK
+StaticFieldGetAndSetAcquireFloat...OK
+StaticFieldGetAndSetAcquireDouble...OK
+StaticFieldGetAndSetReleaseBoolean...OK
+StaticFieldGetAndSetReleaseByte...OK
+StaticFieldGetAndSetReleaseShort...OK
+StaticFieldGetAndSetReleaseChar...OK
+StaticFieldGetAndSetReleaseInt...OK
+StaticFieldGetAndSetReleaseLong...OK
+StaticFieldGetAndSetReleaseFloat...OK
+StaticFieldGetAndSetReleaseDouble...OK
+StaticFieldGetAndAddBoolean...OK
+StaticFieldGetAndAddByte...OK
+StaticFieldGetAndAddShort...OK
+StaticFieldGetAndAddChar...OK
+StaticFieldGetAndAddInt...OK
+StaticFieldGetAndAddLong...OK
+StaticFieldGetAndAddFloat...OK
+StaticFieldGetAndAddDouble...OK
+StaticFieldGetAndAddAcquireBoolean...OK
+StaticFieldGetAndAddAcquireByte...OK
+StaticFieldGetAndAddAcquireShort...OK
+StaticFieldGetAndAddAcquireChar...OK
+StaticFieldGetAndAddAcquireInt...OK
+StaticFieldGetAndAddAcquireLong...OK
+StaticFieldGetAndAddAcquireFloat...OK
+StaticFieldGetAndAddAcquireDouble...OK
+StaticFieldGetAndAddReleaseBoolean...OK
+StaticFieldGetAndAddReleaseByte...OK
+StaticFieldGetAndAddReleaseShort...OK
+StaticFieldGetAndAddReleaseChar...OK
+StaticFieldGetAndAddReleaseInt...OK
+StaticFieldGetAndAddReleaseLong...OK
+StaticFieldGetAndAddReleaseFloat...OK
+StaticFieldGetAndAddReleaseDouble...OK
+StaticFieldGetAndBitwiseOrBoolean...OK
+StaticFieldGetAndBitwiseOrByte...OK
+StaticFieldGetAndBitwiseOrShort...OK
+StaticFieldGetAndBitwiseOrChar...OK
+StaticFieldGetAndBitwiseOrInt...OK
+StaticFieldGetAndBitwiseOrLong...OK
+StaticFieldGetAndBitwiseOrFloat...OK
+StaticFieldGetAndBitwiseOrDouble...OK
+StaticFieldGetAndBitwiseOrReleaseBoolean...OK
+StaticFieldGetAndBitwiseOrReleaseByte...OK
+StaticFieldGetAndBitwiseOrReleaseShort...OK
+StaticFieldGetAndBitwiseOrReleaseChar...OK
+StaticFieldGetAndBitwiseOrReleaseInt...OK
+StaticFieldGetAndBitwiseOrReleaseLong...OK
+StaticFieldGetAndBitwiseOrReleaseFloat...OK
+StaticFieldGetAndBitwiseOrReleaseDouble...OK
+StaticFieldGetAndBitwiseOrAcquireBoolean...OK
+StaticFieldGetAndBitwiseOrAcquireByte...OK
+StaticFieldGetAndBitwiseOrAcquireShort...OK
+StaticFieldGetAndBitwiseOrAcquireChar...OK
+StaticFieldGetAndBitwiseOrAcquireInt...OK
+StaticFieldGetAndBitwiseOrAcquireLong...OK
+StaticFieldGetAndBitwiseOrAcquireFloat...OK
+StaticFieldGetAndBitwiseOrAcquireDouble...OK
+StaticFieldGetAndBitwiseAndBoolean...OK
+StaticFieldGetAndBitwiseAndByte...OK
+StaticFieldGetAndBitwiseAndShort...OK
+StaticFieldGetAndBitwiseAndChar...OK
+StaticFieldGetAndBitwiseAndInt...OK
+StaticFieldGetAndBitwiseAndLong...OK
+StaticFieldGetAndBitwiseAndFloat...OK
+StaticFieldGetAndBitwiseAndDouble...OK
+StaticFieldGetAndBitwiseAndReleaseBoolean...OK
+StaticFieldGetAndBitwiseAndReleaseByte...OK
+StaticFieldGetAndBitwiseAndReleaseShort...OK
+StaticFieldGetAndBitwiseAndReleaseChar...OK
+StaticFieldGetAndBitwiseAndReleaseInt...OK
+StaticFieldGetAndBitwiseAndReleaseLong...OK
+StaticFieldGetAndBitwiseAndReleaseFloat...OK
+StaticFieldGetAndBitwiseAndReleaseDouble...OK
+StaticFieldGetAndBitwiseAndAcquireBoolean...OK
+StaticFieldGetAndBitwiseAndAcquireByte...OK
+StaticFieldGetAndBitwiseAndAcquireShort...OK
+StaticFieldGetAndBitwiseAndAcquireChar...OK
+StaticFieldGetAndBitwiseAndAcquireInt...OK
+StaticFieldGetAndBitwiseAndAcquireLong...OK
+StaticFieldGetAndBitwiseAndAcquireFloat...OK
+StaticFieldGetAndBitwiseAndAcquireDouble...OK
+StaticFieldGetAndBitwiseXorBoolean...OK
+StaticFieldGetAndBitwiseXorByte...OK
+StaticFieldGetAndBitwiseXorShort...OK
+StaticFieldGetAndBitwiseXorChar...OK
+StaticFieldGetAndBitwiseXorInt...OK
+StaticFieldGetAndBitwiseXorLong...OK
+StaticFieldGetAndBitwiseXorFloat...OK
+StaticFieldGetAndBitwiseXorDouble...OK
+StaticFieldGetAndBitwiseXorReleaseBoolean...OK
+StaticFieldGetAndBitwiseXorReleaseByte...OK
+StaticFieldGetAndBitwiseXorReleaseShort...OK
+StaticFieldGetAndBitwiseXorReleaseChar...OK
+StaticFieldGetAndBitwiseXorReleaseInt...OK
+StaticFieldGetAndBitwiseXorReleaseLong...OK
+StaticFieldGetAndBitwiseXorReleaseFloat...OK
+StaticFieldGetAndBitwiseXorReleaseDouble...OK
+StaticFieldGetAndBitwiseXorAcquireBoolean...OK
+StaticFieldGetAndBitwiseXorAcquireByte...OK
+StaticFieldGetAndBitwiseXorAcquireShort...OK
+StaticFieldGetAndBitwiseXorAcquireChar...OK
+StaticFieldGetAndBitwiseXorAcquireInt...OK
+StaticFieldGetAndBitwiseXorAcquireLong...OK
+StaticFieldGetAndBitwiseXorAcquireFloat...OK
+StaticFieldGetAndBitwiseXorAcquireDouble...OK
+StaticFinalFieldGetBoolean...OK
+StaticFinalFieldGetByte...OK
+StaticFinalFieldGetShort...OK
+StaticFinalFieldGetChar...OK
+StaticFinalFieldGetInt...OK
+StaticFinalFieldGetLong...OK
+StaticFinalFieldGetFloat...OK
+StaticFinalFieldGetDouble...OK
+StaticFinalFieldSetBoolean...OK
+StaticFinalFieldSetByte...OK
+StaticFinalFieldSetShort...OK
+StaticFinalFieldSetChar...OK
+StaticFinalFieldSetInt...OK
+StaticFinalFieldSetLong...OK
+StaticFinalFieldSetFloat...OK
+StaticFinalFieldSetDouble...OK
+StaticFinalFieldGetVolatileBoolean...OK
+StaticFinalFieldGetVolatileByte...OK
+StaticFinalFieldGetVolatileShort...OK
+StaticFinalFieldGetVolatileChar...OK
+StaticFinalFieldGetVolatileInt...OK
+StaticFinalFieldGetVolatileLong...OK
+StaticFinalFieldGetVolatileFloat...OK
+StaticFinalFieldGetVolatileDouble...OK
+StaticFinalFieldSetVolatileBoolean...OK
+StaticFinalFieldSetVolatileByte...OK
+StaticFinalFieldSetVolatileShort...OK
+StaticFinalFieldSetVolatileChar...OK
+StaticFinalFieldSetVolatileInt...OK
+StaticFinalFieldSetVolatileLong...OK
+StaticFinalFieldSetVolatileFloat...OK
+StaticFinalFieldSetVolatileDouble...OK
+StaticFinalFieldGetAcquireBoolean...OK
+StaticFinalFieldGetAcquireByte...OK
+StaticFinalFieldGetAcquireShort...OK
+StaticFinalFieldGetAcquireChar...OK
+StaticFinalFieldGetAcquireInt...OK
+StaticFinalFieldGetAcquireLong...OK
+StaticFinalFieldGetAcquireFloat...OK
+StaticFinalFieldGetAcquireDouble...OK
+StaticFinalFieldSetReleaseBoolean...OK
+StaticFinalFieldSetReleaseByte...OK
+StaticFinalFieldSetReleaseShort...OK
+StaticFinalFieldSetReleaseChar...OK
+StaticFinalFieldSetReleaseInt...OK
+StaticFinalFieldSetReleaseLong...OK
+StaticFinalFieldSetReleaseFloat...OK
+StaticFinalFieldSetReleaseDouble...OK
+StaticFinalFieldGetOpaqueBoolean...OK
+StaticFinalFieldGetOpaqueByte...OK
+StaticFinalFieldGetOpaqueShort...OK
+StaticFinalFieldGetOpaqueChar...OK
+StaticFinalFieldGetOpaqueInt...OK
+StaticFinalFieldGetOpaqueLong...OK
+StaticFinalFieldGetOpaqueFloat...OK
+StaticFinalFieldGetOpaqueDouble...OK
+StaticFinalFieldSetOpaqueBoolean...OK
+StaticFinalFieldSetOpaqueByte...OK
+StaticFinalFieldSetOpaqueShort...OK
+StaticFinalFieldSetOpaqueChar...OK
+StaticFinalFieldSetOpaqueInt...OK
+StaticFinalFieldSetOpaqueLong...OK
+StaticFinalFieldSetOpaqueFloat...OK
+StaticFinalFieldSetOpaqueDouble...OK
+StaticFinalFieldCompareAndSetBoolean...OK
+StaticFinalFieldCompareAndSetByte...OK
+StaticFinalFieldCompareAndSetShort...OK
+StaticFinalFieldCompareAndSetChar...OK
+StaticFinalFieldCompareAndSetInt...OK
+StaticFinalFieldCompareAndSetLong...OK
+StaticFinalFieldCompareAndSetFloat...OK
+StaticFinalFieldCompareAndSetDouble...OK
+StaticFinalFieldCompareAndExchangeBoolean...OK
+StaticFinalFieldCompareAndExchangeByte...OK
+StaticFinalFieldCompareAndExchangeShort...OK
+StaticFinalFieldCompareAndExchangeChar...OK
+StaticFinalFieldCompareAndExchangeInt...OK
+StaticFinalFieldCompareAndExchangeLong...OK
+StaticFinalFieldCompareAndExchangeFloat...OK
+StaticFinalFieldCompareAndExchangeDouble...OK
+StaticFinalFieldCompareAndExchangeAcquireBoolean...OK
+StaticFinalFieldCompareAndExchangeAcquireByte...OK
+StaticFinalFieldCompareAndExchangeAcquireShort...OK
+StaticFinalFieldCompareAndExchangeAcquireChar...OK
+StaticFinalFieldCompareAndExchangeAcquireInt...OK
+StaticFinalFieldCompareAndExchangeAcquireLong...OK
+StaticFinalFieldCompareAndExchangeAcquireFloat...OK
+StaticFinalFieldCompareAndExchangeAcquireDouble...OK
+StaticFinalFieldCompareAndExchangeReleaseBoolean...OK
+StaticFinalFieldCompareAndExchangeReleaseByte...OK
+StaticFinalFieldCompareAndExchangeReleaseShort...OK
+StaticFinalFieldCompareAndExchangeReleaseChar...OK
+StaticFinalFieldCompareAndExchangeReleaseInt...OK
+StaticFinalFieldCompareAndExchangeReleaseLong...OK
+StaticFinalFieldCompareAndExchangeReleaseFloat...OK
+StaticFinalFieldCompareAndExchangeReleaseDouble...OK
+StaticFinalFieldWeakCompareAndSetPlainBoolean...OK
+StaticFinalFieldWeakCompareAndSetPlainByte...OK
+StaticFinalFieldWeakCompareAndSetPlainShort...OK
+StaticFinalFieldWeakCompareAndSetPlainChar...OK
+StaticFinalFieldWeakCompareAndSetPlainInt...OK
+StaticFinalFieldWeakCompareAndSetPlainLong...OK
+StaticFinalFieldWeakCompareAndSetPlainFloat...OK
+StaticFinalFieldWeakCompareAndSetPlainDouble...OK
+StaticFinalFieldWeakCompareAndSetBoolean...OK
+StaticFinalFieldWeakCompareAndSetByte...OK
+StaticFinalFieldWeakCompareAndSetShort...OK
+StaticFinalFieldWeakCompareAndSetChar...OK
+StaticFinalFieldWeakCompareAndSetInt...OK
+StaticFinalFieldWeakCompareAndSetLong...OK
+StaticFinalFieldWeakCompareAndSetFloat...OK
+StaticFinalFieldWeakCompareAndSetDouble...OK
+StaticFinalFieldWeakCompareAndSetAcquireBoolean...OK
+StaticFinalFieldWeakCompareAndSetAcquireByte...OK
+StaticFinalFieldWeakCompareAndSetAcquireShort...OK
+StaticFinalFieldWeakCompareAndSetAcquireChar...OK
+StaticFinalFieldWeakCompareAndSetAcquireInt...OK
+StaticFinalFieldWeakCompareAndSetAcquireLong...OK
+StaticFinalFieldWeakCompareAndSetAcquireFloat...OK
+StaticFinalFieldWeakCompareAndSetAcquireDouble...OK
+StaticFinalFieldWeakCompareAndSetReleaseBoolean...OK
+StaticFinalFieldWeakCompareAndSetReleaseByte...OK
+StaticFinalFieldWeakCompareAndSetReleaseShort...OK
+StaticFinalFieldWeakCompareAndSetReleaseChar...OK
+StaticFinalFieldWeakCompareAndSetReleaseInt...OK
+StaticFinalFieldWeakCompareAndSetReleaseLong...OK
+StaticFinalFieldWeakCompareAndSetReleaseFloat...OK
+StaticFinalFieldWeakCompareAndSetReleaseDouble...OK
+StaticFinalFieldGetAndSetBoolean...OK
+StaticFinalFieldGetAndSetByte...OK
+StaticFinalFieldGetAndSetShort...OK
+StaticFinalFieldGetAndSetChar...OK
+StaticFinalFieldGetAndSetInt...OK
+StaticFinalFieldGetAndSetLong...OK
+StaticFinalFieldGetAndSetFloat...OK
+StaticFinalFieldGetAndSetDouble...OK
+StaticFinalFieldGetAndSetAcquireBoolean...OK
+StaticFinalFieldGetAndSetAcquireByte...OK
+StaticFinalFieldGetAndSetAcquireShort...OK
+StaticFinalFieldGetAndSetAcquireChar...OK
+StaticFinalFieldGetAndSetAcquireInt...OK
+StaticFinalFieldGetAndSetAcquireLong...OK
+StaticFinalFieldGetAndSetAcquireFloat...OK
+StaticFinalFieldGetAndSetAcquireDouble...OK
+StaticFinalFieldGetAndSetReleaseBoolean...OK
+StaticFinalFieldGetAndSetReleaseByte...OK
+StaticFinalFieldGetAndSetReleaseShort...OK
+StaticFinalFieldGetAndSetReleaseChar...OK
+StaticFinalFieldGetAndSetReleaseInt...OK
+StaticFinalFieldGetAndSetReleaseLong...OK
+StaticFinalFieldGetAndSetReleaseFloat...OK
+StaticFinalFieldGetAndSetReleaseDouble...OK
+StaticFinalFieldGetAndAddBoolean...OK
+StaticFinalFieldGetAndAddByte...OK
+StaticFinalFieldGetAndAddShort...OK
+StaticFinalFieldGetAndAddChar...OK
+StaticFinalFieldGetAndAddInt...OK
+StaticFinalFieldGetAndAddLong...OK
+StaticFinalFieldGetAndAddFloat...OK
+StaticFinalFieldGetAndAddDouble...OK
+StaticFinalFieldGetAndAddAcquireBoolean...OK
+StaticFinalFieldGetAndAddAcquireByte...OK
+StaticFinalFieldGetAndAddAcquireShort...OK
+StaticFinalFieldGetAndAddAcquireChar...OK
+StaticFinalFieldGetAndAddAcquireInt...OK
+StaticFinalFieldGetAndAddAcquireLong...OK
+StaticFinalFieldGetAndAddAcquireFloat...OK
+StaticFinalFieldGetAndAddAcquireDouble...OK
+StaticFinalFieldGetAndAddReleaseBoolean...OK
+StaticFinalFieldGetAndAddReleaseByte...OK
+StaticFinalFieldGetAndAddReleaseShort...OK
+StaticFinalFieldGetAndAddReleaseChar...OK
+StaticFinalFieldGetAndAddReleaseInt...OK
+StaticFinalFieldGetAndAddReleaseLong...OK
+StaticFinalFieldGetAndAddReleaseFloat...OK
+StaticFinalFieldGetAndAddReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseOrBoolean...OK
+StaticFinalFieldGetAndBitwiseOrByte...OK
+StaticFinalFieldGetAndBitwiseOrShort...OK
+StaticFinalFieldGetAndBitwiseOrChar...OK
+StaticFinalFieldGetAndBitwiseOrInt...OK
+StaticFinalFieldGetAndBitwiseOrLong...OK
+StaticFinalFieldGetAndBitwiseOrFloat...OK
+StaticFinalFieldGetAndBitwiseOrDouble...OK
+StaticFinalFieldGetAndBitwiseOrReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseOrReleaseByte...OK
+StaticFinalFieldGetAndBitwiseOrReleaseShort...OK
+StaticFinalFieldGetAndBitwiseOrReleaseChar...OK
+StaticFinalFieldGetAndBitwiseOrReleaseInt...OK
+StaticFinalFieldGetAndBitwiseOrReleaseLong...OK
+StaticFinalFieldGetAndBitwiseOrReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseOrReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseOrAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseOrAcquireByte...OK
+StaticFinalFieldGetAndBitwiseOrAcquireShort...OK
+StaticFinalFieldGetAndBitwiseOrAcquireChar...OK
+StaticFinalFieldGetAndBitwiseOrAcquireInt...OK
+StaticFinalFieldGetAndBitwiseOrAcquireLong...OK
+StaticFinalFieldGetAndBitwiseOrAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseOrAcquireDouble...OK
+StaticFinalFieldGetAndBitwiseAndBoolean...OK
+StaticFinalFieldGetAndBitwiseAndByte...OK
+StaticFinalFieldGetAndBitwiseAndShort...OK
+StaticFinalFieldGetAndBitwiseAndChar...OK
+StaticFinalFieldGetAndBitwiseAndInt...OK
+StaticFinalFieldGetAndBitwiseAndLong...OK
+StaticFinalFieldGetAndBitwiseAndFloat...OK
+StaticFinalFieldGetAndBitwiseAndDouble...OK
+StaticFinalFieldGetAndBitwiseAndReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseAndReleaseByte...OK
+StaticFinalFieldGetAndBitwiseAndReleaseShort...OK
+StaticFinalFieldGetAndBitwiseAndReleaseChar...OK
+StaticFinalFieldGetAndBitwiseAndReleaseInt...OK
+StaticFinalFieldGetAndBitwiseAndReleaseLong...OK
+StaticFinalFieldGetAndBitwiseAndReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseAndReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseAndAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseAndAcquireByte...OK
+StaticFinalFieldGetAndBitwiseAndAcquireShort...OK
+StaticFinalFieldGetAndBitwiseAndAcquireChar...OK
+StaticFinalFieldGetAndBitwiseAndAcquireInt...OK
+StaticFinalFieldGetAndBitwiseAndAcquireLong...OK
+StaticFinalFieldGetAndBitwiseAndAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseAndAcquireDouble...OK
+StaticFinalFieldGetAndBitwiseXorBoolean...OK
+StaticFinalFieldGetAndBitwiseXorByte...OK
+StaticFinalFieldGetAndBitwiseXorShort...OK
+StaticFinalFieldGetAndBitwiseXorChar...OK
+StaticFinalFieldGetAndBitwiseXorInt...OK
+StaticFinalFieldGetAndBitwiseXorLong...OK
+StaticFinalFieldGetAndBitwiseXorFloat...OK
+StaticFinalFieldGetAndBitwiseXorDouble...OK
+StaticFinalFieldGetAndBitwiseXorReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseXorReleaseByte...OK
+StaticFinalFieldGetAndBitwiseXorReleaseShort...OK
+StaticFinalFieldGetAndBitwiseXorReleaseChar...OK
+StaticFinalFieldGetAndBitwiseXorReleaseInt...OK
+StaticFinalFieldGetAndBitwiseXorReleaseLong...OK
+StaticFinalFieldGetAndBitwiseXorReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseXorReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseXorAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseXorAcquireByte...OK
+StaticFinalFieldGetAndBitwiseXorAcquireShort...OK
+StaticFinalFieldGetAndBitwiseXorAcquireChar...OK
+StaticFinalFieldGetAndBitwiseXorAcquireInt...OK
+StaticFinalFieldGetAndBitwiseXorAcquireLong...OK
+StaticFinalFieldGetAndBitwiseXorAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseXorAcquireDouble...OK
+ArrayElementGetBoolean...OK
+ArrayElementGetByte...OK
+ArrayElementGetShort...OK
+ArrayElementGetChar...OK
+ArrayElementGetInt...OK
+ArrayElementGetLong...OK
+ArrayElementGetFloat...OK
+ArrayElementGetDouble...OK
+ArrayElementSetBoolean...OK
+ArrayElementSetByte...OK
+ArrayElementSetShort...OK
+ArrayElementSetChar...OK
+ArrayElementSetInt...OK
+ArrayElementSetLong...OK
+ArrayElementSetFloat...OK
+ArrayElementSetDouble...OK
+ArrayElementGetVolatileBoolean...OK
+ArrayElementGetVolatileByte...OK
+ArrayElementGetVolatileShort...OK
+ArrayElementGetVolatileChar...OK
+ArrayElementGetVolatileInt...OK
+ArrayElementGetVolatileLong...OK
+ArrayElementGetVolatileFloat...OK
+ArrayElementGetVolatileDouble...OK
+ArrayElementSetVolatileBoolean...OK
+ArrayElementSetVolatileByte...OK
+ArrayElementSetVolatileShort...OK
+ArrayElementSetVolatileChar...OK
+ArrayElementSetVolatileInt...OK
+ArrayElementSetVolatileLong...OK
+ArrayElementSetVolatileFloat...OK
+ArrayElementSetVolatileDouble...OK
+ArrayElementGetAcquireBoolean...OK
+ArrayElementGetAcquireByte...OK
+ArrayElementGetAcquireShort...OK
+ArrayElementGetAcquireChar...OK
+ArrayElementGetAcquireInt...OK
+ArrayElementGetAcquireLong...OK
+ArrayElementGetAcquireFloat...OK
+ArrayElementGetAcquireDouble...OK
+ArrayElementSetReleaseBoolean...OK
+ArrayElementSetReleaseByte...OK
+ArrayElementSetReleaseShort...OK
+ArrayElementSetReleaseChar...OK
+ArrayElementSetReleaseInt...OK
+ArrayElementSetReleaseLong...OK
+ArrayElementSetReleaseFloat...OK
+ArrayElementSetReleaseDouble...OK
+ArrayElementGetOpaqueBoolean...OK
+ArrayElementGetOpaqueByte...OK
+ArrayElementGetOpaqueShort...OK
+ArrayElementGetOpaqueChar...OK
+ArrayElementGetOpaqueInt...OK
+ArrayElementGetOpaqueLong...OK
+ArrayElementGetOpaqueFloat...OK
+ArrayElementGetOpaqueDouble...OK
+ArrayElementSetOpaqueBoolean...OK
+ArrayElementSetOpaqueByte...OK
+ArrayElementSetOpaqueShort...OK
+ArrayElementSetOpaqueChar...OK
+ArrayElementSetOpaqueInt...OK
+ArrayElementSetOpaqueLong...OK
+ArrayElementSetOpaqueFloat...OK
+ArrayElementSetOpaqueDouble...OK
+ArrayElementCompareAndSetBoolean...OK
+ArrayElementCompareAndSetByte...OK
+ArrayElementCompareAndSetShort...OK
+ArrayElementCompareAndSetChar...OK
+ArrayElementCompareAndSetInt...OK
+ArrayElementCompareAndSetLong...OK
+ArrayElementCompareAndSetFloat...OK
+ArrayElementCompareAndSetDouble...OK
+ArrayElementCompareAndExchangeBoolean...OK
+ArrayElementCompareAndExchangeByte...OK
+ArrayElementCompareAndExchangeShort...OK
+ArrayElementCompareAndExchangeChar...OK
+ArrayElementCompareAndExchangeInt...OK
+ArrayElementCompareAndExchangeLong...OK
+ArrayElementCompareAndExchangeFloat...OK
+ArrayElementCompareAndExchangeDouble...OK
+ArrayElementCompareAndExchangeAcquireBoolean...OK
+ArrayElementCompareAndExchangeAcquireByte...OK
+ArrayElementCompareAndExchangeAcquireShort...OK
+ArrayElementCompareAndExchangeAcquireChar...OK
+ArrayElementCompareAndExchangeAcquireInt...OK
+ArrayElementCompareAndExchangeAcquireLong...OK
+ArrayElementCompareAndExchangeAcquireFloat...OK
+ArrayElementCompareAndExchangeAcquireDouble...OK
+ArrayElementCompareAndExchangeReleaseBoolean...OK
+ArrayElementCompareAndExchangeReleaseByte...OK
+ArrayElementCompareAndExchangeReleaseShort...OK
+ArrayElementCompareAndExchangeReleaseChar...OK
+ArrayElementCompareAndExchangeReleaseInt...OK
+ArrayElementCompareAndExchangeReleaseLong...OK
+ArrayElementCompareAndExchangeReleaseFloat...OK
+ArrayElementCompareAndExchangeReleaseDouble...OK
+ArrayElementWeakCompareAndSetPlainBoolean...OK
+ArrayElementWeakCompareAndSetPlainByte...OK
+ArrayElementWeakCompareAndSetPlainShort...OK
+ArrayElementWeakCompareAndSetPlainChar...OK
+ArrayElementWeakCompareAndSetPlainInt...OK
+ArrayElementWeakCompareAndSetPlainLong...OK
+ArrayElementWeakCompareAndSetPlainFloat...OK
+ArrayElementWeakCompareAndSetPlainDouble...OK
+ArrayElementWeakCompareAndSetBoolean...OK
+ArrayElementWeakCompareAndSetByte...OK
+ArrayElementWeakCompareAndSetShort...OK
+ArrayElementWeakCompareAndSetChar...OK
+ArrayElementWeakCompareAndSetInt...OK
+ArrayElementWeakCompareAndSetLong...OK
+ArrayElementWeakCompareAndSetFloat...OK
+ArrayElementWeakCompareAndSetDouble...OK
+ArrayElementWeakCompareAndSetAcquireBoolean...OK
+ArrayElementWeakCompareAndSetAcquireByte...OK
+ArrayElementWeakCompareAndSetAcquireShort...OK
+ArrayElementWeakCompareAndSetAcquireChar...OK
+ArrayElementWeakCompareAndSetAcquireInt...OK
+ArrayElementWeakCompareAndSetAcquireLong...OK
+ArrayElementWeakCompareAndSetAcquireFloat...OK
+ArrayElementWeakCompareAndSetAcquireDouble...OK
+ArrayElementWeakCompareAndSetReleaseBoolean...OK
+ArrayElementWeakCompareAndSetReleaseByte...OK
+ArrayElementWeakCompareAndSetReleaseShort...OK
+ArrayElementWeakCompareAndSetReleaseChar...OK
+ArrayElementWeakCompareAndSetReleaseInt...OK
+ArrayElementWeakCompareAndSetReleaseLong...OK
+ArrayElementWeakCompareAndSetReleaseFloat...OK
+ArrayElementWeakCompareAndSetReleaseDouble...OK
+ArrayElementGetAndSetBoolean...OK
+ArrayElementGetAndSetByte...OK
+ArrayElementGetAndSetShort...OK
+ArrayElementGetAndSetChar...OK
+ArrayElementGetAndSetInt...OK
+ArrayElementGetAndSetLong...OK
+ArrayElementGetAndSetFloat...OK
+ArrayElementGetAndSetDouble...OK
+ArrayElementGetAndSetAcquireBoolean...OK
+ArrayElementGetAndSetAcquireByte...OK
+ArrayElementGetAndSetAcquireShort...OK
+ArrayElementGetAndSetAcquireChar...OK
+ArrayElementGetAndSetAcquireInt...OK
+ArrayElementGetAndSetAcquireLong...OK
+ArrayElementGetAndSetAcquireFloat...OK
+ArrayElementGetAndSetAcquireDouble...OK
+ArrayElementGetAndSetReleaseBoolean...OK
+ArrayElementGetAndSetReleaseByte...OK
+ArrayElementGetAndSetReleaseShort...OK
+ArrayElementGetAndSetReleaseChar...OK
+ArrayElementGetAndSetReleaseInt...OK
+ArrayElementGetAndSetReleaseLong...OK
+ArrayElementGetAndSetReleaseFloat...OK
+ArrayElementGetAndSetReleaseDouble...OK
+ArrayElementGetAndAddBoolean...OK
+ArrayElementGetAndAddByte...OK
+ArrayElementGetAndAddShort...OK
+ArrayElementGetAndAddChar...OK
+ArrayElementGetAndAddInt...OK
+ArrayElementGetAndAddLong...OK
+ArrayElementGetAndAddFloat...OK
+ArrayElementGetAndAddDouble...OK
+ArrayElementGetAndAddAcquireBoolean...OK
+ArrayElementGetAndAddAcquireByte...OK
+ArrayElementGetAndAddAcquireShort...OK
+ArrayElementGetAndAddAcquireChar...OK
+ArrayElementGetAndAddAcquireInt...OK
+ArrayElementGetAndAddAcquireLong...OK
+ArrayElementGetAndAddAcquireFloat...OK
+ArrayElementGetAndAddAcquireDouble...OK
+ArrayElementGetAndAddReleaseBoolean...OK
+ArrayElementGetAndAddReleaseByte...OK
+ArrayElementGetAndAddReleaseShort...OK
+ArrayElementGetAndAddReleaseChar...OK
+ArrayElementGetAndAddReleaseInt...OK
+ArrayElementGetAndAddReleaseLong...OK
+ArrayElementGetAndAddReleaseFloat...OK
+ArrayElementGetAndAddReleaseDouble...OK
+ArrayElementGetAndBitwiseOrBoolean...OK
+ArrayElementGetAndBitwiseOrByte...OK
+ArrayElementGetAndBitwiseOrShort...OK
+ArrayElementGetAndBitwiseOrChar...OK
+ArrayElementGetAndBitwiseOrInt...OK
+ArrayElementGetAndBitwiseOrLong...OK
+ArrayElementGetAndBitwiseOrFloat...OK
+ArrayElementGetAndBitwiseOrDouble...OK
+ArrayElementGetAndBitwiseOrReleaseBoolean...OK
+ArrayElementGetAndBitwiseOrReleaseByte...OK
+ArrayElementGetAndBitwiseOrReleaseShort...OK
+ArrayElementGetAndBitwiseOrReleaseChar...OK
+ArrayElementGetAndBitwiseOrReleaseInt...OK
+ArrayElementGetAndBitwiseOrReleaseLong...OK
+ArrayElementGetAndBitwiseOrReleaseFloat...OK
+ArrayElementGetAndBitwiseOrReleaseDouble...OK
+ArrayElementGetAndBitwiseOrAcquireBoolean...OK
+ArrayElementGetAndBitwiseOrAcquireByte...OK
+ArrayElementGetAndBitwiseOrAcquireShort...OK
+ArrayElementGetAndBitwiseOrAcquireChar...OK
+ArrayElementGetAndBitwiseOrAcquireInt...OK
+ArrayElementGetAndBitwiseOrAcquireLong...OK
+ArrayElementGetAndBitwiseOrAcquireFloat...OK
+ArrayElementGetAndBitwiseOrAcquireDouble...OK
+ArrayElementGetAndBitwiseAndBoolean...OK
+ArrayElementGetAndBitwiseAndByte...OK
+ArrayElementGetAndBitwiseAndShort...OK
+ArrayElementGetAndBitwiseAndChar...OK
+ArrayElementGetAndBitwiseAndInt...OK
+ArrayElementGetAndBitwiseAndLong...OK
+ArrayElementGetAndBitwiseAndFloat...OK
+ArrayElementGetAndBitwiseAndDouble...OK
+ArrayElementGetAndBitwiseAndReleaseBoolean...OK
+ArrayElementGetAndBitwiseAndReleaseByte...OK
+ArrayElementGetAndBitwiseAndReleaseShort...OK
+ArrayElementGetAndBitwiseAndReleaseChar...OK
+ArrayElementGetAndBitwiseAndReleaseInt...OK
+ArrayElementGetAndBitwiseAndReleaseLong...OK
+ArrayElementGetAndBitwiseAndReleaseFloat...OK
+ArrayElementGetAndBitwiseAndReleaseDouble...OK
+ArrayElementGetAndBitwiseAndAcquireBoolean...OK
+ArrayElementGetAndBitwiseAndAcquireByte...OK
+ArrayElementGetAndBitwiseAndAcquireShort...OK
+ArrayElementGetAndBitwiseAndAcquireChar...OK
+ArrayElementGetAndBitwiseAndAcquireInt...OK
+ArrayElementGetAndBitwiseAndAcquireLong...OK
+ArrayElementGetAndBitwiseAndAcquireFloat...OK
+ArrayElementGetAndBitwiseAndAcquireDouble...OK
+ArrayElementGetAndBitwiseXorBoolean...OK
+ArrayElementGetAndBitwiseXorByte...OK
+ArrayElementGetAndBitwiseXorShort...OK
+ArrayElementGetAndBitwiseXorChar...OK
+ArrayElementGetAndBitwiseXorInt...OK
+ArrayElementGetAndBitwiseXorLong...OK
+ArrayElementGetAndBitwiseXorFloat...OK
+ArrayElementGetAndBitwiseXorDouble...OK
+ArrayElementGetAndBitwiseXorReleaseBoolean...OK
+ArrayElementGetAndBitwiseXorReleaseByte...OK
+ArrayElementGetAndBitwiseXorReleaseShort...OK
+ArrayElementGetAndBitwiseXorReleaseChar...OK
+ArrayElementGetAndBitwiseXorReleaseInt...OK
+ArrayElementGetAndBitwiseXorReleaseLong...OK
+ArrayElementGetAndBitwiseXorReleaseFloat...OK
+ArrayElementGetAndBitwiseXorReleaseDouble...OK
+ArrayElementGetAndBitwiseXorAcquireBoolean...OK
+ArrayElementGetAndBitwiseXorAcquireByte...OK
+ArrayElementGetAndBitwiseXorAcquireShort...OK
+ArrayElementGetAndBitwiseXorAcquireChar...OK
+ArrayElementGetAndBitwiseXorAcquireInt...OK
+ArrayElementGetAndBitwiseXorAcquireLong...OK
+ArrayElementGetAndBitwiseXorAcquireFloat...OK
+ArrayElementGetAndBitwiseXorAcquireDouble...OK
+ByteArrayViewLEGetShort...OK
+ByteArrayViewLEGetChar...OK
+ByteArrayViewLEGetInt...OK
+ByteArrayViewLEGetLong...OK
+ByteArrayViewLEGetFloat...OK
+ByteArrayViewLEGetDouble...OK
+ByteArrayViewLESetShort...OK
+ByteArrayViewLESetChar...OK
+ByteArrayViewLESetInt...OK
+ByteArrayViewLESetLong...OK
+ByteArrayViewLESetFloat...OK
+ByteArrayViewLESetDouble...OK
+ByteArrayViewLEGetVolatileShort...OK
+ByteArrayViewLEGetVolatileChar...OK
+ByteArrayViewLEGetVolatileInt...OK
+ByteArrayViewLEGetVolatileLong...OK
+ByteArrayViewLEGetVolatileFloat...OK
+ByteArrayViewLEGetVolatileDouble...OK
+ByteArrayViewLESetVolatileShort...OK
+ByteArrayViewLESetVolatileChar...OK
+ByteArrayViewLESetVolatileInt...OK
+ByteArrayViewLESetVolatileLong...OK
+ByteArrayViewLESetVolatileFloat...OK
+ByteArrayViewLESetVolatileDouble...OK
+ByteArrayViewLEGetAcquireShort...OK
+ByteArrayViewLEGetAcquireChar...OK
+ByteArrayViewLEGetAcquireInt...OK
+ByteArrayViewLEGetAcquireLong...OK
+ByteArrayViewLEGetAcquireFloat...OK
+ByteArrayViewLEGetAcquireDouble...OK
+ByteArrayViewLESetReleaseShort...OK
+ByteArrayViewLESetReleaseChar...OK
+ByteArrayViewLESetReleaseInt...OK
+ByteArrayViewLESetReleaseLong...OK
+ByteArrayViewLESetReleaseFloat...OK
+ByteArrayViewLESetReleaseDouble...OK
+ByteArrayViewLEGetOpaqueShort...OK
+ByteArrayViewLEGetOpaqueChar...OK
+ByteArrayViewLEGetOpaqueInt...OK
+ByteArrayViewLEGetOpaqueLong...OK
+ByteArrayViewLEGetOpaqueFloat...OK
+ByteArrayViewLEGetOpaqueDouble...OK
+ByteArrayViewLESetOpaqueShort...OK
+ByteArrayViewLESetOpaqueChar...OK
+ByteArrayViewLESetOpaqueInt...OK
+ByteArrayViewLESetOpaqueLong...OK
+ByteArrayViewLESetOpaqueFloat...OK
+ByteArrayViewLESetOpaqueDouble...OK
+ByteArrayViewLECompareAndSetShort...OK
+ByteArrayViewLECompareAndSetChar...OK
+ByteArrayViewLECompareAndSetInt...OK
+ByteArrayViewLECompareAndSetLong...OK
+ByteArrayViewLECompareAndSetFloat...OK
+ByteArrayViewLECompareAndSetDouble...OK
+ByteArrayViewLECompareAndExchangeShort...OK
+ByteArrayViewLECompareAndExchangeChar...OK
+ByteArrayViewLECompareAndExchangeInt...OK
+ByteArrayViewLECompareAndExchangeLong...OK
+ByteArrayViewLECompareAndExchangeFloat...OK
+ByteArrayViewLECompareAndExchangeDouble...OK
+ByteArrayViewLECompareAndExchangeAcquireShort...OK
+ByteArrayViewLECompareAndExchangeAcquireChar...OK
+ByteArrayViewLECompareAndExchangeAcquireInt...OK
+ByteArrayViewLECompareAndExchangeAcquireLong...OK
+ByteArrayViewLECompareAndExchangeAcquireFloat...OK
+ByteArrayViewLECompareAndExchangeAcquireDouble...OK
+ByteArrayViewLECompareAndExchangeReleaseShort...OK
+ByteArrayViewLECompareAndExchangeReleaseChar...OK
+ByteArrayViewLECompareAndExchangeReleaseInt...OK
+ByteArrayViewLECompareAndExchangeReleaseLong...OK
+ByteArrayViewLECompareAndExchangeReleaseFloat...OK
+ByteArrayViewLECompareAndExchangeReleaseDouble...OK
+ByteArrayViewLEWeakCompareAndSetPlainShort...OK
+ByteArrayViewLEWeakCompareAndSetPlainChar...OK
+ByteArrayViewLEWeakCompareAndSetPlainInt...OK
+ByteArrayViewLEWeakCompareAndSetPlainLong...OK
+ByteArrayViewLEWeakCompareAndSetPlainFloat...OK
+ByteArrayViewLEWeakCompareAndSetPlainDouble...OK
+ByteArrayViewLEWeakCompareAndSetShort...OK
+ByteArrayViewLEWeakCompareAndSetChar...OK
+ByteArrayViewLEWeakCompareAndSetInt...OK
+ByteArrayViewLEWeakCompareAndSetLong...OK
+ByteArrayViewLEWeakCompareAndSetFloat...OK
+ByteArrayViewLEWeakCompareAndSetDouble...OK
+ByteArrayViewLEWeakCompareAndSetAcquireShort...OK
+ByteArrayViewLEWeakCompareAndSetAcquireChar...OK
+ByteArrayViewLEWeakCompareAndSetAcquireInt...OK
+ByteArrayViewLEWeakCompareAndSetAcquireLong...OK
+ByteArrayViewLEWeakCompareAndSetAcquireFloat...OK
+ByteArrayViewLEWeakCompareAndSetAcquireDouble...OK
+ByteArrayViewLEWeakCompareAndSetReleaseShort...OK
+ByteArrayViewLEWeakCompareAndSetReleaseChar...OK
+ByteArrayViewLEWeakCompareAndSetReleaseInt...OK
+ByteArrayViewLEWeakCompareAndSetReleaseLong...OK
+ByteArrayViewLEWeakCompareAndSetReleaseFloat...OK
+ByteArrayViewLEWeakCompareAndSetReleaseDouble...OK
+ByteArrayViewLEGetAndSetShort...OK
+ByteArrayViewLEGetAndSetChar...OK
+ByteArrayViewLEGetAndSetInt...OK
+ByteArrayViewLEGetAndSetLong...OK
+ByteArrayViewLEGetAndSetFloat...OK
+ByteArrayViewLEGetAndSetDouble...OK
+ByteArrayViewLEGetAndSetAcquireShort...OK
+ByteArrayViewLEGetAndSetAcquireChar...OK
+ByteArrayViewLEGetAndSetAcquireInt...OK
+ByteArrayViewLEGetAndSetAcquireLong...OK
+ByteArrayViewLEGetAndSetAcquireFloat...OK
+ByteArrayViewLEGetAndSetAcquireDouble...OK
+ByteArrayViewLEGetAndSetReleaseShort...OK
+ByteArrayViewLEGetAndSetReleaseChar...OK
+ByteArrayViewLEGetAndSetReleaseInt...OK
+ByteArrayViewLEGetAndSetReleaseLong...OK
+ByteArrayViewLEGetAndSetReleaseFloat...OK
+ByteArrayViewLEGetAndSetReleaseDouble...OK
+ByteArrayViewLEGetAndAddShort...OK
+ByteArrayViewLEGetAndAddChar...OK
+ByteArrayViewLEGetAndAddInt...OK
+ByteArrayViewLEGetAndAddLong...OK
+ByteArrayViewLEGetAndAddFloat...OK
+ByteArrayViewLEGetAndAddDouble...OK
+ByteArrayViewLEGetAndAddAcquireShort...OK
+ByteArrayViewLEGetAndAddAcquireChar...OK
+ByteArrayViewLEGetAndAddAcquireInt...OK
+ByteArrayViewLEGetAndAddAcquireLong...OK
+ByteArrayViewLEGetAndAddAcquireFloat...OK
+ByteArrayViewLEGetAndAddAcquireDouble...OK
+ByteArrayViewLEGetAndAddReleaseShort...OK
+ByteArrayViewLEGetAndAddReleaseChar...OK
+ByteArrayViewLEGetAndAddReleaseInt...OK
+ByteArrayViewLEGetAndAddReleaseLong...OK
+ByteArrayViewLEGetAndAddReleaseFloat...OK
+ByteArrayViewLEGetAndAddReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseOrShort...OK
+ByteArrayViewLEGetAndBitwiseOrChar...OK
+ByteArrayViewLEGetAndBitwiseOrInt...OK
+ByteArrayViewLEGetAndBitwiseOrLong...OK
+ByteArrayViewLEGetAndBitwiseOrFloat...OK
+ByteArrayViewLEGetAndBitwiseOrDouble...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireDouble...OK
+ByteArrayViewLEGetAndBitwiseAndShort...OK
+ByteArrayViewLEGetAndBitwiseAndChar...OK
+ByteArrayViewLEGetAndBitwiseAndInt...OK
+ByteArrayViewLEGetAndBitwiseAndLong...OK
+ByteArrayViewLEGetAndBitwiseAndFloat...OK
+ByteArrayViewLEGetAndBitwiseAndDouble...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireDouble...OK
+ByteArrayViewLEGetAndBitwiseXorShort...OK
+ByteArrayViewLEGetAndBitwiseXorChar...OK
+ByteArrayViewLEGetAndBitwiseXorInt...OK
+ByteArrayViewLEGetAndBitwiseXorLong...OK
+ByteArrayViewLEGetAndBitwiseXorFloat...OK
+ByteArrayViewLEGetAndBitwiseXorDouble...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireDouble...OK
+ByteArrayViewBEGetShort...OK
+ByteArrayViewBEGetChar...OK
+ByteArrayViewBEGetInt...OK
+ByteArrayViewBEGetLong...OK
+ByteArrayViewBEGetFloat...OK
+ByteArrayViewBEGetDouble...OK
+ByteArrayViewBESetShort...OK
+ByteArrayViewBESetChar...OK
+ByteArrayViewBESetInt...OK
+ByteArrayViewBESetLong...OK
+ByteArrayViewBESetFloat...OK
+ByteArrayViewBESetDouble...OK
+ByteArrayViewBEGetVolatileShort...OK
+ByteArrayViewBEGetVolatileChar...OK
+ByteArrayViewBEGetVolatileInt...OK
+ByteArrayViewBEGetVolatileLong...OK
+ByteArrayViewBEGetVolatileFloat...OK
+ByteArrayViewBEGetVolatileDouble...OK
+ByteArrayViewBESetVolatileShort...OK
+ByteArrayViewBESetVolatileChar...OK
+ByteArrayViewBESetVolatileInt...OK
+ByteArrayViewBESetVolatileLong...OK
+ByteArrayViewBESetVolatileFloat...OK
+ByteArrayViewBESetVolatileDouble...OK
+ByteArrayViewBEGetAcquireShort...OK
+ByteArrayViewBEGetAcquireChar...OK
+ByteArrayViewBEGetAcquireInt...OK
+ByteArrayViewBEGetAcquireLong...OK
+ByteArrayViewBEGetAcquireFloat...OK
+ByteArrayViewBEGetAcquireDouble...OK
+ByteArrayViewBESetReleaseShort...OK
+ByteArrayViewBESetReleaseChar...OK
+ByteArrayViewBESetReleaseInt...OK
+ByteArrayViewBESetReleaseLong...OK
+ByteArrayViewBESetReleaseFloat...OK
+ByteArrayViewBESetReleaseDouble...OK
+ByteArrayViewBEGetOpaqueShort...OK
+ByteArrayViewBEGetOpaqueChar...OK
+ByteArrayViewBEGetOpaqueInt...OK
+ByteArrayViewBEGetOpaqueLong...OK
+ByteArrayViewBEGetOpaqueFloat...OK
+ByteArrayViewBEGetOpaqueDouble...OK
+ByteArrayViewBESetOpaqueShort...OK
+ByteArrayViewBESetOpaqueChar...OK
+ByteArrayViewBESetOpaqueInt...OK
+ByteArrayViewBESetOpaqueLong...OK
+ByteArrayViewBESetOpaqueFloat...OK
+ByteArrayViewBESetOpaqueDouble...OK
+ByteArrayViewBECompareAndSetShort...OK
+ByteArrayViewBECompareAndSetChar...OK
+ByteArrayViewBECompareAndSetInt...OK
+ByteArrayViewBECompareAndSetLong...OK
+ByteArrayViewBECompareAndSetFloat...OK
+ByteArrayViewBECompareAndSetDouble...OK
+ByteArrayViewBECompareAndExchangeShort...OK
+ByteArrayViewBECompareAndExchangeChar...OK
+ByteArrayViewBECompareAndExchangeInt...OK
+ByteArrayViewBECompareAndExchangeLong...OK
+ByteArrayViewBECompareAndExchangeFloat...OK
+ByteArrayViewBECompareAndExchangeDouble...OK
+ByteArrayViewBECompareAndExchangeAcquireShort...OK
+ByteArrayViewBECompareAndExchangeAcquireChar...OK
+ByteArrayViewBECompareAndExchangeAcquireInt...OK
+ByteArrayViewBECompareAndExchangeAcquireLong...OK
+ByteArrayViewBECompareAndExchangeAcquireFloat...OK
+ByteArrayViewBECompareAndExchangeAcquireDouble...OK
+ByteArrayViewBECompareAndExchangeReleaseShort...OK
+ByteArrayViewBECompareAndExchangeReleaseChar...OK
+ByteArrayViewBECompareAndExchangeReleaseInt...OK
+ByteArrayViewBECompareAndExchangeReleaseLong...OK
+ByteArrayViewBECompareAndExchangeReleaseFloat...OK
+ByteArrayViewBECompareAndExchangeReleaseDouble...OK
+ByteArrayViewBEWeakCompareAndSetPlainShort...OK
+ByteArrayViewBEWeakCompareAndSetPlainChar...OK
+ByteArrayViewBEWeakCompareAndSetPlainInt...OK
+ByteArrayViewBEWeakCompareAndSetPlainLong...OK
+ByteArrayViewBEWeakCompareAndSetPlainFloat...OK
+ByteArrayViewBEWeakCompareAndSetPlainDouble...OK
+ByteArrayViewBEWeakCompareAndSetShort...OK
+ByteArrayViewBEWeakCompareAndSetChar...OK
+ByteArrayViewBEWeakCompareAndSetInt...OK
+ByteArrayViewBEWeakCompareAndSetLong...OK
+ByteArrayViewBEWeakCompareAndSetFloat...OK
+ByteArrayViewBEWeakCompareAndSetDouble...OK
+ByteArrayViewBEWeakCompareAndSetAcquireShort...OK
+ByteArrayViewBEWeakCompareAndSetAcquireChar...OK
+ByteArrayViewBEWeakCompareAndSetAcquireInt...OK
+ByteArrayViewBEWeakCompareAndSetAcquireLong...OK
+ByteArrayViewBEWeakCompareAndSetAcquireFloat...OK
+ByteArrayViewBEWeakCompareAndSetAcquireDouble...OK
+ByteArrayViewBEWeakCompareAndSetReleaseShort...OK
+ByteArrayViewBEWeakCompareAndSetReleaseChar...OK
+ByteArrayViewBEWeakCompareAndSetReleaseInt...OK
+ByteArrayViewBEWeakCompareAndSetReleaseLong...OK
+ByteArrayViewBEWeakCompareAndSetReleaseFloat...OK
+ByteArrayViewBEWeakCompareAndSetReleaseDouble...OK
+ByteArrayViewBEGetAndSetShort...OK
+ByteArrayViewBEGetAndSetChar...OK
+ByteArrayViewBEGetAndSetInt...OK
+ByteArrayViewBEGetAndSetLong...OK
+ByteArrayViewBEGetAndSetFloat...OK
+ByteArrayViewBEGetAndSetDouble...OK
+ByteArrayViewBEGetAndSetAcquireShort...OK
+ByteArrayViewBEGetAndSetAcquireChar...OK
+ByteArrayViewBEGetAndSetAcquireInt...OK
+ByteArrayViewBEGetAndSetAcquireLong...OK
+ByteArrayViewBEGetAndSetAcquireFloat...OK
+ByteArrayViewBEGetAndSetAcquireDouble...OK
+ByteArrayViewBEGetAndSetReleaseShort...OK
+ByteArrayViewBEGetAndSetReleaseChar...OK
+ByteArrayViewBEGetAndSetReleaseInt...OK
+ByteArrayViewBEGetAndSetReleaseLong...OK
+ByteArrayViewBEGetAndSetReleaseFloat...OK
+ByteArrayViewBEGetAndSetReleaseDouble...OK
+ByteArrayViewBEGetAndAddShort...OK
+ByteArrayViewBEGetAndAddChar...OK
+ByteArrayViewBEGetAndAddInt...OK
+ByteArrayViewBEGetAndAddLong...OK
+ByteArrayViewBEGetAndAddFloat...OK
+ByteArrayViewBEGetAndAddDouble...OK
+ByteArrayViewBEGetAndAddAcquireShort...OK
+ByteArrayViewBEGetAndAddAcquireChar...OK
+ByteArrayViewBEGetAndAddAcquireInt...OK
+ByteArrayViewBEGetAndAddAcquireLong...OK
+ByteArrayViewBEGetAndAddAcquireFloat...OK
+ByteArrayViewBEGetAndAddAcquireDouble...OK
+ByteArrayViewBEGetAndAddReleaseShort...OK
+ByteArrayViewBEGetAndAddReleaseChar...OK
+ByteArrayViewBEGetAndAddReleaseInt...OK
+ByteArrayViewBEGetAndAddReleaseLong...OK
+ByteArrayViewBEGetAndAddReleaseFloat...OK
+ByteArrayViewBEGetAndAddReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseOrShort...OK
+ByteArrayViewBEGetAndBitwiseOrChar...OK
+ByteArrayViewBEGetAndBitwiseOrInt...OK
+ByteArrayViewBEGetAndBitwiseOrLong...OK
+ByteArrayViewBEGetAndBitwiseOrFloat...OK
+ByteArrayViewBEGetAndBitwiseOrDouble...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireDouble...OK
+ByteArrayViewBEGetAndBitwiseAndShort...OK
+ByteArrayViewBEGetAndBitwiseAndChar...OK
+ByteArrayViewBEGetAndBitwiseAndInt...OK
+ByteArrayViewBEGetAndBitwiseAndLong...OK
+ByteArrayViewBEGetAndBitwiseAndFloat...OK
+ByteArrayViewBEGetAndBitwiseAndDouble...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireDouble...OK
+ByteArrayViewBEGetAndBitwiseXorShort...OK
+ByteArrayViewBEGetAndBitwiseXorChar...OK
+ByteArrayViewBEGetAndBitwiseXorInt...OK
+ByteArrayViewBEGetAndBitwiseXorLong...OK
+ByteArrayViewBEGetAndBitwiseXorFloat...OK
+ByteArrayViewBEGetAndBitwiseXorDouble...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireDouble...OK
+DirectByteBufferViewLEGetShort...OK
+DirectByteBufferViewLEGetChar...OK
+DirectByteBufferViewLEGetInt...OK
+DirectByteBufferViewLEGetLong...OK
+DirectByteBufferViewLEGetFloat...OK
+DirectByteBufferViewLEGetDouble...OK
+DirectByteBufferViewLESetShort...OK
+DirectByteBufferViewLESetChar...OK
+DirectByteBufferViewLESetInt...OK
+DirectByteBufferViewLESetLong...OK
+DirectByteBufferViewLESetFloat...OK
+DirectByteBufferViewLESetDouble...OK
+DirectByteBufferViewLEGetVolatileShort...OK
+DirectByteBufferViewLEGetVolatileChar...OK
+DirectByteBufferViewLEGetVolatileInt...OK
+DirectByteBufferViewLEGetVolatileLong...OK
+DirectByteBufferViewLEGetVolatileFloat...OK
+DirectByteBufferViewLEGetVolatileDouble...OK
+DirectByteBufferViewLESetVolatileShort...OK
+DirectByteBufferViewLESetVolatileChar...OK
+DirectByteBufferViewLESetVolatileInt...OK
+DirectByteBufferViewLESetVolatileLong...OK
+DirectByteBufferViewLESetVolatileFloat...OK
+DirectByteBufferViewLESetVolatileDouble...OK
+DirectByteBufferViewLEGetAcquireShort...OK
+DirectByteBufferViewLEGetAcquireChar...OK
+DirectByteBufferViewLEGetAcquireInt...OK
+DirectByteBufferViewLEGetAcquireLong...OK
+DirectByteBufferViewLEGetAcquireFloat...OK
+DirectByteBufferViewLEGetAcquireDouble...OK
+DirectByteBufferViewLESetReleaseShort...OK
+DirectByteBufferViewLESetReleaseChar...OK
+DirectByteBufferViewLESetReleaseInt...OK
+DirectByteBufferViewLESetReleaseLong...OK
+DirectByteBufferViewLESetReleaseFloat...OK
+DirectByteBufferViewLESetReleaseDouble...OK
+DirectByteBufferViewLEGetOpaqueShort...OK
+DirectByteBufferViewLEGetOpaqueChar...OK
+DirectByteBufferViewLEGetOpaqueInt...OK
+DirectByteBufferViewLEGetOpaqueLong...OK
+DirectByteBufferViewLEGetOpaqueFloat...OK
+DirectByteBufferViewLEGetOpaqueDouble...OK
+DirectByteBufferViewLESetOpaqueShort...OK
+DirectByteBufferViewLESetOpaqueChar...OK
+DirectByteBufferViewLESetOpaqueInt...OK
+DirectByteBufferViewLESetOpaqueLong...OK
+DirectByteBufferViewLESetOpaqueFloat...OK
+DirectByteBufferViewLESetOpaqueDouble...OK
+DirectByteBufferViewLECompareAndSetShort...OK
+DirectByteBufferViewLECompareAndSetChar...OK
+DirectByteBufferViewLECompareAndSetInt...OK
+DirectByteBufferViewLECompareAndSetLong...OK
+DirectByteBufferViewLECompareAndSetFloat...OK
+DirectByteBufferViewLECompareAndSetDouble...OK
+DirectByteBufferViewLECompareAndExchangeShort...OK
+DirectByteBufferViewLECompareAndExchangeChar...OK
+DirectByteBufferViewLECompareAndExchangeInt...OK
+DirectByteBufferViewLECompareAndExchangeLong...OK
+DirectByteBufferViewLECompareAndExchangeFloat...OK
+DirectByteBufferViewLECompareAndExchangeDouble...OK
+DirectByteBufferViewLECompareAndExchangeAcquireShort...OK
+DirectByteBufferViewLECompareAndExchangeAcquireChar...OK
+DirectByteBufferViewLECompareAndExchangeAcquireInt...OK
+DirectByteBufferViewLECompareAndExchangeAcquireLong...OK
+DirectByteBufferViewLECompareAndExchangeAcquireFloat...OK
+DirectByteBufferViewLECompareAndExchangeAcquireDouble...OK
+DirectByteBufferViewLECompareAndExchangeReleaseShort...OK
+DirectByteBufferViewLECompareAndExchangeReleaseChar...OK
+DirectByteBufferViewLECompareAndExchangeReleaseInt...OK
+DirectByteBufferViewLECompareAndExchangeReleaseLong...OK
+DirectByteBufferViewLECompareAndExchangeReleaseFloat...OK
+DirectByteBufferViewLECompareAndExchangeReleaseDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainShort...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainChar...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainInt...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainLong...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetShort...OK
+DirectByteBufferViewLEWeakCompareAndSetChar...OK
+DirectByteBufferViewLEWeakCompareAndSetInt...OK
+DirectByteBufferViewLEWeakCompareAndSetLong...OK
+DirectByteBufferViewLEWeakCompareAndSetFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireShort...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireChar...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireInt...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireLong...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseShort...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseChar...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseInt...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseLong...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
+DirectByteBufferViewLEGetAndSetShort...OK
+DirectByteBufferViewLEGetAndSetChar...OK
+DirectByteBufferViewLEGetAndSetInt...OK
+DirectByteBufferViewLEGetAndSetLong...OK
+DirectByteBufferViewLEGetAndSetFloat...OK
+DirectByteBufferViewLEGetAndSetDouble...OK
+DirectByteBufferViewLEGetAndSetAcquireShort...OK
+DirectByteBufferViewLEGetAndSetAcquireChar...OK
+DirectByteBufferViewLEGetAndSetAcquireInt...OK
+DirectByteBufferViewLEGetAndSetAcquireLong...OK
+DirectByteBufferViewLEGetAndSetAcquireFloat...OK
+DirectByteBufferViewLEGetAndSetAcquireDouble...OK
+DirectByteBufferViewLEGetAndSetReleaseShort...OK
+DirectByteBufferViewLEGetAndSetReleaseChar...OK
+DirectByteBufferViewLEGetAndSetReleaseInt...OK
+DirectByteBufferViewLEGetAndSetReleaseLong...OK
+DirectByteBufferViewLEGetAndSetReleaseFloat...OK
+DirectByteBufferViewLEGetAndSetReleaseDouble...OK
+DirectByteBufferViewLEGetAndAddShort...OK
+DirectByteBufferViewLEGetAndAddChar...OK
+DirectByteBufferViewLEGetAndAddInt...OK
+DirectByteBufferViewLEGetAndAddLong...OK
+DirectByteBufferViewLEGetAndAddFloat...OK
+DirectByteBufferViewLEGetAndAddDouble...OK
+DirectByteBufferViewLEGetAndAddAcquireShort...OK
+DirectByteBufferViewLEGetAndAddAcquireChar...OK
+DirectByteBufferViewLEGetAndAddAcquireInt...OK
+DirectByteBufferViewLEGetAndAddAcquireLong...OK
+DirectByteBufferViewLEGetAndAddAcquireFloat...OK
+DirectByteBufferViewLEGetAndAddAcquireDouble...OK
+DirectByteBufferViewLEGetAndAddReleaseShort...OK
+DirectByteBufferViewLEGetAndAddReleaseChar...OK
+DirectByteBufferViewLEGetAndAddReleaseInt...OK
+DirectByteBufferViewLEGetAndAddReleaseLong...OK
+DirectByteBufferViewLEGetAndAddReleaseFloat...OK
+DirectByteBufferViewLEGetAndAddReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
+DirectByteBufferViewBEGetShort...OK
+DirectByteBufferViewBEGetChar...OK
+DirectByteBufferViewBEGetInt...OK
+DirectByteBufferViewBEGetLong...OK
+DirectByteBufferViewBEGetFloat...OK
+DirectByteBufferViewBEGetDouble...OK
+DirectByteBufferViewBESetShort...OK
+DirectByteBufferViewBESetChar...OK
+DirectByteBufferViewBESetInt...OK
+DirectByteBufferViewBESetLong...OK
+DirectByteBufferViewBESetFloat...OK
+DirectByteBufferViewBESetDouble...OK
+DirectByteBufferViewBEGetVolatileShort...OK
+DirectByteBufferViewBEGetVolatileChar...OK
+DirectByteBufferViewBEGetVolatileInt...OK
+DirectByteBufferViewBEGetVolatileLong...OK
+DirectByteBufferViewBEGetVolatileFloat...OK
+DirectByteBufferViewBEGetVolatileDouble...OK
+DirectByteBufferViewBESetVolatileShort...OK
+DirectByteBufferViewBESetVolatileChar...OK
+DirectByteBufferViewBESetVolatileInt...OK
+DirectByteBufferViewBESetVolatileLong...OK
+DirectByteBufferViewBESetVolatileFloat...OK
+DirectByteBufferViewBESetVolatileDouble...OK
+DirectByteBufferViewBEGetAcquireShort...OK
+DirectByteBufferViewBEGetAcquireChar...OK
+DirectByteBufferViewBEGetAcquireInt...OK
+DirectByteBufferViewBEGetAcquireLong...OK
+DirectByteBufferViewBEGetAcquireFloat...OK
+DirectByteBufferViewBEGetAcquireDouble...OK
+DirectByteBufferViewBESetReleaseShort...OK
+DirectByteBufferViewBESetReleaseChar...OK
+DirectByteBufferViewBESetReleaseInt...OK
+DirectByteBufferViewBESetReleaseLong...OK
+DirectByteBufferViewBESetReleaseFloat...OK
+DirectByteBufferViewBESetReleaseDouble...OK
+DirectByteBufferViewBEGetOpaqueShort...OK
+DirectByteBufferViewBEGetOpaqueChar...OK
+DirectByteBufferViewBEGetOpaqueInt...OK
+DirectByteBufferViewBEGetOpaqueLong...OK
+DirectByteBufferViewBEGetOpaqueFloat...OK
+DirectByteBufferViewBEGetOpaqueDouble...OK
+DirectByteBufferViewBESetOpaqueShort...OK
+DirectByteBufferViewBESetOpaqueChar...OK
+DirectByteBufferViewBESetOpaqueInt...OK
+DirectByteBufferViewBESetOpaqueLong...OK
+DirectByteBufferViewBESetOpaqueFloat...OK
+DirectByteBufferViewBESetOpaqueDouble...OK
+DirectByteBufferViewBECompareAndSetShort...OK
+DirectByteBufferViewBECompareAndSetChar...OK
+DirectByteBufferViewBECompareAndSetInt...OK
+DirectByteBufferViewBECompareAndSetLong...OK
+DirectByteBufferViewBECompareAndSetFloat...OK
+DirectByteBufferViewBECompareAndSetDouble...OK
+DirectByteBufferViewBECompareAndExchangeShort...OK
+DirectByteBufferViewBECompareAndExchangeChar...OK
+DirectByteBufferViewBECompareAndExchangeInt...OK
+DirectByteBufferViewBECompareAndExchangeLong...OK
+DirectByteBufferViewBECompareAndExchangeFloat...OK
+DirectByteBufferViewBECompareAndExchangeDouble...OK
+DirectByteBufferViewBECompareAndExchangeAcquireShort...OK
+DirectByteBufferViewBECompareAndExchangeAcquireChar...OK
+DirectByteBufferViewBECompareAndExchangeAcquireInt...OK
+DirectByteBufferViewBECompareAndExchangeAcquireLong...OK
+DirectByteBufferViewBECompareAndExchangeAcquireFloat...OK
+DirectByteBufferViewBECompareAndExchangeAcquireDouble...OK
+DirectByteBufferViewBECompareAndExchangeReleaseShort...OK
+DirectByteBufferViewBECompareAndExchangeReleaseChar...OK
+DirectByteBufferViewBECompareAndExchangeReleaseInt...OK
+DirectByteBufferViewBECompareAndExchangeReleaseLong...OK
+DirectByteBufferViewBECompareAndExchangeReleaseFloat...OK
+DirectByteBufferViewBECompareAndExchangeReleaseDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainShort...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainChar...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainInt...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainLong...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetShort...OK
+DirectByteBufferViewBEWeakCompareAndSetChar...OK
+DirectByteBufferViewBEWeakCompareAndSetInt...OK
+DirectByteBufferViewBEWeakCompareAndSetLong...OK
+DirectByteBufferViewBEWeakCompareAndSetFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireShort...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireChar...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireInt...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireLong...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseShort...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseChar...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseInt...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseLong...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
+DirectByteBufferViewBEGetAndSetShort...OK
+DirectByteBufferViewBEGetAndSetChar...OK
+DirectByteBufferViewBEGetAndSetInt...OK
+DirectByteBufferViewBEGetAndSetLong...OK
+DirectByteBufferViewBEGetAndSetFloat...OK
+DirectByteBufferViewBEGetAndSetDouble...OK
+DirectByteBufferViewBEGetAndSetAcquireShort...OK
+DirectByteBufferViewBEGetAndSetAcquireChar...OK
+DirectByteBufferViewBEGetAndSetAcquireInt...OK
+DirectByteBufferViewBEGetAndSetAcquireLong...OK
+DirectByteBufferViewBEGetAndSetAcquireFloat...OK
+DirectByteBufferViewBEGetAndSetAcquireDouble...OK
+DirectByteBufferViewBEGetAndSetReleaseShort...OK
+DirectByteBufferViewBEGetAndSetReleaseChar...OK
+DirectByteBufferViewBEGetAndSetReleaseInt...OK
+DirectByteBufferViewBEGetAndSetReleaseLong...OK
+DirectByteBufferViewBEGetAndSetReleaseFloat...OK
+DirectByteBufferViewBEGetAndSetReleaseDouble...OK
+DirectByteBufferViewBEGetAndAddShort...OK
+DirectByteBufferViewBEGetAndAddChar...OK
+DirectByteBufferViewBEGetAndAddInt...OK
+DirectByteBufferViewBEGetAndAddLong...OK
+DirectByteBufferViewBEGetAndAddFloat...OK
+DirectByteBufferViewBEGetAndAddDouble...OK
+DirectByteBufferViewBEGetAndAddAcquireShort...OK
+DirectByteBufferViewBEGetAndAddAcquireChar...OK
+DirectByteBufferViewBEGetAndAddAcquireInt...OK
+DirectByteBufferViewBEGetAndAddAcquireLong...OK
+DirectByteBufferViewBEGetAndAddAcquireFloat...OK
+DirectByteBufferViewBEGetAndAddAcquireDouble...OK
+DirectByteBufferViewBEGetAndAddReleaseShort...OK
+DirectByteBufferViewBEGetAndAddReleaseChar...OK
+DirectByteBufferViewBEGetAndAddReleaseInt...OK
+DirectByteBufferViewBEGetAndAddReleaseLong...OK
+DirectByteBufferViewBEGetAndAddReleaseFloat...OK
+DirectByteBufferViewBEGetAndAddReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferViewLEGetShort...OK
+HeapByteBufferViewLEGetChar...OK
+HeapByteBufferViewLEGetInt...OK
+HeapByteBufferViewLEGetLong...OK
+HeapByteBufferViewLEGetFloat...OK
+HeapByteBufferViewLEGetDouble...OK
+HeapByteBufferViewLESetShort...OK
+HeapByteBufferViewLESetChar...OK
+HeapByteBufferViewLESetInt...OK
+HeapByteBufferViewLESetLong...OK
+HeapByteBufferViewLESetFloat...OK
+HeapByteBufferViewLESetDouble...OK
+HeapByteBufferViewLEGetVolatileShort...OK
+HeapByteBufferViewLEGetVolatileChar...OK
+HeapByteBufferViewLEGetVolatileInt...OK
+HeapByteBufferViewLEGetVolatileLong...OK
+HeapByteBufferViewLEGetVolatileFloat...OK
+HeapByteBufferViewLEGetVolatileDouble...OK
+HeapByteBufferViewLESetVolatileShort...OK
+HeapByteBufferViewLESetVolatileChar...OK
+HeapByteBufferViewLESetVolatileInt...OK
+HeapByteBufferViewLESetVolatileLong...OK
+HeapByteBufferViewLESetVolatileFloat...OK
+HeapByteBufferViewLESetVolatileDouble...OK
+HeapByteBufferViewLEGetAcquireShort...OK
+HeapByteBufferViewLEGetAcquireChar...OK
+HeapByteBufferViewLEGetAcquireInt...OK
+HeapByteBufferViewLEGetAcquireLong...OK
+HeapByteBufferViewLEGetAcquireFloat...OK
+HeapByteBufferViewLEGetAcquireDouble...OK
+HeapByteBufferViewLESetReleaseShort...OK
+HeapByteBufferViewLESetReleaseChar...OK
+HeapByteBufferViewLESetReleaseInt...OK
+HeapByteBufferViewLESetReleaseLong...OK
+HeapByteBufferViewLESetReleaseFloat...OK
+HeapByteBufferViewLESetReleaseDouble...OK
+HeapByteBufferViewLEGetOpaqueShort...OK
+HeapByteBufferViewLEGetOpaqueChar...OK
+HeapByteBufferViewLEGetOpaqueInt...OK
+HeapByteBufferViewLEGetOpaqueLong...OK
+HeapByteBufferViewLEGetOpaqueFloat...OK
+HeapByteBufferViewLEGetOpaqueDouble...OK
+HeapByteBufferViewLESetOpaqueShort...OK
+HeapByteBufferViewLESetOpaqueChar...OK
+HeapByteBufferViewLESetOpaqueInt...OK
+HeapByteBufferViewLESetOpaqueLong...OK
+HeapByteBufferViewLESetOpaqueFloat...OK
+HeapByteBufferViewLESetOpaqueDouble...OK
+HeapByteBufferViewLECompareAndSetShort...OK
+HeapByteBufferViewLECompareAndSetChar...OK
+HeapByteBufferViewLECompareAndSetInt...OK
+HeapByteBufferViewLECompareAndSetLong...OK
+HeapByteBufferViewLECompareAndSetFloat...OK
+HeapByteBufferViewLECompareAndSetDouble...OK
+HeapByteBufferViewLECompareAndExchangeShort...OK
+HeapByteBufferViewLECompareAndExchangeChar...OK
+HeapByteBufferViewLECompareAndExchangeInt...OK
+HeapByteBufferViewLECompareAndExchangeLong...OK
+HeapByteBufferViewLECompareAndExchangeFloat...OK
+HeapByteBufferViewLECompareAndExchangeDouble...OK
+HeapByteBufferViewLECompareAndExchangeAcquireShort...OK
+HeapByteBufferViewLECompareAndExchangeAcquireChar...OK
+HeapByteBufferViewLECompareAndExchangeAcquireInt...OK
+HeapByteBufferViewLECompareAndExchangeAcquireLong...OK
+HeapByteBufferViewLECompareAndExchangeAcquireFloat...OK
+HeapByteBufferViewLECompareAndExchangeAcquireDouble...OK
+HeapByteBufferViewLECompareAndExchangeReleaseShort...OK
+HeapByteBufferViewLECompareAndExchangeReleaseChar...OK
+HeapByteBufferViewLECompareAndExchangeReleaseInt...OK
+HeapByteBufferViewLECompareAndExchangeReleaseLong...OK
+HeapByteBufferViewLECompareAndExchangeReleaseFloat...OK
+HeapByteBufferViewLECompareAndExchangeReleaseDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainShort...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainChar...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainInt...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainLong...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetShort...OK
+HeapByteBufferViewLEWeakCompareAndSetChar...OK
+HeapByteBufferViewLEWeakCompareAndSetInt...OK
+HeapByteBufferViewLEWeakCompareAndSetLong...OK
+HeapByteBufferViewLEWeakCompareAndSetFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferViewLEGetAndSetShort...OK
+HeapByteBufferViewLEGetAndSetChar...OK
+HeapByteBufferViewLEGetAndSetInt...OK
+HeapByteBufferViewLEGetAndSetLong...OK
+HeapByteBufferViewLEGetAndSetFloat...OK
+HeapByteBufferViewLEGetAndSetDouble...OK
+HeapByteBufferViewLEGetAndSetAcquireShort...OK
+HeapByteBufferViewLEGetAndSetAcquireChar...OK
+HeapByteBufferViewLEGetAndSetAcquireInt...OK
+HeapByteBufferViewLEGetAndSetAcquireLong...OK
+HeapByteBufferViewLEGetAndSetAcquireFloat...OK
+HeapByteBufferViewLEGetAndSetAcquireDouble...OK
+HeapByteBufferViewLEGetAndSetReleaseShort...OK
+HeapByteBufferViewLEGetAndSetReleaseChar...OK
+HeapByteBufferViewLEGetAndSetReleaseInt...OK
+HeapByteBufferViewLEGetAndSetReleaseLong...OK
+HeapByteBufferViewLEGetAndSetReleaseFloat...OK
+HeapByteBufferViewLEGetAndSetReleaseDouble...OK
+HeapByteBufferViewLEGetAndAddShort...OK
+HeapByteBufferViewLEGetAndAddChar...OK
+HeapByteBufferViewLEGetAndAddInt...OK
+HeapByteBufferViewLEGetAndAddLong...OK
+HeapByteBufferViewLEGetAndAddFloat...OK
+HeapByteBufferViewLEGetAndAddDouble...OK
+HeapByteBufferViewLEGetAndAddAcquireShort...OK
+HeapByteBufferViewLEGetAndAddAcquireChar...OK
+HeapByteBufferViewLEGetAndAddAcquireInt...OK
+HeapByteBufferViewLEGetAndAddAcquireLong...OK
+HeapByteBufferViewLEGetAndAddAcquireFloat...OK
+HeapByteBufferViewLEGetAndAddAcquireDouble...OK
+HeapByteBufferViewLEGetAndAddReleaseShort...OK
+HeapByteBufferViewLEGetAndAddReleaseChar...OK
+HeapByteBufferViewLEGetAndAddReleaseInt...OK
+HeapByteBufferViewLEGetAndAddReleaseLong...OK
+HeapByteBufferViewLEGetAndAddReleaseFloat...OK
+HeapByteBufferViewLEGetAndAddReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferViewBEGetShort...OK
+HeapByteBufferViewBEGetChar...OK
+HeapByteBufferViewBEGetInt...OK
+HeapByteBufferViewBEGetLong...OK
+HeapByteBufferViewBEGetFloat...OK
+HeapByteBufferViewBEGetDouble...OK
+HeapByteBufferViewBESetShort...OK
+HeapByteBufferViewBESetChar...OK
+HeapByteBufferViewBESetInt...OK
+HeapByteBufferViewBESetLong...OK
+HeapByteBufferViewBESetFloat...OK
+HeapByteBufferViewBESetDouble...OK
+HeapByteBufferViewBEGetVolatileShort...OK
+HeapByteBufferViewBEGetVolatileChar...OK
+HeapByteBufferViewBEGetVolatileInt...OK
+HeapByteBufferViewBEGetVolatileLong...OK
+HeapByteBufferViewBEGetVolatileFloat...OK
+HeapByteBufferViewBEGetVolatileDouble...OK
+HeapByteBufferViewBESetVolatileShort...OK
+HeapByteBufferViewBESetVolatileChar...OK
+HeapByteBufferViewBESetVolatileInt...OK
+HeapByteBufferViewBESetVolatileLong...OK
+HeapByteBufferViewBESetVolatileFloat...OK
+HeapByteBufferViewBESetVolatileDouble...OK
+HeapByteBufferViewBEGetAcquireShort...OK
+HeapByteBufferViewBEGetAcquireChar...OK
+HeapByteBufferViewBEGetAcquireInt...OK
+HeapByteBufferViewBEGetAcquireLong...OK
+HeapByteBufferViewBEGetAcquireFloat...OK
+HeapByteBufferViewBEGetAcquireDouble...OK
+HeapByteBufferViewBESetReleaseShort...OK
+HeapByteBufferViewBESetReleaseChar...OK
+HeapByteBufferViewBESetReleaseInt...OK
+HeapByteBufferViewBESetReleaseLong...OK
+HeapByteBufferViewBESetReleaseFloat...OK
+HeapByteBufferViewBESetReleaseDouble...OK
+HeapByteBufferViewBEGetOpaqueShort...OK
+HeapByteBufferViewBEGetOpaqueChar...OK
+HeapByteBufferViewBEGetOpaqueInt...OK
+HeapByteBufferViewBEGetOpaqueLong...OK
+HeapByteBufferViewBEGetOpaqueFloat...OK
+HeapByteBufferViewBEGetOpaqueDouble...OK
+HeapByteBufferViewBESetOpaqueShort...OK
+HeapByteBufferViewBESetOpaqueChar...OK
+HeapByteBufferViewBESetOpaqueInt...OK
+HeapByteBufferViewBESetOpaqueLong...OK
+HeapByteBufferViewBESetOpaqueFloat...OK
+HeapByteBufferViewBESetOpaqueDouble...OK
+HeapByteBufferViewBECompareAndSetShort...OK
+HeapByteBufferViewBECompareAndSetChar...OK
+HeapByteBufferViewBECompareAndSetInt...OK
+HeapByteBufferViewBECompareAndSetLong...OK
+HeapByteBufferViewBECompareAndSetFloat...OK
+HeapByteBufferViewBECompareAndSetDouble...OK
+HeapByteBufferViewBECompareAndExchangeShort...OK
+HeapByteBufferViewBECompareAndExchangeChar...OK
+HeapByteBufferViewBECompareAndExchangeInt...OK
+HeapByteBufferViewBECompareAndExchangeLong...OK
+HeapByteBufferViewBECompareAndExchangeFloat...OK
+HeapByteBufferViewBECompareAndExchangeDouble...OK
+HeapByteBufferViewBECompareAndExchangeAcquireShort...OK
+HeapByteBufferViewBECompareAndExchangeAcquireChar...OK
+HeapByteBufferViewBECompareAndExchangeAcquireInt...OK
+HeapByteBufferViewBECompareAndExchangeAcquireLong...OK
+HeapByteBufferViewBECompareAndExchangeAcquireFloat...OK
+HeapByteBufferViewBECompareAndExchangeAcquireDouble...OK
+HeapByteBufferViewBECompareAndExchangeReleaseShort...OK
+HeapByteBufferViewBECompareAndExchangeReleaseChar...OK
+HeapByteBufferViewBECompareAndExchangeReleaseInt...OK
+HeapByteBufferViewBECompareAndExchangeReleaseLong...OK
+HeapByteBufferViewBECompareAndExchangeReleaseFloat...OK
+HeapByteBufferViewBECompareAndExchangeReleaseDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainShort...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainChar...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainInt...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainLong...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetShort...OK
+HeapByteBufferViewBEWeakCompareAndSetChar...OK
+HeapByteBufferViewBEWeakCompareAndSetInt...OK
+HeapByteBufferViewBEWeakCompareAndSetLong...OK
+HeapByteBufferViewBEWeakCompareAndSetFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferViewBEGetAndSetShort...OK
+HeapByteBufferViewBEGetAndSetChar...OK
+HeapByteBufferViewBEGetAndSetInt...OK
+HeapByteBufferViewBEGetAndSetLong...OK
+HeapByteBufferViewBEGetAndSetFloat...OK
+HeapByteBufferViewBEGetAndSetDouble...OK
+HeapByteBufferViewBEGetAndSetAcquireShort...OK
+HeapByteBufferViewBEGetAndSetAcquireChar...OK
+HeapByteBufferViewBEGetAndSetAcquireInt...OK
+HeapByteBufferViewBEGetAndSetAcquireLong...OK
+HeapByteBufferViewBEGetAndSetAcquireFloat...OK
+HeapByteBufferViewBEGetAndSetAcquireDouble...OK
+HeapByteBufferViewBEGetAndSetReleaseShort...OK
+HeapByteBufferViewBEGetAndSetReleaseChar...OK
+HeapByteBufferViewBEGetAndSetReleaseInt...OK
+HeapByteBufferViewBEGetAndSetReleaseLong...OK
+HeapByteBufferViewBEGetAndSetReleaseFloat...OK
+HeapByteBufferViewBEGetAndSetReleaseDouble...OK
+HeapByteBufferViewBEGetAndAddShort...OK
+HeapByteBufferViewBEGetAndAddChar...OK
+HeapByteBufferViewBEGetAndAddInt...OK
+HeapByteBufferViewBEGetAndAddLong...OK
+HeapByteBufferViewBEGetAndAddFloat...OK
+HeapByteBufferViewBEGetAndAddDouble...OK
+HeapByteBufferViewBEGetAndAddAcquireShort...OK
+HeapByteBufferViewBEGetAndAddAcquireChar...OK
+HeapByteBufferViewBEGetAndAddAcquireInt...OK
+HeapByteBufferViewBEGetAndAddAcquireLong...OK
+HeapByteBufferViewBEGetAndAddAcquireFloat...OK
+HeapByteBufferViewBEGetAndAddAcquireDouble...OK
+HeapByteBufferViewBEGetAndAddReleaseShort...OK
+HeapByteBufferViewBEGetAndAddReleaseChar...OK
+HeapByteBufferViewBEGetAndAddReleaseInt...OK
+HeapByteBufferViewBEGetAndAddReleaseLong...OK
+HeapByteBufferViewBEGetAndAddReleaseFloat...OK
+HeapByteBufferViewBEGetAndAddReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetShort...OK
+HeapByteBufferReadOnlyViewLEGetChar...OK
+HeapByteBufferReadOnlyViewLEGetInt...OK
+HeapByteBufferReadOnlyViewLEGetLong...OK
+HeapByteBufferReadOnlyViewLEGetFloat...OK
+HeapByteBufferReadOnlyViewLEGetDouble...OK
+HeapByteBufferReadOnlyViewLESetShort...OK
+HeapByteBufferReadOnlyViewLESetChar...OK
+HeapByteBufferReadOnlyViewLESetInt...OK
+HeapByteBufferReadOnlyViewLESetLong...OK
+HeapByteBufferReadOnlyViewLESetFloat...OK
+HeapByteBufferReadOnlyViewLESetDouble...OK
+HeapByteBufferReadOnlyViewLEGetVolatileShort...OK
+HeapByteBufferReadOnlyViewLEGetVolatileChar...OK
+HeapByteBufferReadOnlyViewLEGetVolatileInt...OK
+HeapByteBufferReadOnlyViewLEGetVolatileLong...OK
+HeapByteBufferReadOnlyViewLEGetVolatileFloat...OK
+HeapByteBufferReadOnlyViewLEGetVolatileDouble...OK
+HeapByteBufferReadOnlyViewLESetVolatileShort...OK
+HeapByteBufferReadOnlyViewLESetVolatileChar...OK
+HeapByteBufferReadOnlyViewLESetVolatileInt...OK
+HeapByteBufferReadOnlyViewLESetVolatileLong...OK
+HeapByteBufferReadOnlyViewLESetVolatileFloat...OK
+HeapByteBufferReadOnlyViewLESetVolatileDouble...OK
+HeapByteBufferReadOnlyViewLEGetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLESetReleaseShort...OK
+HeapByteBufferReadOnlyViewLESetReleaseChar...OK
+HeapByteBufferReadOnlyViewLESetReleaseInt...OK
+HeapByteBufferReadOnlyViewLESetReleaseLong...OK
+HeapByteBufferReadOnlyViewLESetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLESetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueShort...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueChar...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueInt...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueLong...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewLESetOpaqueShort...OK
+HeapByteBufferReadOnlyViewLESetOpaqueChar...OK
+HeapByteBufferReadOnlyViewLESetOpaqueInt...OK
+HeapByteBufferReadOnlyViewLESetOpaqueLong...OK
+HeapByteBufferReadOnlyViewLESetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewLESetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndSetShort...OK
+HeapByteBufferReadOnlyViewLECompareAndSetChar...OK
+HeapByteBufferReadOnlyViewLECompareAndSetInt...OK
+HeapByteBufferReadOnlyViewLECompareAndSetLong...OK
+HeapByteBufferReadOnlyViewLECompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetShort...OK
+HeapByteBufferReadOnlyViewBEGetChar...OK
+HeapByteBufferReadOnlyViewBEGetInt...OK
+HeapByteBufferReadOnlyViewBEGetLong...OK
+HeapByteBufferReadOnlyViewBEGetFloat...OK
+HeapByteBufferReadOnlyViewBEGetDouble...OK
+HeapByteBufferReadOnlyViewBESetShort...OK
+HeapByteBufferReadOnlyViewBESetChar...OK
+HeapByteBufferReadOnlyViewBESetInt...OK
+HeapByteBufferReadOnlyViewBESetLong...OK
+HeapByteBufferReadOnlyViewBESetFloat...OK
+HeapByteBufferReadOnlyViewBESetDouble...OK
+HeapByteBufferReadOnlyViewBEGetVolatileShort...OK
+HeapByteBufferReadOnlyViewBEGetVolatileChar...OK
+HeapByteBufferReadOnlyViewBEGetVolatileInt...OK
+HeapByteBufferReadOnlyViewBEGetVolatileLong...OK
+HeapByteBufferReadOnlyViewBEGetVolatileFloat...OK
+HeapByteBufferReadOnlyViewBEGetVolatileDouble...OK
+HeapByteBufferReadOnlyViewBESetVolatileShort...OK
+HeapByteBufferReadOnlyViewBESetVolatileChar...OK
+HeapByteBufferReadOnlyViewBESetVolatileInt...OK
+HeapByteBufferReadOnlyViewBESetVolatileLong...OK
+HeapByteBufferReadOnlyViewBESetVolatileFloat...OK
+HeapByteBufferReadOnlyViewBESetVolatileDouble...OK
+HeapByteBufferReadOnlyViewBEGetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBESetReleaseShort...OK
+HeapByteBufferReadOnlyViewBESetReleaseChar...OK
+HeapByteBufferReadOnlyViewBESetReleaseInt...OK
+HeapByteBufferReadOnlyViewBESetReleaseLong...OK
+HeapByteBufferReadOnlyViewBESetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBESetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueShort...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueChar...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueInt...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueLong...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewBESetOpaqueShort...OK
+HeapByteBufferReadOnlyViewBESetOpaqueChar...OK
+HeapByteBufferReadOnlyViewBESetOpaqueInt...OK
+HeapByteBufferReadOnlyViewBESetOpaqueLong...OK
+HeapByteBufferReadOnlyViewBESetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewBESetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndSetShort...OK
+HeapByteBufferReadOnlyViewBECompareAndSetChar...OK
+HeapByteBufferReadOnlyViewBECompareAndSetInt...OK
+HeapByteBufferReadOnlyViewBECompareAndSetLong...OK
+HeapByteBufferReadOnlyViewBECompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireDouble...OK
+FieldGetWidget...OK
+FieldSetWidget...OK
+FieldGetVolatileWidget...OK
+FieldSetVolatileWidget...OK
+FieldGetAcquireWidget...OK
+FieldSetReleaseWidget...OK
+FieldGetOpaqueWidget...OK
+FieldSetOpaqueWidget...OK
+FieldCompareAndSetWidget...OK
+FieldCompareAndExchangeWidget...OK
+FieldCompareAndExchangeAcquireWidget...OK
+FieldCompareAndExchangeReleaseWidget...OK
+FieldWeakCompareAndSetPlainWidget...OK
+FieldWeakCompareAndSetWidget...OK
+FieldWeakCompareAndSetAcquireWidget...OK
+FieldWeakCompareAndSetReleaseWidget...OK
+FieldGetAndSetWidget...OK
+FieldGetAndSetAcquireWidget...OK
+FieldGetAndSetReleaseWidget...OK
+FieldGetAndAddWidget...OK
+FieldGetAndAddAcquireWidget...OK
+FieldGetAndAddReleaseWidget...OK
+FieldGetAndBitwiseOrWidget...OK
+FieldGetAndBitwiseOrReleaseWidget...OK
+FieldGetAndBitwiseOrAcquireWidget...OK
+FieldGetAndBitwiseAndWidget...OK
+FieldGetAndBitwiseAndReleaseWidget...OK
+FieldGetAndBitwiseAndAcquireWidget...OK
+FieldGetAndBitwiseXorWidget...OK
+FieldGetAndBitwiseXorReleaseWidget...OK
+FieldGetAndBitwiseXorAcquireWidget...OK
+FinalFieldGetWidget...OK
+FinalFieldSetWidget...OK
+FinalFieldGetVolatileWidget...OK
+FinalFieldSetVolatileWidget...OK
+FinalFieldGetAcquireWidget...OK
+FinalFieldSetReleaseWidget...OK
+FinalFieldGetOpaqueWidget...OK
+FinalFieldSetOpaqueWidget...OK
+FinalFieldCompareAndSetWidget...OK
+FinalFieldCompareAndExchangeWidget...OK
+FinalFieldCompareAndExchangeAcquireWidget...OK
+FinalFieldCompareAndExchangeReleaseWidget...OK
+FinalFieldWeakCompareAndSetPlainWidget...OK
+FinalFieldWeakCompareAndSetWidget...OK
+FinalFieldWeakCompareAndSetAcquireWidget...OK
+FinalFieldWeakCompareAndSetReleaseWidget...OK
+FinalFieldGetAndSetWidget...OK
+FinalFieldGetAndSetAcquireWidget...OK
+FinalFieldGetAndSetReleaseWidget...OK
+FinalFieldGetAndAddWidget...OK
+FinalFieldGetAndAddAcquireWidget...OK
+FinalFieldGetAndAddReleaseWidget...OK
+FinalFieldGetAndBitwiseOrWidget...OK
+FinalFieldGetAndBitwiseOrReleaseWidget...OK
+FinalFieldGetAndBitwiseOrAcquireWidget...OK
+FinalFieldGetAndBitwiseAndWidget...OK
+FinalFieldGetAndBitwiseAndReleaseWidget...OK
+FinalFieldGetAndBitwiseAndAcquireWidget...OK
+FinalFieldGetAndBitwiseXorWidget...OK
+FinalFieldGetAndBitwiseXorReleaseWidget...OK
+FinalFieldGetAndBitwiseXorAcquireWidget...OK
+StaticFieldGetWidget...OK
+StaticFieldSetWidget...OK
+StaticFieldGetVolatileWidget...OK
+StaticFieldSetVolatileWidget...OK
+StaticFieldGetAcquireWidget...OK
+StaticFieldSetReleaseWidget...OK
+StaticFieldGetOpaqueWidget...OK
+StaticFieldSetOpaqueWidget...OK
+StaticFieldCompareAndSetWidget...OK
+StaticFieldCompareAndExchangeWidget...OK
+StaticFieldCompareAndExchangeAcquireWidget...OK
+StaticFieldCompareAndExchangeReleaseWidget...OK
+StaticFieldWeakCompareAndSetPlainWidget...OK
+StaticFieldWeakCompareAndSetWidget...OK
+StaticFieldWeakCompareAndSetAcquireWidget...OK
+StaticFieldWeakCompareAndSetReleaseWidget...OK
+StaticFieldGetAndSetWidget...OK
+StaticFieldGetAndSetAcquireWidget...OK
+StaticFieldGetAndSetReleaseWidget...OK
+StaticFieldGetAndAddWidget...OK
+StaticFieldGetAndAddAcquireWidget...OK
+StaticFieldGetAndAddReleaseWidget...OK
+StaticFieldGetAndBitwiseOrWidget...OK
+StaticFieldGetAndBitwiseOrReleaseWidget...OK
+StaticFieldGetAndBitwiseOrAcquireWidget...OK
+StaticFieldGetAndBitwiseAndWidget...OK
+StaticFieldGetAndBitwiseAndReleaseWidget...OK
+StaticFieldGetAndBitwiseAndAcquireWidget...OK
+StaticFieldGetAndBitwiseXorWidget...OK
+StaticFieldGetAndBitwiseXorReleaseWidget...OK
+StaticFieldGetAndBitwiseXorAcquireWidget...OK
+StaticFinalFieldGetWidget...OK
+StaticFinalFieldSetWidget...OK
+StaticFinalFieldGetVolatileWidget...OK
+StaticFinalFieldSetVolatileWidget...OK
+StaticFinalFieldGetAcquireWidget...OK
+StaticFinalFieldSetReleaseWidget...OK
+StaticFinalFieldGetOpaqueWidget...OK
+StaticFinalFieldSetOpaqueWidget...OK
+StaticFinalFieldCompareAndSetWidget...OK
+StaticFinalFieldCompareAndExchangeWidget...OK
+StaticFinalFieldCompareAndExchangeAcquireWidget...OK
+StaticFinalFieldCompareAndExchangeReleaseWidget...OK
+StaticFinalFieldWeakCompareAndSetPlainWidget...OK
+StaticFinalFieldWeakCompareAndSetWidget...OK
+StaticFinalFieldWeakCompareAndSetAcquireWidget...OK
+StaticFinalFieldWeakCompareAndSetReleaseWidget...OK
+StaticFinalFieldGetAndSetWidget...OK
+StaticFinalFieldGetAndSetAcquireWidget...OK
+StaticFinalFieldGetAndSetReleaseWidget...OK
+StaticFinalFieldGetAndAddWidget...OK
+StaticFinalFieldGetAndAddAcquireWidget...OK
+StaticFinalFieldGetAndAddReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseOrWidget...OK
+StaticFinalFieldGetAndBitwiseOrReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseOrAcquireWidget...OK
+StaticFinalFieldGetAndBitwiseAndWidget...OK
+StaticFinalFieldGetAndBitwiseAndReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseAndAcquireWidget...OK
+StaticFinalFieldGetAndBitwiseXorWidget...OK
+StaticFinalFieldGetAndBitwiseXorReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseXorAcquireWidget...OK
+ArrayElementGetWidget...OK
+ArrayElementSetWidget...OK
+ArrayElementGetVolatileWidget...OK
+ArrayElementSetVolatileWidget...OK
+ArrayElementGetAcquireWidget...OK
+ArrayElementSetReleaseWidget...OK
+ArrayElementGetOpaqueWidget...OK
+ArrayElementSetOpaqueWidget...OK
+ArrayElementCompareAndSetWidget...OK
+ArrayElementCompareAndExchangeWidget...OK
+ArrayElementCompareAndExchangeAcquireWidget...OK
+ArrayElementCompareAndExchangeReleaseWidget...OK
+ArrayElementWeakCompareAndSetPlainWidget...OK
+ArrayElementWeakCompareAndSetWidget...OK
+ArrayElementWeakCompareAndSetAcquireWidget...OK
+ArrayElementWeakCompareAndSetReleaseWidget...OK
+ArrayElementGetAndSetWidget...OK
+ArrayElementGetAndSetAcquireWidget...OK
+ArrayElementGetAndSetReleaseWidget...OK
+ArrayElementGetAndAddWidget...OK
+ArrayElementGetAndAddAcquireWidget...OK
+ArrayElementGetAndAddReleaseWidget...OK
+ArrayElementGetAndBitwiseOrWidget...OK
+ArrayElementGetAndBitwiseOrReleaseWidget...OK
+ArrayElementGetAndBitwiseOrAcquireWidget...OK
+ArrayElementGetAndBitwiseAndWidget...OK
+ArrayElementGetAndBitwiseAndReleaseWidget...OK
+ArrayElementGetAndBitwiseAndAcquireWidget...OK
+ArrayElementGetAndBitwiseXorWidget...OK
+ArrayElementGetAndBitwiseXorReleaseWidget...OK
+ArrayElementGetAndBitwiseXorAcquireWidget...OK
+BoxingReturnGetBoolean...OK
+BoxingSetBoolean...OK
+BoxingReturnGetVolatileBoolean...OK
+BoxingSetVolatileBoolean...OK
+BoxingReturnGetAcquireBoolean...OK
+BoxingSetReleaseBoolean...OK
+BoxingReturnGetOpaqueBoolean...OK
+BoxingSetOpaqueBoolean...OK
+BoxingCompareAndSetBoolean...OK
+BoxingCompareAndExchangeBoolean...OK
+BoxingCompareAndExchangeAcquireBoolean...OK
+BoxingCompareAndExchangeReleaseBoolean...OK
+BoxingWeakCompareAndSetPlainBoolean...OK
+BoxingWeakCompareAndSetBoolean...OK
+BoxingWeakCompareAndSetAcquireBoolean...OK
+BoxingWeakCompareAndSetReleaseBoolean...OK
+BoxingGetAndSetBoolean...OK
+BoxingGetAndSetAcquireBoolean...OK
+BoxingGetAndSetReleaseBoolean...OK
+BoxingGetAndAddBoolean...OK
+BoxingGetAndAddAcquireBoolean...OK
+BoxingGetAndAddReleaseBoolean...OK
+BoxingGetAndBitwiseOrBoolean...OK
+BoxingGetAndBitwiseOrReleaseBoolean...OK
+BoxingGetAndBitwiseOrAcquireBoolean...OK
+BoxingGetAndBitwiseAndBoolean...OK
+BoxingGetAndBitwiseAndReleaseBoolean...OK
+BoxingGetAndBitwiseAndAcquireBoolean...OK
+BoxingGetAndBitwiseXorBoolean...OK
+BoxingGetAndBitwiseXorReleaseBoolean...OK
+BoxingGetAndBitwiseXorAcquireBoolean...OK
+BoxingReturnGetByte...OK
+BoxingSetByte...OK
+BoxingReturnGetVolatileByte...OK
+BoxingSetVolatileByte...OK
+BoxingReturnGetAcquireByte...OK
+BoxingSetReleaseByte...OK
+BoxingReturnGetOpaqueByte...OK
+BoxingSetOpaqueByte...OK
+BoxingCompareAndSetByte...OK
+BoxingCompareAndExchangeByte...OK
+BoxingCompareAndExchangeAcquireByte...OK
+BoxingCompareAndExchangeReleaseByte...OK
+BoxingWeakCompareAndSetPlainByte...OK
+BoxingWeakCompareAndSetByte...OK
+BoxingWeakCompareAndSetAcquireByte...OK
+BoxingWeakCompareAndSetReleaseByte...OK
+BoxingGetAndSetByte...OK
+BoxingGetAndSetAcquireByte...OK
+BoxingGetAndSetReleaseByte...OK
+BoxingGetAndAddByte...OK
+BoxingGetAndAddAcquireByte...OK
+BoxingGetAndAddReleaseByte...OK
+BoxingGetAndBitwiseOrByte...OK
+BoxingGetAndBitwiseOrReleaseByte...OK
+BoxingGetAndBitwiseOrAcquireByte...OK
+BoxingGetAndBitwiseAndByte...OK
+BoxingGetAndBitwiseAndReleaseByte...OK
+BoxingGetAndBitwiseAndAcquireByte...OK
+BoxingGetAndBitwiseXorByte...OK
+BoxingGetAndBitwiseXorReleaseByte...OK
+BoxingGetAndBitwiseXorAcquireByte...OK
+BoxingReturnGetShort...OK
+BoxingSetShort...OK
+BoxingReturnGetVolatileShort...OK
+BoxingSetVolatileShort...OK
+BoxingReturnGetAcquireShort...OK
+BoxingSetReleaseShort...OK
+BoxingReturnGetOpaqueShort...OK
+BoxingSetOpaqueShort...OK
+BoxingCompareAndSetShort...OK
+BoxingCompareAndExchangeShort...OK
+BoxingCompareAndExchangeAcquireShort...OK
+BoxingCompareAndExchangeReleaseShort...OK
+BoxingWeakCompareAndSetPlainShort...OK
+BoxingWeakCompareAndSetShort...OK
+BoxingWeakCompareAndSetAcquireShort...OK
+BoxingWeakCompareAndSetReleaseShort...OK
+BoxingGetAndSetShort...OK
+BoxingGetAndSetAcquireShort...OK
+BoxingGetAndSetReleaseShort...OK
+BoxingGetAndAddShort...OK
+BoxingGetAndAddAcquireShort...OK
+BoxingGetAndAddReleaseShort...OK
+BoxingGetAndBitwiseOrShort...OK
+BoxingGetAndBitwiseOrReleaseShort...OK
+BoxingGetAndBitwiseOrAcquireShort...OK
+BoxingGetAndBitwiseAndShort...OK
+BoxingGetAndBitwiseAndReleaseShort...OK
+BoxingGetAndBitwiseAndAcquireShort...OK
+BoxingGetAndBitwiseXorShort...OK
+BoxingGetAndBitwiseXorReleaseShort...OK
+BoxingGetAndBitwiseXorAcquireShort...OK
+BoxingReturnGetChar...OK
+BoxingSetChar...OK
+BoxingReturnGetVolatileChar...OK
+BoxingSetVolatileChar...OK
+BoxingReturnGetAcquireChar...OK
+BoxingSetReleaseChar...OK
+BoxingReturnGetOpaqueChar...OK
+BoxingSetOpaqueChar...OK
+BoxingCompareAndSetChar...OK
+BoxingCompareAndExchangeChar...OK
+BoxingCompareAndExchangeAcquireChar...OK
+BoxingCompareAndExchangeReleaseChar...OK
+BoxingWeakCompareAndSetPlainChar...OK
+BoxingWeakCompareAndSetChar...OK
+BoxingWeakCompareAndSetAcquireChar...OK
+BoxingWeakCompareAndSetReleaseChar...OK
+BoxingGetAndSetChar...OK
+BoxingGetAndSetAcquireChar...OK
+BoxingGetAndSetReleaseChar...OK
+BoxingGetAndAddChar...OK
+BoxingGetAndAddAcquireChar...OK
+BoxingGetAndAddReleaseChar...OK
+BoxingGetAndBitwiseOrChar...OK
+BoxingGetAndBitwiseOrReleaseChar...OK
+BoxingGetAndBitwiseOrAcquireChar...OK
+BoxingGetAndBitwiseAndChar...OK
+BoxingGetAndBitwiseAndReleaseChar...OK
+BoxingGetAndBitwiseAndAcquireChar...OK
+BoxingGetAndBitwiseXorChar...OK
+BoxingGetAndBitwiseXorReleaseChar...OK
+BoxingGetAndBitwiseXorAcquireChar...OK
+BoxingReturnGetInt...OK
+BoxingSetInt...OK
+BoxingReturnGetVolatileInt...OK
+BoxingSetVolatileInt...OK
+BoxingReturnGetAcquireInt...OK
+BoxingSetReleaseInt...OK
+BoxingReturnGetOpaqueInt...OK
+BoxingSetOpaqueInt...OK
+BoxingCompareAndSetInt...OK
+BoxingCompareAndExchangeInt...OK
+BoxingCompareAndExchangeAcquireInt...OK
+BoxingCompareAndExchangeReleaseInt...OK
+BoxingWeakCompareAndSetPlainInt...OK
+BoxingWeakCompareAndSetInt...OK
+BoxingWeakCompareAndSetAcquireInt...OK
+BoxingWeakCompareAndSetReleaseInt...OK
+BoxingGetAndSetInt...OK
+BoxingGetAndSetAcquireInt...OK
+BoxingGetAndSetReleaseInt...OK
+BoxingGetAndAddInt...OK
+BoxingGetAndAddAcquireInt...OK
+BoxingGetAndAddReleaseInt...OK
+BoxingGetAndBitwiseOrInt...OK
+BoxingGetAndBitwiseOrReleaseInt...OK
+BoxingGetAndBitwiseOrAcquireInt...OK
+BoxingGetAndBitwiseAndInt...OK
+BoxingGetAndBitwiseAndReleaseInt...OK
+BoxingGetAndBitwiseAndAcquireInt...OK
+BoxingGetAndBitwiseXorInt...OK
+BoxingGetAndBitwiseXorReleaseInt...OK
+BoxingGetAndBitwiseXorAcquireInt...OK
+BoxingReturnGetLong...OK
+BoxingSetLong...OK
+BoxingReturnGetVolatileLong...OK
+BoxingSetVolatileLong...OK
+BoxingReturnGetAcquireLong...OK
+BoxingSetReleaseLong...OK
+BoxingReturnGetOpaqueLong...OK
+BoxingSetOpaqueLong...OK
+BoxingCompareAndSetLong...OK
+BoxingCompareAndExchangeLong...OK
+BoxingCompareAndExchangeAcquireLong...OK
+BoxingCompareAndExchangeReleaseLong...OK
+BoxingWeakCompareAndSetPlainLong...OK
+BoxingWeakCompareAndSetLong...OK
+BoxingWeakCompareAndSetAcquireLong...OK
+BoxingWeakCompareAndSetReleaseLong...OK
+BoxingGetAndSetLong...OK
+BoxingGetAndSetAcquireLong...OK
+BoxingGetAndSetReleaseLong...OK
+BoxingGetAndAddLong...OK
+BoxingGetAndAddAcquireLong...OK
+BoxingGetAndAddReleaseLong...OK
+BoxingGetAndBitwiseOrLong...OK
+BoxingGetAndBitwiseOrReleaseLong...OK
+BoxingGetAndBitwiseOrAcquireLong...OK
+BoxingGetAndBitwiseAndLong...OK
+BoxingGetAndBitwiseAndReleaseLong...OK
+BoxingGetAndBitwiseAndAcquireLong...OK
+BoxingGetAndBitwiseXorLong...OK
+BoxingGetAndBitwiseXorReleaseLong...OK
+BoxingGetAndBitwiseXorAcquireLong...OK
+BoxingReturnGetFloat...OK
+BoxingSetFloat...OK
+BoxingReturnGetVolatileFloat...OK
+BoxingSetVolatileFloat...OK
+BoxingReturnGetAcquireFloat...OK
+BoxingSetReleaseFloat...OK
+BoxingReturnGetOpaqueFloat...OK
+BoxingSetOpaqueFloat...OK
+BoxingCompareAndSetFloat...OK
+BoxingCompareAndExchangeFloat...OK
+BoxingCompareAndExchangeAcquireFloat...OK
+BoxingCompareAndExchangeReleaseFloat...OK
+BoxingWeakCompareAndSetPlainFloat...OK
+BoxingWeakCompareAndSetFloat...OK
+BoxingWeakCompareAndSetAcquireFloat...OK
+BoxingWeakCompareAndSetReleaseFloat...OK
+BoxingGetAndSetFloat...OK
+BoxingGetAndSetAcquireFloat...OK
+BoxingGetAndSetReleaseFloat...OK
+BoxingGetAndAddFloat...OK
+BoxingGetAndAddAcquireFloat...OK
+BoxingGetAndAddReleaseFloat...OK
+BoxingGetAndBitwiseOrFloat...OK
+BoxingGetAndBitwiseOrReleaseFloat...OK
+BoxingGetAndBitwiseOrAcquireFloat...OK
+BoxingGetAndBitwiseAndFloat...OK
+BoxingGetAndBitwiseAndReleaseFloat...OK
+BoxingGetAndBitwiseAndAcquireFloat...OK
+BoxingGetAndBitwiseXorFloat...OK
+BoxingGetAndBitwiseXorReleaseFloat...OK
+BoxingGetAndBitwiseXorAcquireFloat...OK
+BoxingReturnGetDouble...OK
+BoxingSetDouble...OK
+BoxingReturnGetVolatileDouble...OK
+BoxingSetVolatileDouble...OK
+BoxingReturnGetAcquireDouble...OK
+BoxingSetReleaseDouble...OK
+BoxingReturnGetOpaqueDouble...OK
+BoxingSetOpaqueDouble...OK
+BoxingCompareAndSetDouble...OK
+BoxingCompareAndExchangeDouble...OK
+BoxingCompareAndExchangeAcquireDouble...OK
+BoxingCompareAndExchangeReleaseDouble...OK
+BoxingWeakCompareAndSetPlainDouble...OK
+BoxingWeakCompareAndSetDouble...OK
+BoxingWeakCompareAndSetAcquireDouble...OK
+BoxingWeakCompareAndSetReleaseDouble...OK
+BoxingGetAndSetDouble...OK
+BoxingGetAndSetAcquireDouble...OK
+BoxingGetAndSetReleaseDouble...OK
+BoxingGetAndAddDouble...OK
+BoxingGetAndAddAcquireDouble...OK
+BoxingGetAndAddReleaseDouble...OK
+BoxingGetAndBitwiseOrDouble...OK
+BoxingGetAndBitwiseOrReleaseDouble...OK
+BoxingGetAndBitwiseOrAcquireDouble...OK
+BoxingGetAndBitwiseAndDouble...OK
+BoxingGetAndBitwiseAndReleaseDouble...OK
+BoxingGetAndBitwiseAndAcquireDouble...OK
+BoxingGetAndBitwiseXorDouble...OK
+BoxingGetAndBitwiseXorReleaseDouble...OK
+BoxingGetAndBitwiseXorAcquireDouble...OK
+NullReceiverTest...OK
+UnsupportedAccessModeTest...OK
+WrongArgumentTypeCausingWrongMethodTypeTest...OK
+TooManyArgumentsCausingWrongMethodTypeTest...OK
+TooFewArgumentsCausingWrongMethodTypeTest...OK
+ReturnTypeCausingWrongMethodTypeTest...OK
+UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest...OK
+FieldCoordinateTypeTest...OK
+ArrayElementOutOfBoundsIndexTest...OK
+ArrayElementBadIndexTypeTest...OK
+ArrayElementNullArrayTest...OK
+ArrayElementWrongArrayTypeTest...OK
+ArrayElementMissingIndexTest...OK
+ByteArrayViewOutOfBoundsIndexTest...OK
+ByteArrayViewUnalignedAccessesIndexTest...OK
+ByteArrayViewBadIndexTypeTest...OK
+ByteArrayViewMissingIndexTest...OK
+ByteArrayViewBadByteArrayTest...OK
+ByteBufferViewOutOfBoundsIndexTest...OK
+ByteBufferViewUnalignedAccessesIndexTest...OK
+ByteBufferViewBadIndexTypeTest...OK
+ByteBufferViewMissingIndexTest...OK
+ByteBufferViewBadByteBufferTest...OK
+VoidReturnTypeTest...OK
+BoxedNullBooleanThrowsNPETest...OK
+BoxedNullByteThrowsNPETest...OK
+BoxedNullCharacterThrowsNPETest...OK
+BoxedNullShortThrowsNPETest...OK
+BoxedNullIntegerThrowsNPETest...OK
+BoxedNullLongThrowsNPETest...OK
+BoxedNullFloatThrowsNPETest...OK
+BoxedNullDoubleThrowsNPETest...OK
+WideningBooleanArgumentTest...OK
+WideningByteArgumentTest...OK
+WideningCharacterArgumentTest...OK
+WideningShortArgumentTest...OK
+WideningIntegerArgumentTest...OK
+WideningLongArgumentTest...OK
+WideningFloatArgumentTest...OK
+WideningDoubleArgumentTest...OK
+WideningBooleanReturnValueTest...OK
+WideningByteReturnValueTest...OK
+WideningCharacterReturnValueTest...OK
+WideningShortReturnValueTest...OK
+WideningIntegerReturnValueTest...OK
+WideningLongReturnValueTest...OK
+WideningFloatReturnValueTest...OK
+WideningDoubleReturnValueTest...OK
+SubtypeTest...OK
+SupertypeTest...OK
+ImplicitBoxingIntegerTest...OK
+3182 successes, 0 skips, 0 failures.
diff --git a/test/712-varhandle-invocations/info.txt b/test/712-varhandle-invocations/info.txt
new file mode 100644
index 0000000000..e2de024d8e
--- /dev/null
+++ b/test/712-varhandle-invocations/info.txt
@@ -0,0 +1 @@
+Generates and runs tests that invoke VarHandle accessor methods.
diff --git a/test/712-varhandle-invocations/src/SimpleTests.java b/test/712-varhandle-invocations/src/SimpleTests.java
new file mode 100644
index 0000000000..6e62bff4b4
--- /dev/null
+++ b/test/712-varhandle-invocations/src/SimpleTests.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.
+ */
+
+public class SimpleTests {
+ public static class TestGuardSkips extends VarHandleUnitTest {
+ public boolean checkGuard() {
+ return false;
+ }
+
+ @Override
+ protected void doTest() {
+ throw new IllegalStateException("Not reachable");
+ }
+
+ public static void main(String[] args) {
+ new TestGuardSkips().run();
+ }
+ }
+
+ public static class TestEqualsOK extends VarHandleUnitTest {
+ @Override
+ protected void doTest() {
+ assertEquals(true, true);
+ }
+ }
+
+ public static class TestEqualsOK2 extends VarHandleUnitTest {
+ @Override
+ protected void doTest() {
+ assertEquals(true, false);
+ }
+ }
+
+ public static class TestExceptionsFail extends VarHandleUnitTest {
+ @Override
+ protected void doTest() {
+ throw new NullPointerException();
+ }
+ }
+
+ public static void main(String[] args) {
+ new TestGuardSkips().run();
+ new TestEqualsOK().run();
+ new TestEqualsOK2().run();
+ new TestExceptionsFail().run();
+ VarHandleUnitTest.DEFAULT_COLLECTOR.printSummary();
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java b/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java
new file mode 100644
index 0000000000..4c9013b14d
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java
@@ -0,0 +1,232 @@
+/*
+ * 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.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+
+// These tests cover DoVarHandleInvokeCommon in interpreter_common.cc.
+
+public class VarHandleAccessorExceptionTests {
+ public static class NullReceiverTest extends VarHandleUnitTest {
+ private static final VarHandle vh = null;
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(3);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new NullReceiverTest().run();
+ }
+ }
+
+ public static class UnsupportedAccessModeTest extends VarHandleUnitTest {
+ private static final boolean b = true;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = UnsupportedAccessModeTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ // A final field should not support an VarHandle access modes which can update it
+ boolean isSupported =
+ vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND);
+ assertFalse(isSupported);
+ try {
+ vh.getAndBitwiseAnd(true);
+ failUnreachable();
+ } catch (UnsupportedOperationException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new UnsupportedAccessModeTest().run();
+ }
+ }
+
+ public static class WrongArgumentTypeCausingWrongMethodTypeTest extends VarHandleUnitTest {
+ private short s;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WrongArgumentTypeCausingWrongMethodTypeTest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "s", short.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(this, (short) 0xcafe);
+ try {
+ vh.setVolatile(this, System.out); // System.out is a PrintStream, not short!
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WrongArgumentTypeCausingWrongMethodTypeTest().run();
+ }
+ }
+
+ // Too many arguments causing WMTE
+ public static class TooManyArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest {
+ private int i;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = TooManyArgumentsCausingWrongMethodTypeTest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(this, 0x12345678);
+ try {
+ vh.setVolatile(this, 0x5a5a55aa, 0xc3c30f0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new TooManyArgumentsCausingWrongMethodTypeTest().run();
+ }
+ }
+
+ public static class TooFewArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest {
+ private int i;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = TooFewArgumentsCausingWrongMethodTypeTest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ i = 33;
+ vh.compareAndSet(this, 33, 44);
+ boolean updated = false;
+ try {
+ updated = (boolean) vh.compareAndSet(this, 44);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ assertFalse(updated); // Should have failed too few arguments
+ }
+
+ public static void main(String[] args) {
+ new TooFewArgumentsCausingWrongMethodTypeTest().run();
+ }
+ }
+
+ public static class ReturnTypeCausingWrongMethodTypeTest extends VarHandleUnitTest {
+ private int i;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = ReturnTypeCausingWrongMethodTypeTest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ i = 33;
+ vh.getAndSet(this, 44);
+ Runtime runtime = null;
+ try {
+ runtime = (Runtime) vh.getAndSet(this, 44);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ assertEquals(null, runtime);
+ }
+
+ public static void main(String[] args) {
+ new ReturnTypeCausingWrongMethodTypeTest().run();
+ }
+ }
+
+ public static class UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest
+ extends VarHandleUnitTest {
+ private static final boolean b = true;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ // A final field should not support an VarHandle access modes which can update it
+ boolean supported = vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND);
+ assertFalse(supported);
+ try {
+ // The following is both unsupported and a wrong method type...
+ vh.getAndBitwiseAnd(System.out);
+ failUnreachable();
+ } catch (UnsupportedOperationException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest().run();
+ }
+ }
+
+ public static void main(String[] args) {
+ NullReceiverTest.main(args);
+ UnsupportedAccessModeTest.main(args);
+ WrongArgumentTypeCausingWrongMethodTypeTest.main(args);
+ TooManyArgumentsCausingWrongMethodTypeTest.main(args);
+ TooFewArgumentsCausingWrongMethodTypeTest.main(args);
+ ReturnTypeCausingWrongMethodTypeTest.main(args);
+ UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.main(args);
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java
new file mode 100644
index 0000000000..8f81c94a89
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java
@@ -0,0 +1,948 @@
+/*
+ * 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.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class VarHandleBadCoordinateTests {
+ public static class FieldCoordinateTypeTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ public static class A {
+ public byte field;
+ }
+
+ public static class B extends A {
+ private byte other_field;
+ }
+
+ public static class C {}
+
+ static {
+ try {
+ vh = MethodHandles.lookup().findVarHandle(A.class, "field", byte.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.compareAndSet(new A(), (byte) 0, (byte) 3);
+ vh.compareAndSet(new B(), (byte) 0, (byte) 3);
+ try {
+ vh.compareAndSet(new C(), (byte) 0, (byte) 3);
+ failUnreachable();
+ } catch (ClassCastException ex) {
+ }
+ try {
+ vh.compareAndSet(0xbad0bad0, (byte) 0, (byte) 3);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.compareAndSet(0xbad0bad0, (byte) 0, Integer.MAX_VALUE);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.compareAndSet(0xbad0bad0, (byte) 0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.compareAndSet(new A(), (byte) 0, Integer.MAX_VALUE);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.compareAndSet((A) null, (byte) 0, (byte) 3);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new FieldCoordinateTypeTest().run();
+ }
+ }
+
+ public static class ArrayElementOutOfBoundsIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ long[] values = new long[33];
+ try {
+ vh.get(values, -1);
+ failUnreachable();
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(values, values.length);
+ failUnreachable();
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(values, Integer.MAX_VALUE - 1);
+ failUnreachable();
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ArrayElementOutOfBoundsIndexTest().run();
+ }
+ }
+
+ public static class ArrayElementBadIndexTypeTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ long[] values = new long[33];
+ vh.set(values, Integer.valueOf(3), Long.MIN_VALUE);
+ vh.set(values, Byte.valueOf((byte) 0), Long.MIN_VALUE);
+ try {
+ vh.set(values, 3.3f, Long.MAX_VALUE);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ArrayElementBadIndexTypeTest().run();
+ }
+ }
+
+ public static class ArrayElementNullArrayTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ long[] values = null;
+ try {
+ vh.get(values);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ArrayElementNullArrayTest().run();
+ }
+ }
+
+ public static class ArrayElementWrongArrayTypeTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.get(new char[10], 0);
+ failUnreachable();
+ } catch (ClassCastException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ArrayElementWrongArrayTypeTest().run();
+ }
+ }
+
+ public static class ArrayElementMissingIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ long[] values = new long[33];
+ try {
+ vh.get(values);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ArrayElementMissingIndexTest().run();
+ }
+ }
+
+ public static class ByteArrayViewOutOfBoundsIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[16];
+ try {
+ vh.get(bytes, -1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(bytes, bytes.length);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(bytes, Integer.MAX_VALUE - 1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(bytes, bytes.length - Integer.SIZE / 8 + 1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ vh.get(bytes, bytes.length - Integer.SIZE / 8);
+ }
+
+ public static void main(String[] args) {
+ new ByteArrayViewOutOfBoundsIndexTest().run();
+ }
+ }
+
+ public static class ByteArrayViewUnalignedAccessesIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[33];
+
+ int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0);
+ for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) {
+ // No exceptions are expected for GET and SET
+ // accessors irrespective of the access alignment.
+ vh.set(bytes, i, 380);
+ vh.get(bytes, i);
+ // Other accessors raise an IllegalStateException if
+ // the access is unaligned.
+ try {
+ vh.compareAndExchange(bytes, i, 777, 320);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndExchangeAcquire(bytes, i, 320, 767);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndExchangeRelease(bytes, i, 767, 321);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndSet(bytes, i, 767, 321);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAcquire(bytes, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAdd(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAddAcquire(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAddRelease(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAnd(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAndAcquire(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAndRelease(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOr(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOrAcquire(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOrRelease(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXor(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXorAcquire(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXorRelease(bytes, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSet(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSetAcquire(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSetRelease(bytes, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getOpaque(bytes, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getVolatile(bytes, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setOpaque(bytes, i, 777);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setRelease(bytes, i, 319);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setVolatile(bytes, i, 787);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSet(bytes, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetAcquire(bytes, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetPlain(bytes, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetRelease(bytes, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteArrayViewUnalignedAccessesIndexTest().run();
+ }
+ }
+
+ public static class ByteArrayViewBadIndexTypeTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[16];
+ // Boxed index goes through argument conversion so no exception expected.
+ vh.get(bytes, Integer.valueOf(3));
+ vh.get(bytes, Short.valueOf((short) 3));
+
+ try {
+ vh.get(bytes, System.out);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteArrayViewBadIndexTypeTest().run();
+ }
+ }
+
+ public static class ByteArrayViewMissingIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[16];
+ try {
+ vh.get(bytes);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteArrayViewMissingIndexTest().run();
+ }
+ }
+
+ public static class ByteArrayViewBadByteArrayTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = null;
+ try {
+ vh.get(bytes, Integer.valueOf(3));
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ try {
+ vh.get(System.err, Integer.valueOf(3));
+ failUnreachable();
+ } catch (ClassCastException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteArrayViewBadByteArrayTest().run();
+ }
+ }
+
+ public static class ByteBufferViewOutOfBoundsIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer[] buffers =
+ new ByteBuffer[] {
+ ByteBuffer.allocateDirect(16),
+ ByteBuffer.allocate(37),
+ ByteBuffer.wrap(new byte[27], 3, 27 - 3)
+ };
+ for (ByteBuffer buffer : buffers) {
+ try {
+ vh.get(buffer, -1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(buffer, buffer.limit());
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(buffer, Integer.MAX_VALUE - 1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ try {
+ vh.get(buffer, buffer.limit() - Integer.SIZE / 8 + 1);
+ failUnreachable();
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ vh.get(buffer, buffer.limit() - Integer.SIZE / 8);
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteBufferViewOutOfBoundsIndexTest().run();
+ }
+ }
+
+ public static class ByteBufferViewUnalignedAccessesIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer[] buffers =
+ new ByteBuffer[] {
+ ByteBuffer.allocateDirect(16),
+ ByteBuffer.allocate(37),
+ ByteBuffer.wrap(new byte[27], 3, 27 - 3)
+ };
+
+ for (ByteBuffer buffer : buffers) {
+ int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(buffer, 0);
+ for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) {
+ // No exceptions are expected for GET and SET
+ // accessors irrespective of the access alignment.
+ vh.set(buffer, i, 380);
+ vh.get(buffer, i);
+ // Other accessors raise an IllegalStateException if
+ // the access is unaligned.
+ try {
+ vh.compareAndExchange(buffer, i, 777, 320);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndExchangeAcquire(buffer, i, 320, 767);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndExchangeRelease(buffer, i, 767, 321);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.compareAndSet(buffer, i, 767, 321);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAcquire(buffer, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAdd(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAddAcquire(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndAddRelease(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAnd(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAndAcquire(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseAndRelease(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOr(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOrAcquire(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseOrRelease(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXor(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXorAcquire(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndBitwiseXorRelease(buffer, i, 118);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSet(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSetAcquire(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getAndSetRelease(buffer, i, 117);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getOpaque(buffer, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.getVolatile(buffer, i);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setOpaque(buffer, i, 777);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setRelease(buffer, i, 319);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.setVolatile(buffer, i, 787);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSet(buffer, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetAcquire(buffer, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetPlain(buffer, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ try {
+ vh.weakCompareAndSetRelease(buffer, i, 787, 340);
+ assertTrue(i == alignedIndex);
+ } catch (IllegalStateException ex) {
+ assertFalse(i == alignedIndex);
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteBufferViewUnalignedAccessesIndexTest().run();
+ }
+ }
+
+ public static class ByteBufferViewBadIndexTypeTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer[] buffers =
+ new ByteBuffer[] {
+ ByteBuffer.allocateDirect(16),
+ ByteBuffer.allocate(16),
+ ByteBuffer.wrap(new byte[32], 4, 32 - 4)
+ };
+
+ for (ByteBuffer buffer : buffers) {
+ // Boxed index goes through argument conversion so no exception expected.
+ vh.get(buffer, Integer.valueOf(3));
+ vh.get(buffer, Short.valueOf((short) 3));
+ vh.get(buffer, Byte.valueOf((byte) 7));
+ try {
+ vh.get(buffer, System.out);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteBufferViewBadIndexTypeTest().run();
+ }
+ }
+
+ public static class ByteBufferViewMissingIndexTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer[] buffers =
+ new ByteBuffer[] {
+ ByteBuffer.allocateDirect(16),
+ ByteBuffer.allocate(16),
+ ByteBuffer.wrap(new byte[32], 4, 32 - 4)
+ };
+ for (ByteBuffer buffer : buffers) {
+ try {
+ vh.get(buffer);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteBufferViewMissingIndexTest().run();
+ }
+ }
+
+ public static class ByteBufferViewBadByteBufferTest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ if (VarHandleUnitTestHelpers.isRunningOnAndroid()) {
+ ByteBuffer buffer = null;
+ // The RI does not like this test
+ try {
+ vh.get(buffer, 3);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+ try {
+ vh.get(System.err, 3);
+ failUnreachable();
+ } catch (ClassCastException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new ByteBufferViewBadByteBufferTest().run();
+ }
+ }
+
+ public static void main(String[] args) {
+ FieldCoordinateTypeTest.main(args);
+
+ ArrayElementOutOfBoundsIndexTest.main(args);
+ ArrayElementBadIndexTypeTest.main(args);
+ ArrayElementNullArrayTest.main(args);
+ ArrayElementWrongArrayTypeTest.main(args);
+ ArrayElementMissingIndexTest.main(args);
+
+ ByteArrayViewOutOfBoundsIndexTest.main(args);
+ ByteArrayViewUnalignedAccessesIndexTest.main(args);
+ ByteArrayViewBadIndexTypeTest.main(args);
+ ByteArrayViewMissingIndexTest.main(args);
+ ByteArrayViewBadByteArrayTest.main(args);
+
+ ByteBufferViewOutOfBoundsIndexTest.main(args);
+ ByteBufferViewUnalignedAccessesIndexTest.main(args);
+ ByteBufferViewBadIndexTypeTest.main(args);
+ ByteBufferViewMissingIndexTest.main(args);
+ ByteBufferViewBadByteBufferTest.main(args);
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleReflectiveTest.java b/test/712-varhandle-invocations/src/VarHandleReflectiveTest.java
new file mode 100644
index 0000000000..ae2f332171
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleReflectiveTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class VarHandleReflectiveTest {
+ public static class ReflectiveAccessorInvocations extends VarHandleUnitTest {
+ private static final VarHandle vh;
+ private static int field;
+
+ static {
+ try {
+ Class<?> cls = ReflectiveAccessorInvocations.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "field", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() throws Exception {
+ for (VarHandle.AccessMode accessMode : VarHandle.AccessMode.values()) {
+ Method accessorMethod =
+ VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
+ try {
+ accessorMethod.invoke(vh, new Object[] {new Object[] {}});
+ failUnreachable();
+ } catch (InvocationTargetException e) {
+ assertEquals(e.getCause().getClass(), UnsupportedOperationException.class);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new ReflectiveAccessorInvocations().run();
+ }
+ }
+
+ public static void main(String[] args) {
+ ReflectiveAccessorInvocations.main(args);
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java
new file mode 100644
index 0000000000..c0fbd492b2
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java
@@ -0,0 +1,1343 @@
+/*
+ * 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.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class VarHandleTypeConversionTests {
+ public static class VoidReturnTypeTest extends VarHandleUnitTest {
+ private int i;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = VoidReturnTypeTest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ // Void is always okay for a return type.
+ vh.setVolatile(this, 33);
+ vh.get(this);
+ vh.compareAndSet(this, 33, 44);
+ vh.compareAndSet(this, 27, 16);
+ vh.weakCompareAndSet(this, 17, 19);
+ vh.getAndSet(this, 200000);
+ vh.getAndBitwiseXor(this, 0x5a5a5a5a);
+ vh.getAndAdd(this, 99);
+ }
+
+ public static void main(String[] args) {
+ new VoidReturnTypeTest().run();
+ }
+ }
+
+ //
+ // Tests that a null reference as a boxed primitive type argument
+ // throws a NullPointerException. These vary the VarHandle type
+ // with each primitive for coverage.
+ //
+
+ public static class BoxedNullBooleanThrowsNPETest extends VarHandleUnitTest {
+ private static boolean z;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = BoxedNullBooleanThrowsNPETest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "z", boolean.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ Boolean newValue = null;
+ try {
+ vh.getAndSet(newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullBooleanThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullByteThrowsNPETest extends VarHandleUnitTest {
+ private byte b;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = BoxedNullByteThrowsNPETest.class;
+ vh = MethodHandles.lookup().findVarHandle(cls, "b", byte.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ Byte newValue = null;
+ try {
+ vh.getAndSet(this, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullByteThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullCharacterThrowsNPETest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.arrayElementVarHandle(char[].class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ char[] values = new char[3];
+ Character newValue = null;
+ try {
+ vh.getAndSet(values, 0, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullCharacterThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullShortThrowsNPETest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = BoxedNullShortThrowsNPETest.class;
+ vh = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[2 * Short.SIZE];
+ int index = VarHandleUnitTestHelpers.alignedOffset_short(bytes, 0);
+ Short newValue = null;
+ try {
+ vh.set(bytes, index, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullShortThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullIntegerThrowsNPETest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[2 * Integer.SIZE];
+ int index = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0);
+ Integer newValue = null;
+ try {
+ vh.setVolatile(bytes, index, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullIntegerThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullLongThrowsNPETest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = BoxedNullLongThrowsNPETest.class;
+ vh = MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer bb = ByteBuffer.allocateDirect(2 * Long.SIZE);
+ int index = VarHandleUnitTestHelpers.alignedOffset_long(bb, 0);
+ Long newValue = null;
+ try {
+ vh.getAndAdd(bb, index, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullLongThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullFloatThrowsNPETest extends VarHandleUnitTest {
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = BoxedNullFloatThrowsNPETest.class;
+ vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.BIG_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ ByteBuffer bb = ByteBuffer.allocate(2 * Float.SIZE);
+ int index = VarHandleUnitTestHelpers.alignedOffset_float(bb, 0);
+ Float newValue = null;
+ try {
+ vh.set(bb, index, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullFloatThrowsNPETest().run();
+ }
+ }
+
+ public static class BoxedNullDoubleThrowsNPETest extends VarHandleUnitTest {
+ private double d;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.byteBufferViewVarHandle(double[].class, ByteOrder.LITTLE_ENDIAN);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ byte[] bytes = new byte[3 * Double.SIZE];
+ int offset = 1;
+ ByteBuffer bb = ByteBuffer.wrap(bytes, offset, bytes.length - offset);
+ int index = VarHandleUnitTestHelpers.alignedOffset_double(bb, 0);
+ Double newValue = null;
+ try {
+ vh.set(bb, index, newValue);
+ failUnreachable();
+ } catch (NullPointerException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new BoxedNullDoubleThrowsNPETest().run();
+ }
+ }
+
+ public static class WideningBooleanArgumentTest extends VarHandleUnitTest {
+ private static boolean v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningBooleanArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(true);
+ try {
+ vh.set((byte) 3);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set('c');
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((short) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((int) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((long) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningBooleanArgumentTest().run();
+ }
+ }
+
+ public static class WideningByteArgumentTest extends VarHandleUnitTest {
+ private static byte v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningByteArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ try {
+ vh.set('c');
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((short) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((int) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((long) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningByteArgumentTest().run();
+ }
+ }
+
+ public static class WideningCharacterArgumentTest extends VarHandleUnitTest {
+ private static char v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningCharacterArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((byte) 3);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set('c');
+ try {
+ vh.set((short) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((int) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((long) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningCharacterArgumentTest().run();
+ }
+ }
+
+ public static class WideningShortArgumentTest extends VarHandleUnitTest {
+ private static short v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningShortArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ try {
+ vh.set('c');
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((short) 1);
+ try {
+ vh.set((int) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((long) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningShortArgumentTest().run();
+ }
+ }
+
+ public static class WideningIntegerArgumentTest extends VarHandleUnitTest {
+ private static int v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningIntegerArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ vh.set('c');
+ vh.set((char) 0x8fff);
+ assertEquals(0x8fff, v);
+ vh.set((short) 1);
+ vh.set((int) 1);
+ try {
+ vh.set((long) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningIntegerArgumentTest().run();
+ }
+ }
+
+ public static class WideningLongArgumentTest extends VarHandleUnitTest {
+ private static long v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningLongArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ vh.set('c');
+ vh.set((short) 1);
+ vh.set((int) 1);
+ vh.set((long) 1);
+ try {
+ vh.set((float) 1.0f);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningLongArgumentTest().run();
+ }
+ }
+
+ public static class WideningFloatArgumentTest extends VarHandleUnitTest {
+ private static float v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningFloatArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ vh.set('c');
+ vh.set((short) 1);
+ vh.set((int) 1);
+ vh.set((long) 1);
+ vh.set((float) 1.0f);
+ try {
+ vh.set((double) 1.0);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningFloatArgumentTest().run();
+ }
+ }
+
+ public static class WideningDoubleArgumentTest extends VarHandleUnitTest {
+ private static double v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningDoubleArgumentTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ vh.set((byte) 3);
+ vh.set('c');
+ vh.set((short) 1);
+ vh.set((int) 1);
+ vh.set((long) 1);
+ vh.set((double) 1.0f);
+ vh.set((double) 1.0);
+ }
+
+ public static void main(String[] args) {
+ new WideningDoubleArgumentTest().run();
+ }
+ }
+
+ public static class WideningBooleanReturnValueTest extends VarHandleUnitTest {
+ private static boolean v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningBooleanReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(true);
+ vh.get();
+ boolean z = (boolean) vh.get();
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ int i = (int) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ long j = (long) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ float f = (float) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ double d = (double) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningBooleanReturnValueTest().run();
+ }
+ }
+
+ public static class WideningByteReturnValueTest extends VarHandleUnitTest {
+ private static byte v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningByteReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set((byte) 3);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+
+ byte b = (byte) vh.get();
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ short s = (short) vh.get();
+ int i = (int) vh.get();
+ long j = (long) vh.get();
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+
+ public static void main(String[] args) {
+ new WideningByteReturnValueTest().run();
+ }
+ }
+
+ public static class WideningCharacterReturnValueTest extends VarHandleUnitTest {
+ private static char v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningCharacterReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningCharacterReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set('c');
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ char c = (char) vh.get();
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ int i = (int) vh.get();
+ long j = (long) vh.get();
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class WideningShortReturnValueTest extends VarHandleUnitTest {
+ private static short v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningShortReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningShortReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set((short) 8888);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ short s = (short) vh.get();
+ int i = (int) vh.get();
+ long j = (long) vh.get();
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class WideningIntegerReturnValueTest extends VarHandleUnitTest {
+ private static int v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningIntegerReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningIntegerReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(0x1234fedc);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ int i = (int) vh.get();
+ long j = (long) vh.get();
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class WideningLongReturnValueTest extends VarHandleUnitTest {
+ private static long v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningLongReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningLongReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(0xfedcba987654321l);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ int i = (int) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ long j = (long) vh.get();
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class WideningFloatReturnValueTest extends VarHandleUnitTest {
+ private static float v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningFloatReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningFloatReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(7.77e20f);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ int i = (int) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ long j = (long) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ float f = (float) vh.get();
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class WideningDoubleReturnValueTest extends VarHandleUnitTest {
+ private static double v;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ Class<?> cls = WideningDoubleReturnValueTest.class;
+ vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new WideningDoubleReturnValueTest().run();
+ }
+
+ @Override
+ protected void doTest() {
+ vh.set(Math.E);
+ vh.get();
+ try {
+ boolean z = (boolean) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ byte b = (byte) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ char c = (char) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ short s = (short) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ int i = (int) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ long j = (long) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ try {
+ float f = (float) vh.get();
+ failUnreachable();
+ } catch (WrongMethodTypeException ex) {
+ }
+ double d = (double) vh.get();
+ }
+ }
+
+ public static class SubtypeTest extends VarHandleUnitTest {
+ private static final Widget INITIAL_VALUE = Widget.ONE;
+ private static final VarHandle vh;
+ private Widget w = INITIAL_VALUE;
+
+ static {
+ try {
+ vh = MethodHandles.lookup().findVarHandle(SubtypeTest.class, "w", Widget.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new SubtypeTest().run();
+ }
+
+ // A sub-type of the Widget class
+ public static class WidgetChild extends Widget {
+ private int weight;
+
+ public WidgetChild(int requistionNumber, int weight) {
+ super(requistionNumber);
+ this.weight = weight;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof WidgetChild == false) {
+ return false;
+ }
+ WidgetChild wc = (WidgetChild) o;
+ return (requisitionNumber == wc.requisitionNumber && weight == wc.weight);
+ }
+
+ public static final WidgetChild ONE = new WidgetChild(1, 100);
+ public static final WidgetChild TWO = new WidgetChild(2, 2000);
+ }
+
+ @Override
+ public void doTest() {
+ assertEquals(INITIAL_VALUE, vh.getVolatile(this));
+ vh.setVolatile(this, null);
+ Widget rw = (Widget) vh.compareAndExchange(this, null, WidgetChild.ONE);
+ assertEquals(null, rw);
+ assertEquals(WidgetChild.ONE, this.w);
+ WidgetChild rwc =
+ (WidgetChild)
+ vh.compareAndExchangeRelease(this, WidgetChild.ONE, WidgetChild.TWO);
+ assertEquals(WidgetChild.TWO, w);
+ rwc = (WidgetChild) vh.compareAndExchangeAcquire(this, WidgetChild.TWO, Widget.ONE);
+ assertEquals(Widget.ONE, w);
+ assertEquals(false, (boolean) vh.compareAndSet(this, null, null));
+ assertEquals(true, vh.compareAndSet(this, Widget.ONE, Widget.TWO));
+ assertEquals(Widget.TWO, w);
+ vh.set(this, null);
+ assertEquals(null, (Widget) vh.get(this));
+ vh.setRelease(this, WidgetChild.ONE);
+ assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAcquire(this));
+ assertEquals(WidgetChild.ONE, w);
+ vh.setOpaque(this, WidgetChild.TWO);
+ assertEquals(WidgetChild.TWO, vh.getOpaque(this));
+ assertEquals(WidgetChild.TWO, w);
+ vh.setVolatile(this, null);
+ assertEquals(null, (Widget) vh.getVolatile(this));
+ assertEquals(null, w);
+ assertEquals(null, (WidgetChild) vh.getAndSet(this, WidgetChild.ONE));
+ assertEquals(WidgetChild.ONE, w);
+ assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAndSetRelease(this, WidgetChild.TWO));
+ assertEquals(WidgetChild.TWO, (WidgetChild) vh.getAndSetAcquire(this, WidgetChild.ONE));
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndAdd(this, WidgetChild.ONE);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndAddAcquire(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndAddRelease(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseAnd(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseAndAcquire(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseAndRelease(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseOr(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseOrAcquire(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseOrRelease(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseXor(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseXorAcquire(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ WidgetChild result = (WidgetChild) vh.getAndBitwiseXorRelease(this, 1);
+ failUnreachable();
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+ }
+
+ public static class SupertypeTest extends VarHandleUnitTest {
+ private Widget w = null;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh = MethodHandles.lookup().findVarHandle(SupertypeTest.class, "w", Widget.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new SupertypeTest().run();
+ }
+
+ @Override
+ public void doTest() {
+ assertEquals(null, (Object) vh.get(this));
+ vh.set(this, Widget.ONE);
+ assertEquals(Widget.ONE, vh.getVolatile(this));
+ try {
+ vh.setVolatile(this, new Object());
+ } catch (ClassCastException e) {
+ }
+ }
+ }
+
+ public static class ImplicitBoxingIntegerTest extends VarHandleUnitTest {
+ private static Integer field;
+ private static final VarHandle vh;
+
+ static {
+ try {
+ vh =
+ MethodHandles.lookup()
+ .findStaticVarHandle(
+ ImplicitBoxingIntegerTest.class, "field", Integer.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ new ImplicitBoxingIntegerTest().run();
+ }
+
+ @Override
+ public void doTest() {
+ try {
+ vh.set(true);
+ failUnreachable();
+ } catch (WrongMethodTypeException e) {
+ }
+ try {
+ vh.set((byte) 0);
+ failUnreachable();
+ } catch (WrongMethodTypeException e) {
+ }
+ try {
+ vh.set((short) 1);
+ failUnreachable();
+ } catch (WrongMethodTypeException e) {
+ }
+ try {
+ vh.set('A');
+ failUnreachable();
+ } catch (WrongMethodTypeException e) {
+ }
+ vh.set(2);
+ try {
+ vh.setRelease(Long.MAX_VALUE);
+ } catch (WrongMethodTypeException e) {
+ }
+ try {
+ vh.setRelease(Float.MAX_VALUE);
+ } catch (WrongMethodTypeException e) {
+ }
+ try {
+ vh.setRelease(Double.MAX_VALUE);
+ } catch (WrongMethodTypeException e) {
+ }
+ vh.set(null);
+ vh.set(Integer.valueOf(Integer.MAX_VALUE));
+ }
+ }
+
+ public static void main(String[] args) {
+ VoidReturnTypeTest.main(args);
+
+ BoxedNullBooleanThrowsNPETest.main(args);
+ BoxedNullByteThrowsNPETest.main(args);
+ BoxedNullCharacterThrowsNPETest.main(args);
+ BoxedNullShortThrowsNPETest.main(args);
+ BoxedNullIntegerThrowsNPETest.main(args);
+ BoxedNullLongThrowsNPETest.main(args);
+ BoxedNullFloatThrowsNPETest.main(args);
+ BoxedNullDoubleThrowsNPETest.main(args);
+
+ WideningBooleanArgumentTest.main(args);
+ WideningByteArgumentTest.main(args);
+ WideningCharacterArgumentTest.main(args);
+ WideningShortArgumentTest.main(args);
+ WideningIntegerArgumentTest.main(args);
+ WideningLongArgumentTest.main(args);
+ WideningFloatArgumentTest.main(args);
+ WideningDoubleArgumentTest.main(args);
+
+ WideningBooleanReturnValueTest.main(args);
+ WideningByteReturnValueTest.main(args);
+ WideningCharacterReturnValueTest.main(args);
+ WideningShortReturnValueTest.main(args);
+ WideningIntegerReturnValueTest.main(args);
+ WideningLongReturnValueTest.main(args);
+ WideningFloatReturnValueTest.main(args);
+ WideningDoubleReturnValueTest.main(args);
+
+ SubtypeTest.main(args);
+ SupertypeTest.main(args);
+
+ ImplicitBoxingIntegerTest.main(args);
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTest.java b/test/712-varhandle-invocations/src/VarHandleUnitTest.java
new file mode 100644
index 0000000000..601d470950
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleUnitTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+// Base class for VarHandle unit tests for accessor operations
+public abstract class VarHandleUnitTest {
+ public static VarHandleUnitTestCollector DEFAULT_COLLECTOR = new VarHandleUnitTestCollector();
+
+ // Error log (lazily initialized on failure).
+ private StringBuilder lazyErrorLog = null;
+
+ // Tracker of test events (starts, skips, ends)
+ private final VarHandleUnitTestCollector collector;
+
+ public VarHandleUnitTest(VarHandleUnitTestCollector collector) {
+ this.collector = collector;
+ }
+
+ public VarHandleUnitTest() {
+ this.collector = DEFAULT_COLLECTOR;
+ }
+
+ // Method that can be overloaded to signify that a test should be
+ // run or skipped. Returns true if the test should be run and
+ // false if the test should be skipped.
+ public boolean checkGuard() {
+ return true;
+ }
+
+ // Method that implementations should use to perform a specific test.
+ protected abstract void doTest() throws Exception;
+
+ public final void assertTrue(boolean value) {
+ assertEquals(true, value);
+ }
+
+ public final void assertFalse(boolean value) {
+ assertEquals(false, value);
+ }
+
+ public final void assertEquals(boolean expected, boolean actual) {
+ assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
+ }
+
+ public final void assertEquals(byte expected, byte actual) {
+ assertEquals(Byte.valueOf(expected), Byte.valueOf(actual));
+ }
+
+ public final void assertEquals(char expected, char actual) {
+ assertEquals(Character.valueOf(expected), Character.valueOf(actual));
+ }
+
+ public final void assertEquals(short expected, short actual) {
+ assertEquals(Short.valueOf(expected), Short.valueOf(actual));
+ }
+
+ public final void assertEquals(int expected, int actual) {
+ assertEquals(Integer.valueOf(expected), Integer.valueOf(actual));
+ }
+
+ public final void assertEquals(long expected, long actual) {
+ assertEquals(Long.valueOf(expected), Long.valueOf(actual));
+ }
+
+ public final void assertEquals(float expected, float actual) {
+ assertEquals(Float.valueOf(expected), Float.valueOf(actual));
+ }
+
+ public final void assertEquals(double expected, double actual) {
+ assertEquals(Double.valueOf(expected), Double.valueOf(actual));
+ }
+
+ public final void assertEquals(Object expected, Object actual) {
+ if (expected == null) {
+ if (actual == null) {
+ return;
+ }
+ } else if (expected.equals(actual)) {
+ return;
+ }
+ failNotEquals("Failed assertion (expected != actual)", expected, actual);
+ }
+
+ public final void failUnreachable() {
+ fail("Unreachable code");
+ }
+
+ public final void run() {
+ collector.start(getClass().getSimpleName());
+ if (!checkGuard()) {
+ collector.skip();
+ return;
+ }
+
+ try {
+ doTest();
+ } catch (Exception e) {
+ fail("Unexpected exception", e);
+ } finally {
+ if (lazyErrorLog == null) {
+ collector.success();
+ } else {
+ collector.fail(lazyErrorLog.toString());
+ }
+ }
+ }
+
+ private void failNotEquals(String message, Object expected, Object actual) {
+ errorLog()
+ .append(message)
+ .append(": ")
+ .append(expected)
+ .append(" != ")
+ .append(actual)
+ .append(" in ")
+ .append(getSourceInfo())
+ .append('\n');
+ }
+
+ private void fail(String message) {
+ errorLog().append(message).append(" in ").append(getSourceInfo()).append('\n');
+ }
+
+ private void fail(String message, String detail) {
+ errorLog()
+ .append(message)
+ .append(": ")
+ .append(detail)
+ .append(" in ")
+ .append(getSourceInfo())
+ .append('\n');
+ }
+
+ private void fail(String message, Exception e) {
+ errorLog()
+ .append(message)
+ .append(": ")
+ .append(e.toString())
+ .append(" in ")
+ .append(getSourceInfo(e))
+ .append('\n');
+ }
+
+ private String getSourceInfo(Exception e) {
+ // Unit test has thrown an exception. Stack likely looks like
+ // runtime frames then unit test frames then
+ // VarHandleUnitFrames.
+ StackTraceElement[] stackTraceElements = e.getStackTrace();
+ int index = 1;
+ for (int i = 1; i < stackTraceElements.length; ++i) {
+ if ("VarHandleUnitTest".equals(stackTraceElements[i].getClassName())) {
+ return stackTraceElements[i - 1].toString();
+ }
+ }
+ return "Unknown";
+ }
+
+ private String getSourceInfo() {
+ // Gets source info for a failure such as an assertion. The
+ // test has called a method on VarHandleUnitTest so the stack
+ // looks like some frames in VarHandleUnitTest methods and then
+ // a frame in the test itself.
+ StackTraceElement[] stackTraceElements = new Exception().getStackTrace();
+ for (StackTraceElement stackTraceElement : stackTraceElements) {
+ if (!"VarHandleUnitTest".equals(stackTraceElement.getClassName())) {
+ return stackTraceElement.toString();
+ }
+ }
+ return "Unknown";
+ }
+
+ private StringBuilder errorLog() {
+ if (lazyErrorLog == null) {
+ lazyErrorLog = new StringBuilder();
+ }
+ return lazyErrorLog;
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java b/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java
new file mode 100644
index 0000000000..bc64c0c8b1
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.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.io.PrintStream;
+
+// Results collector for VarHandle Unit tests
+public final class VarHandleUnitTestCollector {
+ private final PrintStream out = System.out;
+
+ private int numberOfSuccesses;
+ private int numberOfSkips;
+ private int numberOfFailures;
+
+ public void start(String testName) {
+ out.print(testName);
+ out.print("...");
+ }
+
+ public void skip() {
+ numberOfSkips += 1;
+ out.println("SKIP");
+ }
+
+ public void success() {
+ numberOfSuccesses += 1;
+ out.println("OK");
+ }
+
+ public void fail(String errorMessage) {
+ numberOfFailures += 1;
+ out.println("FAIL");
+ out.print(errorMessage);
+ }
+
+ public void printSummary() {
+ out.append(Integer.toString(numberOfSuccesses))
+ .append(" successes, ")
+ .append(Integer.toString(numberOfSkips))
+ .append(" skips, ")
+ .append(Integer.toString(numberOfFailures))
+ .append(" failures.");
+ out.println();
+ }
+
+ boolean failuresOccurred() {
+ return numberOfFailures != 0;
+ }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java b/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java
new file mode 100644
index 0000000000..6f72e9962f
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java
@@ -0,0 +1,281 @@
+/*
+ * 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.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class VarHandleUnitTestHelpers {
+ public static boolean isRunningOnAndroid() {
+ return System.getProperty("java.vm.vendor").contains("Android");
+ }
+
+ public static boolean is64Bit() {
+ // The behaviour of certain accessors depends on the ISA word size.
+ if (isRunningOnAndroid()) {
+ try {
+ Class<?> runtimeClass = Class.forName("dalvik.system.VMRuntime");
+ MethodHandle getRuntimeMH =
+ MethodHandles.lookup()
+ .findStatic(
+ runtimeClass,
+ "getRuntime",
+ MethodType.methodType(runtimeClass));
+ Object runtime = getRuntimeMH.invoke();
+ MethodHandle is64BitMH =
+ MethodHandles.lookup()
+ .findVirtual(
+ runtimeClass,
+ "is64Bit",
+ MethodType.methodType(boolean.class));
+ return (boolean) is64BitMH.invoke(runtime);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ } else {
+ return System.getProperty("sun.arch.data.model").equals("64");
+ }
+ }
+
+ public static boolean getBytesAs_boolean(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_boolean(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static byte getBytesAs_byte(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_byte(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static char getBytesAs_char(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_char(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static short getBytesAs_short(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_short(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static int getBytesAs_int(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_int(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static long getBytesAs_long(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_long(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static float getBytesAs_float(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_float(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static double getBytesAs_double(byte[] array, int index, ByteOrder order) {
+ return getBytesAs_double(ByteBuffer.wrap(array), index, order);
+ }
+
+ public static boolean getBytesAs_boolean(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).get(index) != 0;
+ }
+
+ public static byte getBytesAs_byte(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).get(index);
+ }
+
+ public static char getBytesAs_char(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getChar(index);
+ }
+
+ public static short getBytesAs_short(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getShort(index);
+ }
+
+ public static int getBytesAs_int(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getInt(index);
+ }
+
+ public static long getBytesAs_long(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getLong(index);
+ }
+
+ public static float getBytesAs_float(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getFloat(index);
+ }
+
+ public static double getBytesAs_double(ByteBuffer buffer, int index, ByteOrder order) {
+ return buffer.order(order).getDouble(index);
+ }
+
+ public static void setBytesAs_boolean(byte[] array, int index, boolean value, ByteOrder order) {
+ setBytesAs_boolean(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_byte(byte[] array, int index, byte value, ByteOrder order) {
+ setBytesAs_byte(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_char(byte[] array, int index, char value, ByteOrder order) {
+ setBytesAs_char(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_short(byte[] array, int index, short value, ByteOrder order) {
+ setBytesAs_short(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_int(byte[] array, int index, int value, ByteOrder order) {
+ setBytesAs_int(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_long(byte[] array, int index, long value, ByteOrder order) {
+ setBytesAs_long(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_float(byte[] array, int index, float value, ByteOrder order) {
+ setBytesAs_float(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_double(byte[] array, int index, double value, ByteOrder order) {
+ setBytesAs_double(ByteBuffer.wrap(array), index, value, order);
+ }
+
+ public static void setBytesAs_boolean(
+ ByteBuffer buffer, int index, boolean value, ByteOrder order) {
+ buffer.order(order).put(index, value ? (byte) 1 : (byte) 0);
+ }
+
+ public static void setBytesAs_byte(ByteBuffer buffer, int index, byte value, ByteOrder order) {
+ buffer.order(order).put(index, value);
+ }
+
+ public static void setBytesAs_char(ByteBuffer buffer, int index, char value, ByteOrder order) {
+ buffer.order(order).putChar(index, value);
+ }
+
+ public static void setBytesAs_short(
+ ByteBuffer buffer, int index, short value, ByteOrder order) {
+ buffer.order(order).putShort(index, value);
+ }
+
+ public static void setBytesAs_int(ByteBuffer buffer, int index, int value, ByteOrder order) {
+ buffer.order(order).putInt(index, value);
+ }
+
+ public static void setBytesAs_long(ByteBuffer buffer, int index, long value, ByteOrder order) {
+ buffer.order(order).putLong(index, value);
+ }
+
+ public static void setBytesAs_float(
+ ByteBuffer buffer, int index, float value, ByteOrder order) {
+ buffer.order(order).putFloat(index, value);
+ }
+
+ public static void setBytesAs_double(
+ ByteBuffer buffer, int index, double value, ByteOrder order) {
+ buffer.order(order).putDouble(index, value);
+ }
+
+ // Until ART is running on an OpenJDK9 based runtime, there are no
+ // calls to help with alignment. OpenJDK9 introduces
+ // ByteBuffer.alignedSlice() and ByteBuffer.alignmentOffset(). RI
+ // and ART have different data structure alignments which may make
+ // porting code interesting.
+
+ public static int alignedOffset_char(ByteBuffer buffer, int start) {
+ return alignedOffset_short(buffer, start);
+ }
+
+ public static int alignedOffset_short(ByteBuffer buffer, int start) {
+ for (int i = 0; i < Short.SIZE; ++i) {
+ try {
+ vh_probe_short.getVolatile(buffer, start + i);
+ return start + i;
+ } catch (IllegalStateException e) {
+ // Unaligned access.
+ }
+ }
+ return start;
+ }
+
+ public static int alignedOffset_int(ByteBuffer buffer, int start) {
+ for (int i = 0; i < Integer.SIZE; ++i) {
+ try {
+ vh_probe_int.getVolatile(buffer, start + i);
+ return start + i;
+ } catch (IllegalStateException e) {
+ // Unaligned access.
+ } catch (Exception e) {
+ break;
+ }
+ }
+ return start;
+ }
+
+ public static int alignedOffset_long(ByteBuffer buffer, int start) {
+ for (int i = 0; i < Long.SIZE; ++i) {
+ try {
+ vh_probe_long.getVolatile(buffer, start + i);
+ return start + i;
+ } catch (IllegalStateException e) {
+ // Unaligned access.
+ } catch (UnsupportedOperationException e) {
+ // 64-bit operation is not supported irrespective of alignment.
+ break;
+ }
+ }
+ return start;
+ }
+
+ public static int alignedOffset_float(ByteBuffer buffer, int start) {
+ return alignedOffset_int(buffer, start);
+ }
+
+ public static int alignedOffset_double(ByteBuffer buffer, int start) {
+ return alignedOffset_long(buffer, start);
+ }
+
+ public static int alignedOffset_char(byte[] array, int start) {
+ return alignedOffset_char(ByteBuffer.wrap(array), start);
+ }
+
+ public static int alignedOffset_short(byte[] array, int start) {
+ return alignedOffset_short(ByteBuffer.wrap(array), start);
+ }
+
+ public static int alignedOffset_int(byte[] array, int start) {
+ return alignedOffset_int(ByteBuffer.wrap(array), start);
+ }
+
+ public static int alignedOffset_long(byte[] array, int start) {
+ return alignedOffset_long(ByteBuffer.wrap(array), start);
+ }
+
+ public static int alignedOffset_float(byte[] array, int start) {
+ return alignedOffset_float(ByteBuffer.wrap(array), start);
+ }
+
+ public static int alignedOffset_double(byte[] array, int start) {
+ return alignedOffset_double(ByteBuffer.wrap(array), start);
+ }
+
+ static {
+ ByteOrder order = ByteOrder.LITTLE_ENDIAN;
+ vh_probe_short = MethodHandles.byteBufferViewVarHandle(short[].class, order);
+ vh_probe_int = MethodHandles.byteBufferViewVarHandle(int[].class, order);
+ vh_probe_long = MethodHandles.byteBufferViewVarHandle(long[].class, order);
+ }
+
+ private static final VarHandle vh_probe_short;
+ private static final VarHandle vh_probe_int;
+ private static final VarHandle vh_probe_long;
+}
diff --git a/test/712-varhandle-invocations/src/Widget.java b/test/712-varhandle-invocations/src/Widget.java
new file mode 100644
index 0000000000..0282ff8d64
--- /dev/null
+++ b/test/712-varhandle-invocations/src/Widget.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+// Widget class for reference type accessor tests.
+public class Widget {
+ protected int requisitionNumber;
+
+ public Widget(int requisitionNumber) {
+ this.requisitionNumber = requisitionNumber;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Widget)) {
+ return false;
+ }
+ Widget wo = (Widget) o;
+ return requisitionNumber == wo.requisitionNumber;
+ }
+
+ public static final Widget ONE = new Widget(1);
+ public static final Widget TWO = new Widget(2);
+}
diff --git a/test/712-varhandle-invocations/util-src/generate_java.py b/test/712-varhandle-invocations/util-src/generate_java.py
new file mode 100644
index 0000000000..9520b53844
--- /dev/null
+++ b/test/712-varhandle-invocations/util-src/generate_java.py
@@ -0,0 +1,876 @@
+#!/usr/bin/python3
+#
+# 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.
+
+"""
+Generate java test files for 712-varhandle-invocations
+"""
+
+from enum import Enum
+from pathlib import Path
+from random import Random
+from string import Template
+
+import io
+import re
+import sys
+
+class JavaType(object):
+ def __init__(self, name, examples, supports_bitwise=False, supports_numeric=False):
+ self.name=name
+ self.examples=examples
+ self.supports_bitwise=supports_bitwise
+ self.supports_numeric=supports_numeric
+
+ def is_value_type(self):
+ return False
+
+ def __repr__(self):
+ return self.name
+
+ def __str__(self):
+ return self.name
+
+class ValueType(JavaType):
+ def __init__(self, name, boxed_type, examples, ordinal=-1, width=-1, supports_bitwise=True, supports_numeric=True):
+ JavaType.__init__(self, name, examples, supports_bitwise, supports_numeric)
+ self.ordinal=ordinal
+ self.width=width
+ self.boxed_type=boxed_type
+
+ def boxing_method(self):
+ return self.boxed_type + ".valueOf"
+
+ def unboxing_method(self):
+ return self.name + "Value"
+
+ def is_value_type(self):
+ return True
+
+ def __eq__(self, other):
+ return self.ordinal == other.ordinal
+
+ def __hash__(self):
+ return self.ordinal
+
+ def __le__(self, other):
+ return self.ordinal < other.ordinal
+
+ def __repr__(self):
+ return self.name
+
+ def __str__(self):
+ return self.name
+
+BOOLEAN_TYPE = ValueType("boolean", "Boolean", [ "true", "false" ], ordinal = 0, width = 1, supports_numeric=False)
+BYTE_TYPE=ValueType("byte", "Byte", [ "(byte) -128", "(byte) -61", "(byte) 7", "(byte) 127", "(byte) 33" ], ordinal=1, width=1)
+SHORT_TYPE=ValueType("short", "Short", [ "(short) -32768", "(short) -384", "(short) 32767", "(short) 0xaa55" ], ordinal=2, width=2)
+CHAR_TYPE=ValueType("char", "Character", [ r"'A'", r"'#'", r"'$'", r"'Z'", r"'t'", r"'c'" ], ordinal=3, width=2)
+INT_TYPE=ValueType("int", "Integer", [ "-0x01234567", "0x7f6e5d4c", "0x12345678", "0x10215220", "42" ], ordinal=4, width=4)
+LONG_TYPE=ValueType("long", "Long", [ "-0x0123456789abcdefl", "0x789abcdef0123456l", "0xfedcba9876543210l" ], ordinal=5, width=8)
+FLOAT_TYPE=ValueType("float", "Float", [ "-7.77e23f", "1.234e-17f", "3.40e36f", "-8.888e3f", "4.442e11f" ], ordinal=6, width=4, supports_bitwise=False)
+DOUBLE_TYPE=ValueType("double", "Double", [ "-1.0e-200", "1.11e200", "3.141", "1.1111", "6.022e23", "6.626e-34" ], ordinal=7, width=4, supports_bitwise=False)
+
+VALUE_TYPES = { BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }
+
+WIDENING_CONVERSIONS = {
+ BOOLEAN_TYPE : set(),
+ BYTE_TYPE : { SHORT_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE },
+ SHORT_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE },
+ CHAR_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE },
+ INT_TYPE : { LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE },
+ LONG_TYPE : { FLOAT_TYPE, DOUBLE_TYPE },
+ FLOAT_TYPE : { DOUBLE_TYPE },
+ DOUBLE_TYPE : set()
+}
+
+def types_that_widen_to(var_type):
+ types_that_widen = { var_type }
+ for src_type in WIDENING_CONVERSIONS:
+ if var_type in WIDENING_CONVERSIONS[src_type]:
+ types_that_widen.add(src_type)
+ return types_that_widen
+
+class VarHandleKind(object):
+ ALL_SUPPORTED_TYPES = VALUE_TYPES
+ VIEW_SUPPORTED_TYPES = list(filter(lambda x : x.width >= 2, ALL_SUPPORTED_TYPES))
+
+ def __init__(self, name, imports=[], declarations=[], lookup='', coordinates=[], get_value='', may_throw_read_only=False):
+ self.name = name
+ self.imports = imports
+ self.declarations = declarations
+ self.lookup = lookup
+ self.coordinates = coordinates
+ self.get_value_ = get_value
+ self.may_throw_read_only = may_throw_read_only
+
+ def get_name(self):
+ return self.name
+
+ def get_coordinates(self):
+ return self.coordinates
+
+ def get_field_declarations(self, dictionary):
+ return list(map(lambda d: Template(d).safe_substitute(dictionary), self.declarations))
+
+ def get_imports(self):
+ return self.imports
+
+ def get_lookup(self, dictionary):
+ return Template(self.lookup).safe_substitute(dictionary)
+
+ def get_supported_types(self):
+ return VarHandleKind.VIEW_SUPPORTED_TYPES if self.is_view() else VarHandleKind.ALL_SUPPORTED_TYPES
+
+ def is_view(self):
+ return "View" in self.name
+
+ def get_value(self, dictionary):
+ return Template(self.get_value_).safe_substitute(dictionary)
+
+FIELD_VAR_HANDLE = VarHandleKind("Field",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle'
+ ],
+ [
+ "${var_type} field = ${initial_value}"
+ ],
+ 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)',
+ [
+ 'this'
+ ],
+ 'field',
+ may_throw_read_only = False)
+
+FINAL_FIELD_VAR_HANDLE = VarHandleKind("FinalField",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle'
+ ],
+ [
+ "${var_type} field = ${initial_value}"
+ ],
+ 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)',
+ [
+ 'this'
+ ],
+ 'field',
+ may_throw_read_only = False)
+
+STATIC_FIELD_VAR_HANDLE = VarHandleKind("StaticField",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle'
+ ],
+ [
+ "static ${var_type} field = ${initial_value}"
+ ],
+ 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)',
+ [],
+ 'field',
+ may_throw_read_only = False)
+
+STATIC_FINAL_FIELD_VAR_HANDLE = VarHandleKind("StaticFinalField",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle'
+ ],
+ [
+ "static ${var_type} field = ${initial_value}"
+ ],
+ 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)',
+ [],
+ 'field',
+ may_throw_read_only = False)
+
+ARRAY_ELEMENT_VAR_HANDLE = VarHandleKind("ArrayElement",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle'
+ ],
+ [
+ "${var_type}[] array = new ${var_type}[11]",
+ "int index = 3",
+ "{ array[index] = ${initial_value}; }"
+ ],
+ 'MethodHandles.arrayElementVarHandle(${var_type}[].class)',
+ [ 'array', 'index'],
+ 'array[index]',
+ may_throw_read_only = False)
+
+BYTE_ARRAY_LE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewLE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "byte[] array = new byte[27]",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)',
+ [
+ 'array',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.LITTLE_ENDIAN)',
+ may_throw_read_only = False)
+
+BYTE_ARRAY_BE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewBE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "byte[] array = new byte[27]",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)',
+ [
+ 'array',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.BIG_ENDIAN)',
+ may_throw_read_only = False)
+
+DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewLE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "ByteBuffer bb = ByteBuffer.allocateDirect(31)",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)',
+ may_throw_read_only = False)
+
+DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewBE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "ByteBuffer bb = ByteBuffer.allocateDirect(31)",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)',
+ may_throw_read_only = False)
+
+HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewLE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "byte[] array = new byte[36]",
+ "int offset = 8",
+ "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)',
+ may_throw_read_only = False)
+
+HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewBE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder'
+ ],
+ [
+ "byte[] array = new byte[47]",
+ "int offset = 8",
+ "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)",
+ "int index = 8",
+ "{"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);"
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)',
+ may_throw_read_only = False)
+
+HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewLE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder',
+ 'java.nio.ReadOnlyBufferException'
+ ],
+ [
+ "byte[] array = new byte[43]",
+ "int index = 8",
+ "ByteBuffer bb",
+ "{"
+ " bb = ByteBuffer.wrap(array).asReadOnlyBuffer();"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);"
+ " bb = bb.asReadOnlyBuffer();"
+
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)',
+ may_throw_read_only = True)
+
+HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewBE",
+ [
+ 'java.lang.invoke.MethodHandles',
+ 'java.lang.invoke.VarHandle',
+ 'java.nio.ByteBuffer',
+ 'java.nio.ByteOrder',
+ 'java.nio.ReadOnlyBufferException'
+ ],
+ [
+ "byte[] array = new byte[29]",
+ "int index",
+ "ByteBuffer bb",
+ "{"
+ " bb = ByteBuffer.wrap(array);"
+ " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, 8);"
+ " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);"
+ " bb = bb.asReadOnlyBuffer();"
+ "}"
+ ],
+ 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)',
+ [
+ 'bb',
+ 'index'
+ ],
+ 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)',
+ may_throw_read_only = True)
+
+ALL_FIELD_VAR_HANDLE_KINDS = [
+ FIELD_VAR_HANDLE,
+ FINAL_FIELD_VAR_HANDLE,
+ STATIC_FIELD_VAR_HANDLE,
+ STATIC_FINAL_FIELD_VAR_HANDLE
+]
+
+ALL_BYTE_VIEW_VAR_HANDLE_KINDS = [
+ BYTE_ARRAY_LE_VIEW_VAR_HANDLE,
+ BYTE_ARRAY_BE_VIEW_VAR_HANDLE,
+ DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE,
+ DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE,
+ HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE,
+ HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE,
+ HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE,
+ HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE
+]
+
+ALL_VAR_HANDLE_KINDS = ALL_FIELD_VAR_HANDLE_KINDS + [ ARRAY_ELEMENT_VAR_HANDLE ] + ALL_BYTE_VIEW_VAR_HANDLE_KINDS
+
+class AccessModeForm(Enum):
+ GET = 0
+ SET = 1
+ STRONG_COMPARE_AND_SET = 2
+ WEAK_COMPARE_AND_SET = 3
+ COMPARE_AND_EXCHANGE = 4
+ GET_AND_SET = 5
+ GET_AND_UPDATE_BITWISE = 6
+ GET_AND_UPDATE_NUMERIC = 7
+
+class VarHandleAccessor:
+ def __init__(self, method_name):
+ self.method_name = method_name
+ self.access_mode = self.get_access_mode(method_name)
+ self.access_mode_form = self.get_access_mode_form(method_name)
+
+ def get_return_type(self, var_type):
+ if self.access_mode_form == AccessModeForm.SET:
+ return None
+ elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or
+ self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET):
+ return BOOLEAN_TYPE
+ else:
+ return var_type
+
+ def get_number_of_var_type_arguments(self):
+ if self.access_mode_form == AccessModeForm.GET:
+ return 0
+ elif (self.access_mode_form == AccessModeForm.SET or
+ self.access_mode_form == AccessModeForm.GET_AND_SET or
+ self.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE or
+ self.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC):
+ return 1
+ elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or
+ self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET or
+ self.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE):
+ return 2
+ else:
+ raise ValueError(self.access_mode_form)
+
+ def is_read_only(self):
+ return self.access_mode_form == AccessModeForm.GET
+
+ def get_java_bitwise_operator(self):
+ if "BitwiseAnd" in self.method_name:
+ return "&"
+ elif "BitwiseOr" in self.method_name:
+ return "|"
+ elif "BitwiseXor" in self.method_name:
+ return "^"
+ raise ValueError(self.method_name)
+
+ def get_java_numeric_operator(self):
+ if "Add" in self.method_name:
+ return "+"
+ raise ValueError(self.method_name)
+
+ @staticmethod
+ def get_access_mode(accessor_method):
+ """Converts an access method name to AccessMode value. For example, getAndSet becomes GET_AND_SET"""
+ return re.sub('([A-Z])', r'_\1', accessor_method).upper()
+
+ @staticmethod
+ def get_access_mode_form(accessor_method):
+ prefix_mode_list = [
+ ('getAndAdd', AccessModeForm.GET_AND_UPDATE_NUMERIC),
+ ('getAndBitwise', AccessModeForm.GET_AND_UPDATE_BITWISE),
+ ('getAndSet', AccessModeForm.GET_AND_SET),
+ ('get', AccessModeForm.GET),
+ ('set', AccessModeForm.SET),
+ ('compareAndSet', AccessModeForm.STRONG_COMPARE_AND_SET),
+ ('weakCompareAndSet', AccessModeForm.WEAK_COMPARE_AND_SET),
+ ('compareAndExchange', AccessModeForm.COMPARE_AND_EXCHANGE)]
+ for prefix, mode in prefix_mode_list:
+ if accessor_method.startswith(prefix):
+ return mode
+ raise ValueError(accessor_method)
+
+VAR_HANDLE_ACCESSORS = [
+ VarHandleAccessor('get'),
+ VarHandleAccessor('set'),
+ VarHandleAccessor('getVolatile'),
+ VarHandleAccessor('setVolatile'),
+ VarHandleAccessor('getAcquire'),
+ VarHandleAccessor('setRelease'),
+ VarHandleAccessor('getOpaque'),
+ VarHandleAccessor('setOpaque'),
+ VarHandleAccessor('compareAndSet'),
+ VarHandleAccessor('compareAndExchange'),
+ VarHandleAccessor('compareAndExchangeAcquire'),
+ VarHandleAccessor('compareAndExchangeRelease'),
+ VarHandleAccessor('weakCompareAndSetPlain'),
+ VarHandleAccessor('weakCompareAndSet'),
+ VarHandleAccessor('weakCompareAndSetAcquire'),
+ VarHandleAccessor('weakCompareAndSetRelease'),
+ VarHandleAccessor('getAndSet'),
+ VarHandleAccessor('getAndSetAcquire'),
+ VarHandleAccessor('getAndSetRelease'),
+ VarHandleAccessor('getAndAdd'),
+ VarHandleAccessor('getAndAddAcquire'),
+ VarHandleAccessor('getAndAddRelease'),
+ VarHandleAccessor('getAndBitwiseOr'),
+ VarHandleAccessor('getAndBitwiseOrRelease'),
+ VarHandleAccessor('getAndBitwiseOrAcquire'),
+ VarHandleAccessor('getAndBitwiseAnd'),
+ VarHandleAccessor('getAndBitwiseAndRelease'),
+ VarHandleAccessor('getAndBitwiseAndAcquire'),
+ VarHandleAccessor('getAndBitwiseXor'),
+ VarHandleAccessor('getAndBitwiseXorRelease'),
+ VarHandleAccessor('getAndBitwiseXorAcquire')
+]
+
+# Pseudo-RNG used for arbitrary decisions
+RANDOM = Random(0)
+
+BANNER = '// This file is generated by util-src/generate_java.py do not directly modify!'
+
+# List of generated test classes
+GENERATED_TEST_CLASSES = []
+
+def java_file_for_class(class_name):
+ return class_name + ".java"
+
+def capitalize_first(word):
+ return word[0].upper() + word[1:]
+
+def indent_code(code):
+ """Applies rudimentary indentation to code"""
+ return code
+
+def build_template_dictionary(test_class, var_handle_kind, accessor, var_type):
+ initial_value = RANDOM.choice(var_type.examples)
+ updated_value = RANDOM.choice(list(filter(lambda v : v != initial_value, var_type.examples)))
+ coordinates = ", ".join(var_handle_kind.get_coordinates())
+ if accessor.get_number_of_var_type_arguments() != 0 and coordinates != "":
+ coordinates += ", "
+ dictionary = {
+ 'accessor_method' : accessor.method_name,
+ 'access_mode' : accessor.access_mode,
+ 'banner' : BANNER,
+ 'coordinates' : coordinates,
+ 'initial_value' : initial_value,
+ 'test_class' : test_class,
+ 'updated_value' : updated_value,
+ 'var_type' : var_type,
+ }
+ dictionary['imports'] = ";\n".join(list(map(lambda x: "import " + x, var_handle_kind.get_imports())))
+ dictionary['lookup'] = var_handle_kind.get_lookup(dictionary)
+ dictionary['field_declarations'] = ";\n".join(var_handle_kind.get_field_declarations(dictionary))
+ dictionary['read_value'] = var_handle_kind.get_value(dictionary)
+ return dictionary
+
+def emit_accessor_test(var_handle_kind, accessor, var_type, output_path):
+ test_class = var_handle_kind.get_name() + capitalize_first(accessor.method_name) + capitalize_first(var_type.name)
+ GENERATED_TEST_CLASSES.append(test_class)
+ src_file_path = output_path / java_file_for_class(test_class)
+ expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type)
+ # Compute test operation
+ if accessor.access_mode_form == AccessModeForm.GET:
+ test_template = Template("""
+ ${var_type} value = (${var_type}) vh.${accessor_method}(${coordinates});
+ assertEquals(${initial_value}, value);""")
+ elif accessor.access_mode_form == AccessModeForm.SET:
+ test_template = Template("""
+ vh.${accessor_method}(${coordinates}${updated_value});
+ assertEquals(${updated_value}, ${read_value});""")
+ elif accessor.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET:
+ test_template = Template("""
+ assertEquals(${initial_value}, ${read_value});
+ // Test an update that should succeed.
+ boolean applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value});
+ assertEquals(${updated_value}, ${read_value});
+ assertTrue(applied);
+ // Test an update that should fail.
+ applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value});
+ assertFalse(applied);
+ assertEquals(${updated_value}, ${read_value});""")
+ elif accessor.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET:
+ test_template = Template("""
+ assertEquals(${initial_value}, ${read_value});
+ // Test an update that should succeed.
+ int attempts = 10000;
+ boolean applied;
+ do {
+ applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value});
+ } while (applied == false && attempts-- > 0);
+ assertEquals(${updated_value}, ${read_value});
+ assertTrue(attempts > 0);
+ // Test an update that should fail.
+ applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value});
+ assertFalse(applied);
+ assertEquals(${updated_value}, ${read_value});""")
+ elif accessor.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE:
+ test_template = Template("""
+ // This update should succeed.
+ ${var_type} witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value});
+ assertEquals(${initial_value}, witness_value);
+ assertEquals(${updated_value}, ${read_value});
+ // This update should fail.
+ witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value});
+ assertEquals(${updated_value}, witness_value);
+ assertEquals(${updated_value}, ${read_value});""")
+ elif accessor.access_mode_form == AccessModeForm.GET_AND_SET:
+ test_template = Template("""
+ ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value});
+ assertEquals(${initial_value}, old_value);
+ assertEquals(${updated_value}, ${read_value});""")
+ elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE:
+ if var_type.supports_bitwise == True:
+ expansions['binop'] = accessor.get_java_bitwise_operator()
+ test_template = Template("""
+ ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value});
+ assertEquals(${initial_value}, old_value);
+ assertEquals(${initial_value} ${binop} ${updated_value}, ${read_value});""")
+ else:
+ test_template = Template("""
+ vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value});
+ failUnreachable();""")
+ elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC:
+ if var_type.supports_numeric == True:
+ expansions['binop'] = accessor.get_java_numeric_operator()
+ test_template = Template("""
+ ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value});
+ assertEquals(${initial_value}, old_value);
+ ${var_type} expected_value = (${var_type}) (${initial_value} ${binop} ${updated_value});
+ assertEquals(expected_value, ${read_value});""")
+ else:
+ test_template = Template("""
+ vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value});
+ failUnreachable();""")
+ else:
+ raise ValueError(accessor.access_mode_form)
+
+ if var_handle_kind.may_throw_read_only and not accessor.is_read_only():
+ # ByteBufferViews can be read-only and dynamically raise ReadOnlyBufferException.
+ expansions['try_statement'] = "try {"
+ expansions['catch_statement'] = "failUnreachable();\n} catch (ReadOnlyBufferException ex) {}"
+ else:
+ expansions['try_statement'] = ""
+ expansions['catch_statement'] = ""
+
+ expansions['test_body'] = test_template.safe_substitute(expansions)
+
+ s = Template("""${banner}
+
+${imports};
+
+class ${test_class} extends VarHandleUnitTest {
+ ${field_declarations};
+ static final VarHandle vh;
+ static {
+ try {
+ vh = ${lookup};
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected initialization exception", e);
+ }
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ if (!vh.isAccessModeSupported(VarHandle.AccessMode.${access_mode})) {
+ try {
+ ${test_body}
+ failUnreachable();
+ } catch (UnsupportedOperationException ex) {}
+ } else {
+ ${try_statement}
+ ${test_body}
+ ${catch_statement}
+ }
+ }
+
+ public static void main(String[] args) {
+ new ${test_class}().run();
+ }
+}
+""").safe_substitute(expansions)
+ with src_file_path.open("w") as src_file:
+ print(s, file=src_file)
+
+def emit_value_type_accessor_tests(output_path):
+ for var_handle_kind in ALL_VAR_HANDLE_KINDS:
+ for accessor in VAR_HANDLE_ACCESSORS:
+ for var_type in var_handle_kind.get_supported_types():
+ emit_accessor_test(var_handle_kind, accessor, var_type, output_path)
+
+def emit_reference_accessor_tests(output_path):
+ ref_type = JavaType("Widget", [ "Widget.ONE", "Widget.TWO", "null" ])
+ for var_handle_kind in ALL_VAR_HANDLE_KINDS:
+ if var_handle_kind.is_view():
+ # Views as reference type arrays are not supported. They
+ # fail instantiation. This is tested in 710-varhandle-creation.
+ continue
+ for accessor in VAR_HANDLE_ACCESSORS:
+ emit_accessor_test(var_handle_kind, accessor, ref_type, output_path)
+
+def emit_boxing_value_type_accessor_test(accessor, var_type, output_path):
+ test_class = "Boxing" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name)
+ GENERATED_TEST_CLASSES.append(test_class)
+ src_file_path = output_path / java_file_for_class(test_class)
+ var_handle_kind = FIELD_VAR_HANDLE
+ expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type)
+ template = Template("""
+${banner}
+
+${imports};
+import java.lang.invoke.WrongMethodTypeException;
+
+public class ${test_class} extends VarHandleUnitTest {
+ ${field_declarations};
+ private static final VarHandle vh;
+ static {
+ try {
+ vh = ${lookup};
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected initialization exception", e);
+ }
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ ${body}
+ }
+
+ public static void main(String[] args) {
+ new ${test_class}().run();
+ }
+}
+""")
+ with io.StringIO() as body_text:
+ compatible_types = types_that_widen_to(var_type)
+ for value_type in VALUE_TYPES:
+ print("try {", file=body_text)
+ return_type = accessor.get_return_type(var_type)
+ if return_type:
+ print("{0} result = ({0}) ".format(return_type), end="", file=body_text)
+ print("vh.{0}(this".format(accessor.method_name), end="", file=body_text)
+ num_args = accessor.get_number_of_var_type_arguments()
+ for i in range(0, num_args):
+ print(", {0}({1})".format(value_type.boxing_method(), value_type.examples[i]), end="", file=body_text)
+ print(");", file=body_text)
+ if value_type in compatible_types:
+ print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode),
+ file=body_text)
+ else:
+ print("failUnreachable();", file=body_text)
+ print("} catch (WrongMethodTypeException e) {", file=body_text)
+ print("} catch (UnsupportedOperationException e) {", file=body_text)
+ print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode),
+ file=body_text)
+ print("}", file=body_text)
+ expansions['body'] = body_text.getvalue();
+ with src_file_path.open("w") as src_file:
+ print(template.safe_substitute(expansions), file=src_file)
+
+def emit_boxing_return_value_type_test(accessor, var_type, output_path):
+ test_class = "BoxingReturn" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name)
+ GENERATED_TEST_CLASSES.append(test_class)
+ src_file_path = output_path / java_file_for_class(test_class)
+ var_handle_kind = FIELD_VAR_HANDLE
+ expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type)
+ template = Template("""
+${banner}
+
+${imports};
+import java.lang.invoke.WrongMethodTypeException;
+
+public class ${test_class} extends VarHandleUnitTest {
+ ${field_declarations};
+ private static final VarHandle vh;
+ static {
+ try {
+ vh = ${lookup};
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected initialization exception", e);
+ }
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ ${body}
+ }
+
+ public static void main(String[] args) {
+ new ${test_class}().run();
+ }
+}
+""")
+ with io.StringIO() as body_text:
+ return_type = accessor.get_return_type(var_type)
+ compatible_types = { return_type }
+ for value_type in VALUE_TYPES:
+ print("try {", file=body_text)
+ print("{0} result = ({0}) ".format(value_type.boxed_type), end="", file=body_text)
+ print("vh.{0}(this".format(accessor.method_name), end="", file=body_text)
+ num_args = accessor.get_number_of_var_type_arguments()
+ for i in range(0, num_args):
+ print(", {0})".format(var_type.examples[i]), end="", file=body_text)
+ print(");", file=body_text)
+ if value_type in compatible_types:
+ print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode),
+ file=body_text)
+ else:
+ print("failUnreachable();", file=body_text)
+ print("} catch (WrongMethodTypeException e) {", file=body_text)
+ print("} catch (UnsupportedOperationException e) {", file=body_text)
+ print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode),
+ file=body_text)
+ print("}", file=body_text)
+ expansions['body'] = body_text.getvalue();
+ with src_file_path.open("w") as src_file:
+ print(template.safe_substitute(expansions), file=src_file)
+
+def emit_boxing_value_type_accessor_tests(output_path):
+ for var_type in VALUE_TYPES:
+ for accessor in VAR_HANDLE_ACCESSORS:
+ if accessor.get_number_of_var_type_arguments() > 0:
+ emit_boxing_value_type_accessor_test(accessor, var_type, output_path)
+ else:
+ emit_boxing_return_value_type_test(accessor, var_type, output_path)
+
+def emit_main(output_path, manual_test_classes):
+ main_file_path = output_path / "Main.java"
+ all_test_classes = GENERATED_TEST_CLASSES + manual_test_classes
+ with main_file_path.open("w") as main_file:
+ print("// " + BANNER, file=main_file)
+ print("""
+public class Main {
+ public static void main(String[] args) {
+""", file=main_file)
+ for cls in all_test_classes:
+ print(" " + cls + ".main(args);", file=main_file)
+ print(" VarHandleUnitTest.DEFAULT_COLLECTOR.printSummary();", file=main_file)
+ print(" System.exit(VarHandleUnitTest.DEFAULT_COLLECTOR.failuresOccurred() ? 1 : 0);", file=main_file)
+ print(" }\n}", file=main_file)
+
+def main(argv):
+ final_java_dir = Path(argv[1])
+ if not final_java_dir.exists() or not final_java_dir.is_dir():
+ print("{} is not a valid java dir".format(final_java_dir), file=sys.stderr)
+ sys.exit(1)
+ emit_value_type_accessor_tests(final_java_dir)
+ emit_reference_accessor_tests(final_java_dir)
+ emit_boxing_value_type_accessor_tests(final_java_dir)
+ emit_main(final_java_dir, argv[2:])
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/714-invoke-custom-lambda-metafactory/expected.txt b/test/714-invoke-custom-lambda-metafactory/expected.txt
index cbe98404c5..54b6c24798 100644
--- a/test/714-invoke-custom-lambda-metafactory/expected.txt
+++ b/test/714-invoke-custom-lambda-metafactory/expected.txt
@@ -2,3 +2,4 @@ Exception in thread "main" java.lang.BootstrapMethodError: Exception from call s
at Main.main(Main.java:25)
Caused by: java.lang.NullPointerException: Bootstrap method returned null
... 1 more
+exit status: 1
diff --git a/test/714-invoke-custom-lambda-metafactory/run b/test/714-invoke-custom-lambda-metafactory/run
new file mode 100755
index 0000000000..7a0d0d05ab
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# Squash the exit status and put it in expected
+./default-run "$@"
+echo "exit status:" $?
diff --git a/test/800-smali/smali/b_22045582.smali b/test/800-smali/smali/b_22045582.smali
index 3cb661a7cb..09ea784b5b 100644
--- a/test/800-smali/smali/b_22045582.smali
+++ b/test/800-smali/smali/b_22045582.smali
@@ -5,7 +5,7 @@
.super Ljava/lang/Object;
-.method public static run()La/b/c/d/e/nonexistant;
+.method public static run()La/b/c/d/e/nonexistent;
.registers 4
# v1 is undefined, and the return type cannot be resolved. The Undefined should take
# precedence here.
diff --git a/test/988-TooDeepClassInstanceOf/expected.txt b/test/805-TooDeepClassInstanceOf/expected.txt
index b0aad4deb5..b0aad4deb5 100644
--- a/test/988-TooDeepClassInstanceOf/expected.txt
+++ b/test/805-TooDeepClassInstanceOf/expected.txt
diff --git a/test/988-TooDeepClassInstanceOf/info.txt b/test/805-TooDeepClassInstanceOf/info.txt
index 390b00d122..390b00d122 100644
--- a/test/988-TooDeepClassInstanceOf/info.txt
+++ b/test/805-TooDeepClassInstanceOf/info.txt
diff --git a/test/988-TooDeepClassInstanceOf/src/Main.java b/test/805-TooDeepClassInstanceOf/src/Main.java
index 93a41e565b..93a41e565b 100644
--- a/test/988-TooDeepClassInstanceOf/src/Main.java
+++ b/test/805-TooDeepClassInstanceOf/src/Main.java
diff --git a/test/988-TooWideClassInstanceOf/expected.txt b/test/806-TooWideClassInstanceOf/expected.txt
index b0aad4deb5..b0aad4deb5 100644
--- a/test/988-TooWideClassInstanceOf/expected.txt
+++ b/test/806-TooWideClassInstanceOf/expected.txt
diff --git a/test/988-TooWideClassInstanceOf/info.txt b/test/806-TooWideClassInstanceOf/info.txt
index 30546fe076..30546fe076 100644
--- a/test/988-TooWideClassInstanceOf/info.txt
+++ b/test/806-TooWideClassInstanceOf/info.txt
diff --git a/test/988-TooWideClassInstanceOf/src/Main.java b/test/806-TooWideClassInstanceOf/src/Main.java
index 332569c104..332569c104 100644
--- a/test/988-TooWideClassInstanceOf/src/Main.java
+++ b/test/806-TooWideClassInstanceOf/src/Main.java
diff --git a/test/911-get-stack-trace/expected_d8.diff b/test/911-get-stack-trace/expected_d8.diff
index 3ce9bedf95..c12015a832 100644
--- a/test/911-get-stack-trace/expected_d8.diff
+++ b/test/911-get-stack-trace/expected_d8.diff
@@ -161,7 +161,7 @@
363c363
< doTest ()V 122 59
---
-> doTest ()V 119 59
+> doTest ()V 120 59
376c376
< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
---
@@ -325,15 +325,15 @@
598c598
< doTest ()V 127 61
---
-> doTest ()V 124 61
+> doTest ()V 125 61
630c630
< doTest ()V 112 54
---
-> doTest ()V 109 54
+> doTest ()V 110 54
677c677
< doTest ()V 117 56
---
-> doTest ()V 114 56
+> doTest ()V 115 56
687c687
< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
---
diff --git a/test/952-invoke-custom-lookup/build b/test/952-invoke-custom-lookup/build
new file mode 100644
index 0000000000..f3fe95c135
--- /dev/null
+++ b/test/952-invoke-custom-lookup/build
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+# make us exit on a failure
+set -e
+
+# This test uses previously prepared dex and jar files. They need to
+# be re-packaged to match the files that the run-test-jar script
+# expects.
+if [[ $@ != *"--jvm"* ]]; then
+ zip ${TEST_NAME}.jar classes.dex
+else
+ unzip -d classes classes.jar
+fi
diff --git a/test/952-invoke-custom-lookup/classes.dex b/test/952-invoke-custom-lookup/classes.dex
new file mode 100644
index 0000000000..670d93dedf
--- /dev/null
+++ b/test/952-invoke-custom-lookup/classes.dex
Binary files differ
diff --git a/test/952-invoke-custom-lookup/classes.jar b/test/952-invoke-custom-lookup/classes.jar
new file mode 100644
index 0000000000..aa6a1f65fa
--- /dev/null
+++ b/test/952-invoke-custom-lookup/classes.jar
Binary files differ
diff --git a/test/952-invoke-custom-lookup/expected.txt b/test/952-invoke-custom-lookup/expected.txt
new file mode 100644
index 0000000000..0da2b866d2
--- /dev/null
+++ b/test/952-invoke-custom-lookup/expected.txt
@@ -0,0 +1,10 @@
+NAME: 1
+CALLER: Main
+CALLER CLASS: class Main
+THIS CLASS: class com.android.tools.r8.maindexlist.desugar.BootstrapHolder
+invokedynamic target on Main
+NAME: 2
+CALLER: Main
+CALLER CLASS: class Main
+THIS CLASS: class com.android.tools.r8.maindexlist.desugar.BootstrapHolder
+invokedynamic target on BootstrapHolder
diff --git a/test/952-invoke-custom-lookup/info.txt b/test/952-invoke-custom-lookup/info.txt
new file mode 100644
index 0000000000..3bfe87dfd3
--- /dev/null
+++ b/test/952-invoke-custom-lookup/info.txt
@@ -0,0 +1 @@
+A temporary test for the lookup class used for invoke-custom (see b/73056094).
diff --git a/test/965-default-verify/src/Iface.java b/test/965-default-verify/src/Iface.java
index 180fba2833..698230a666 100644
--- a/test/965-default-verify/src/Iface.java
+++ b/test/965-default-verify/src/Iface.java
@@ -18,6 +18,6 @@ public interface Iface {
return "Hello";
}
public default void verificationSoftFail() {
- Statics.nonexistantFunction();
+ Statics.nonexistentFunction();
}
}
diff --git a/test/965-default-verify/src/Statics.java b/test/965-default-verify/src/Statics.java
index 2e17ba4174..23a4a01863 100644
--- a/test/965-default-verify/src/Statics.java
+++ b/test/965-default-verify/src/Statics.java
@@ -15,8 +15,7 @@
*/
class Statics {
- public static void nonexistantFunction() {
+ public static void nonexistentFunction() {
System.out.println("I don't exist");
}
}
-
diff --git a/test/965-default-verify/src2/Statics.java b/test/965-default-verify/src2/Statics.java
index 7899ca9c5e..73c5ec6188 100644
--- a/test/965-default-verify/src2/Statics.java
+++ b/test/965-default-verify/src2/Statics.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
class Statics {
- // public static void nonexistantFunction() {
+ // public static void nonexistentFunction() {
// System.out.println("I don't exist");
// }
}
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index dfefce207b..26c5668681 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -19,25 +19,19 @@
#include <cstdio>
#include <cstring>
#include <iostream>
+#include <sstream>
#include <vector>
#include "android-base/stringprintf.h"
#include "jni.h"
#include "jvmti.h"
+#include "scoped_local_ref.h"
-#include "base/macros.h"
-#include "bytecode_utils.h"
#include "dex/code_item_accessors-inl.h"
-#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file_loader.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_instruction.h"
-#include "jit/jit.h"
-#include "native_stack_dump.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
-#include "thread_list.h"
// Test infrastructure
#include "jvmti_helper.h"
@@ -48,9 +42,19 @@ namespace Test983SourceTransformVerify {
constexpr bool kSkipInitialLoad = true;
+static void Println(JNIEnv* env, std::ostringstream msg_stream) {
+ std::string msg = msg_stream.str();
+ ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983"));
+ jmethodID println_method = env->GetStaticMethodID(test_klass.get(),
+ "doPrintln",
+ "(Ljava/lang/String;)V");
+ ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg.c_str()));
+ env->CallStaticVoidMethod(test_klass.get(), println_method, data.get());
+}
+
// The hook we are using.
void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
- JNIEnv* jni_env ATTRIBUTE_UNUSED,
+ JNIEnv* env,
jclass class_being_redefined,
jobject loader ATTRIBUTE_UNUSED,
const char* name,
@@ -60,10 +64,11 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
jint* new_class_data_len ATTRIBUTE_UNUSED,
unsigned char** new_class_data ATTRIBUTE_UNUSED) {
if (kSkipInitialLoad && class_being_redefined == nullptr) {
- // Something got loaded concurrently. Just ignore it for now.
+ // Something got loaded concurrently. Just ignore it for now. To make sure the test is
+ // repeatable we only care about things that come from RetransformClasses.
return;
}
- std::cout << "Dex file hook for " << name << std::endl;
+ Println(env, std::ostringstream() << "Dex file hook for " << name);
if (IsJVM()) {
return;
}
@@ -75,7 +80,7 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
class_data_len = static_cast<jint>(header_file_size);
- const ArtDexFileLoader dex_file_loader;
+ const DexFileLoader dex_file_loader;
std::string error;
std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
class_data_len,
@@ -86,7 +91,8 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
/*verify_checksum*/ true,
&error));
if (dex.get() == nullptr) {
- std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
+ Println(env, std::ostringstream() << "Failed to verify dex file for "
+ << name << " because " << error);
return;
}
for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
@@ -105,9 +111,10 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
(inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
- std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
- << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
- << inst.DumpString(dex.get()) << std::endl;
+ Println(env, std::ostringstream() << "Unexpected instruction found in "
+ << dex->PrettyMethod(it.GetMemberIndex())
+ << " [Dex PC: 0x" << std::hex << pair.DexPc()
+ << std::dec << "] : " << inst.DumpString(dex.get()));
continue;
}
}
@@ -116,22 +123,11 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
}
// Get all capabilities except those related to retransformation.
-jint OnLoad(JavaVM* vm,
- char* options ATTRIBUTE_UNUSED,
- void* reserved ATTRIBUTE_UNUSED) {
- if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
- printf("Unable to get jvmti env!\n");
- return 1;
- }
- SetStandardCapabilities(jvmti_env);
+extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) {
jvmtiEventCallbacks cb;
memset(&cb, 0, sizeof(cb));
cb.ClassFileLoadHook = CheckDexFileHook;
- if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
- printf("Unable to set class file load hook cb!\n");
- return 1;
- }
- return 0;
+ JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
}
} // namespace Test983SourceTransformVerify
diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java
index faae96aef6..7dc47ab06a 100644
--- a/test/983-source-transform-verify/src/art/Test983.java
+++ b/test/983-source-transform-verify/src/art/Test983.java
@@ -27,7 +27,15 @@ public class Test983 {
doTest();
}
+ private native static void setupLoadHook();
+
+ /* called from JNI */
+ public static void doPrintln(String str) {
+ System.out.println(str);
+ }
+
public static void doTest() {
+ setupLoadHook();
Redefinition.enableCommonRetransformation(true);
Redefinition.doCommonClassRetransformation(Transform.class);
Redefinition.doCommonClassRetransformation(Object.class);
diff --git a/test/993-breakpoints/src/art/Breakpoint.java b/test/993-breakpoints/src/art/Breakpoint.java
index 2a370ebd40..bbb89f707f 100644
--- a/test/993-breakpoints/src/art/Breakpoint.java
+++ b/test/993-breakpoints/src/art/Breakpoint.java
@@ -117,7 +117,7 @@ public class Breakpoint {
Thread thr);
public static native void stopBreakpointWatch(Thread thr);
- public static final class LineNumber {
+ public static final class LineNumber implements Comparable<LineNumber> {
public final long location;
public final int line;
diff --git a/test/Android.bp b/test/Android.bp
index 72e8eee95a..25556adf65 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -62,7 +62,7 @@ art_cc_defaults {
"libvixld-arm",
"libvixld-arm64",
"libart-gtest",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libicuuc",
@@ -114,7 +114,7 @@ art_cc_defaults {
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
],
static_libs: [
"libgtest",
@@ -151,7 +151,7 @@ art_cc_library {
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libbacktrace",
],
@@ -238,6 +238,7 @@ art_cc_defaults {
"931-agent-thread/agent_thread.cc",
"933-misc-events/misc_events.cc",
"945-obsolete-native/obsolete_native.cc",
+ "983-source-transform-verify/source_transform.cc",
"984-obsolete-invoke/obsolete_invoke.cc",
"986-native-method-bind/native_bind.cc",
"987-agent-bind/agent_bind.cc",
@@ -267,12 +268,8 @@ art_cc_defaults {
"1942-suspend-raw-monitor-exit/native_suspend_monitor.cc",
"1943-suspend-raw-monitor-wait/native_suspend_monitor.cc",
],
- shared_libs: [
- "libdexfile",
- "libbase",
- ],
header_libs: [
- "libnativehelper_header_only",
+ "jni_headers",
"libopenjdkjvmti_headers",
],
include_dirs: ["art/test/ti-agent"],
@@ -292,15 +289,21 @@ art_cc_defaults {
"909-attach-agent/attach.cc",
"912-classes/classes_art.cc",
"936-search-onload/search_onload.cc",
- "983-source-transform-verify/source_transform.cc",
"1940-ddms-ext/ddm_ext.cc",
+ "1944-sudden-exit/sudden_exit.cc",
+ ],
+ shared_libs: [
+ "libbase",
],
}
art_cc_test_library {
name: "libtiagent",
defaults: ["libtiagent-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -309,7 +312,36 @@ art_cc_test_library {
"art_debug_defaults",
"libtiagent-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
+}
+
+art_cc_test_library {
+ name: "libctstiagent",
+ defaults: ["libtiagent-base-defaults"],
+ whole_static_libs: [
+ "libdexfile",
+ "libz",
+ "libziparchive",
+ ],
+ static_libs: [
+ "libbase",
+ "libcutils",
+ "libutils",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ header_libs: [
+ // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are
+ // many problems with how we export headers that are making doing this the 'right' way
+ // difficult.
+ // TODO: move those headers to art/ rather than under runtime.
+ "libart_runtime_headers",
+ ],
+ export_include_dirs: ["ti-agent"],
}
art_cc_defaults {
@@ -340,12 +372,6 @@ art_cc_test_library {
shared_libs: ["libartd"],
}
-art_cc_test_library {
- name: "libctstiagent",
- defaults: ["libtiagent-base-defaults"],
- export_include_dirs: ["ti-agent"],
-}
-
cc_defaults {
name: "libarttest-defaults",
defaults: [
@@ -399,7 +425,6 @@ cc_defaults {
"708-jit-cache-churn/jit.cc",
],
shared_libs: [
- "libdexfile",
"libbacktrace",
"libbase",
"libnativehelper",
@@ -409,7 +434,10 @@ cc_defaults {
art_cc_test_library {
name: "libarttest",
defaults: ["libarttest-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -418,7 +446,10 @@ art_cc_test_library {
"art_debug_defaults",
"libarttest-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
art_cc_test_library {
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 2df0cc6fae..464449c752 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -32,11 +32,6 @@ TEST_ART_RUN_TEST_DEPENDENCIES += \
$(HOST_OUT_EXECUTABLES)/d8-compat-dx
endif
-# Convert's a rule name to the form used in variables, e.g. no-relocate to NO_RELOCATE
-define name-to-var
-$(shell echo $(1) | tr '[:lower:]' '[:upper:]' | tr '-' '_')
-endef # name-to-var
-
# We need dex2oat and dalvikvm on the target as well as the core images (all images as we sync
# only once).
TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_EXECUTABLES) $(TARGET_CORE_IMG_OUTS)
@@ -124,13 +119,13 @@ define core-image-dependencies
endif
endif
ifeq ($(2),no-image)
- $(1)_prereq_rules += $$($(call name-to-var,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
+ $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
else
ifeq ($(2),picimage)
- $(1)_prereq_rules += $$($(call name-to-var,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
+ $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
else
ifeq ($(2),multipicimage)
- $(1)_prereq_rules += $$($(call name-to-var,$(1))_CORE_IMAGE_$$(image_suffix)_multi_$(4))
+ $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_multi_$(4))
endif
endif
endif
@@ -174,7 +169,6 @@ test-art-run-test : test-art-host-run-test test-art-target-run-test
host_prereq_rules :=
target_prereq_rules :=
core-image-dependencies :=
-name-to-var :=
define-test-art-host-or-target-run-test-group :=
TARGET_TYPES :=
COMPILER_TYPES :=
diff --git a/test/etc/default-build b/test/etc/default-build
index 4dc2393c54..6040f7d910 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -124,18 +124,20 @@ JACK_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-D jack.java.source.version=1.8 -
declare -A SMALI_EXPERIMENTAL_ARGS
SMALI_EXPERIMENTAL_ARGS["default-methods"]="--api 24"
SMALI_EXPERIMENTAL_ARGS["method-handles"]="--api 26"
+SMALI_EXPERIMENTAL_ARGS["var-handles"]="--api 26"
SMALI_EXPERIMENTAL_ARGS["agents"]="--api 26"
declare -A JAVAC_EXPERIMENTAL_ARGS
JAVAC_EXPERIMENTAL_ARGS["default-methods"]="-source 1.8 -target 1.8"
JAVAC_EXPERIMENTAL_ARGS["lambdas"]="-source 1.8 -target 1.8"
JAVAC_EXPERIMENTAL_ARGS["method-handles"]="-source 1.8 -target 1.8"
-# We need to leave javac at default 1.7 so that dx will continue to work
+JAVAC_EXPERIMENTAL_ARGS["var-handles"]="-source 1.8 -target 1.8"
JAVAC_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-source 1.8 -target 1.8"
JAVAC_EXPERIMENTAL_ARGS["agents"]="-source 1.8 -target 1.8"
declare -A DX_EXPERIMENTAL_ARGS
DX_EXPERIMENTAL_ARGS["method-handles"]="--min-sdk-version=26"
+DX_EXPERIMENTAL_ARGS["var-handles"]="--min-sdk-version=26"
while true; do
if [ "x$1" = "x--dx-option" ]; then
@@ -441,7 +443,7 @@ else
if [ "${HAS_SRC2}" = "true" ]; then
mkdir -p classes
- ${JAVAC} ${JAVAC_ARGS} -d classes `find src2 -name '*.java'`
+ ${JAVAC} ${JAVAC_ARGS} -classpath classes -d classes `find src2 -name '*.java'`
fi
if [[ "${HAS_SRC}" == "true" || "${HAS_SRC2}" == "true" || "${HAS_SRC_ART}" == "true" ]]; then
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 02438701b8..b8427f491b 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -570,7 +570,7 @@ if [ "$HAVE_IMAGE" = "n" ]; then
if [ "${RELOCATE}" = "y" ] ; then
DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
else
- DALVIKVM_BOOT_OPT="-Ximage:/system/non-existant/core.art"
+ DALVIKVM_BOOT_OPT="-Ximage:/system/non-existent/core.art"
fi
else
DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
@@ -667,7 +667,8 @@ fi
if [ "$HOST" = "y" ]; then
max_filename_size=$(getconf NAME_MAX $DEX_LOCATION)
else
- # There is no getconf on device, fallback to standard value. See NAME_MAX in kernel <linux/limits.h>
+ # There is no getconf on device, fallback to standard value.
+ # See NAME_MAX in kernel <linux/limits.h>
max_filename_size=255
fi
# Compute VDEX_NAME.
@@ -849,7 +850,7 @@ if [ "$HOST" = "n" ]; then
fi
# System libraries needed by libarttestd.so
- PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so
+ PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so
# Create a script with the command. The command can get longer than the longest
# allowed adb command and there is no way to get the exit status from a adb shell
@@ -886,11 +887,14 @@ if [ "$HOST" = "n" ]; then
adb push $cmdfile $DEX_LOCATION/cmdline.sh > /dev/null 2>&1
fi
+ exit_status=0
if [ "$DRY_RUN" != "y" ]; then
adb shell sh $DEX_LOCATION/cmdline.sh
+ exit_status=$?
fi
rm -f $cmdfile
+ exit $exit_status
else
# Host run.
export ANDROID_PRINTF_LOG=brief
@@ -996,10 +1000,12 @@ else
trap 'kill -INT -$pid' INT
$cmdline "$@" 2>&1 & pid=$!
wait $pid
+ exit_value=$?
# Add extra detail if time out is enabled.
- if [ ${PIPESTATUS[0]} = 124 ] && [ "$TIME_OUT" = "timeout" ]; then
+ if [ $exit_value = 124 ] && [ "$TIME_OUT" = "timeout" ]; then
echo -e "\e[91mTEST TIMED OUT!\e[0m" >&2
fi
+ exit $exit_value
else
# With a thread dump that uses gdb if a timeout.
trap 'kill -INT -$pid' INT
@@ -1022,6 +1028,7 @@ else
# The test timed out.
echo -e "\e[91mTEST TIMED OUT!\e[0m" >&2
fi
+ exit $test_exit_status
fi
fi
fi
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 2b28409a1f..b483b93e19 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1,12 +1,5 @@
[
{
- "tests": [ "1939-proxy-frames", "1914-get-local-instance" ],
- "description": ["Test 1939 & 1914 seems to consistently fail in gcstress on 64 bit with",
- "a proxy this object having no associated class!"],
- "variant": "gcstress",
- "bug": "http://b/67679263"
- },
- {
"tests": "1934-jvmti-signal-thread",
"description": ["Disables 1934-jvmti-signal-thread in tracing configurations"],
"variant": "trace | stream",
@@ -660,8 +653,25 @@
"description": ["Test is designed to only check --compiler-filter=speed"]
},
{
+ "test_patterns": [".*"],
+ "description": ["Tests are timing out for weeks now, disable to fix."],
+ "variant": "cdex-fast & redefine-stress"
+ },
+ {
"tests": "674-HelloWorld-Dm",
"variant": "target",
"description": ["Requires zip, which isn't available on device"]
+ },
+ {
+ "tests": "712-varhandle-invocations",
+ "variant": "speed-profile & debug & gcstress & target",
+ "bug": "b/73275005",
+ "description": ["Time out"]
+ },
+ {
+ "tests": ["130-hprof"],
+ "env_vars": {"SANITIZE_HOST": "address"},
+ "bug": "b/73060923",
+ "description": ["ASAN issue"]
}
]
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 9a7352e479..bfd165db10 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -28,7 +28,6 @@
#include "901-hello-ti-agent/basics.h"
#include "909-attach-agent/attach.h"
#include "936-search-onload/search_onload.h"
-#include "983-source-transform-verify/source_transform.h"
#include "1919-vminit-thread-start-timing/vminit.h"
namespace art {
@@ -83,7 +82,6 @@ static AgentLib agents[] = {
{ "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr },
{ "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr },
{ "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
- { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr },
{ "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr },
};
diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp
index 57c9c095f8..f3342d39f6 100644
--- a/tools/cpp-define-generator/Android.bp
+++ b/tools/cpp-define-generator/Android.bp
@@ -28,7 +28,10 @@ cc_binary { // Do not use art_cc_binary because HOST_PREFER_32_BIT is incompatib
"art_debug_defaults",
"art_defaults",
],
- include_dirs: ["art/runtime"],
+ include_dirs: [
+ "art/libdexfile",
+ "art/runtime",
+ ],
srcs: ["main.cc"],
shared_libs: [
"libbase",
diff --git a/tools/external_oj_libjdwp_art_failures.txt b/tools/external_oj_libjdwp_art_failures.txt
index 828c0aac0f..6c2206fe46 100644
--- a/tools/external_oj_libjdwp_art_failures.txt
+++ b/tools/external_oj_libjdwp_art_failures.txt
@@ -53,25 +53,6 @@
"org.apache.harmony.jpda.tests.jdwp.VirtualMachine.CapabilitiesNewTest#testCapabilitiesNew001" ]
},
{
- description: "Test is flaky",
- result: EXEC_FAILED,
- bug: 69121056,
- name: "org.apache.harmony.jpda.tests.jdwp.ObjectReference.IsCollectedTest#testIsCollected001"
-},
-{
- description: "Test is flaky",
- result: EXEC_FAILED,
- bug: 70958370,
- names: [ "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection001",
- "org.apache.harmony.jpda.tests.jdwp.MultiSession.EnableCollectionTest#testEnableCollection001" ]
-},
-{
- description: "Test crashes",
- result: EXEC_FAILED,
- bug: 69591477,
- name: "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ExitTest#testExit001"
-},
-{
description: "Test times out on fugu-debug",
result: EXEC_FAILED,
bug: 70459916,
diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp
index f9824f1fa3..af87d31e53 100644
--- a/tools/hiddenapi/Android.bp
+++ b/tools/hiddenapi/Android.bp
@@ -30,7 +30,6 @@ cc_defaults {
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -40,6 +39,7 @@ art_cc_binary {
defaults: ["hiddenapi-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -51,6 +51,7 @@ art_cc_binary {
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/tools/prebuilt_libjdwp_art_failures.txt b/tools/prebuilt_libjdwp_art_failures.txt
index a9d268de0a..2664560455 100644
--- a/tools/prebuilt_libjdwp_art_failures.txt
+++ b/tools/prebuilt_libjdwp_art_failures.txt
@@ -102,28 +102,9 @@
"org.apache.harmony.jpda.tests.jdwp.VirtualMachine.CapabilitiesNewTest#testCapabilitiesNew001" ]
},
{
- description: "Test is flaky",
- result: EXEC_FAILED,
- bug: 69121056,
- name: "org.apache.harmony.jpda.tests.jdwp.ObjectReference.IsCollectedTest#testIsCollected001"
-},
-{
description: "Test for ddms extensions that are not implemented for prebuilt-libjdwp",
result: EXEC_FAILED,
bug: 69169846,
name: "org.apache.harmony.jpda.tests.jdwp.DDM.DDMTest#testChunk001"
},
-{
- description: "Test is flakey",
- result: EXEC_FAILED,
- bug: 70958370,
- names: [ "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection001",
- "org.apache.harmony.jpda.tests.jdwp.MultiSession.EnableCollectionTest#testEnableCollection001" ]
-},
-{
- description: "Test crashes",
- result: EXEC_FAILED,
- bug: 69591477,
- name: "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ExitTest#testExit001"
-}
]
diff --git a/tools/public.libraries.buildbot.txt b/tools/public.libraries.buildbot.txt
index 734fd1e50b..de636a813a 100644
--- a/tools/public.libraries.buildbot.txt
+++ b/tools/public.libraries.buildbot.txt
@@ -1,6 +1,7 @@
libart.so
libartd.so
libdexfile.so
+libdexfiled.so
libbacktrace.so
libc.so
libc++.so
diff --git a/tools/titrace/Android.bp b/tools/titrace/Android.bp
index 097622e756..21f266c087 100644
--- a/tools/titrace/Android.bp
+++ b/tools/titrace/Android.bp
@@ -40,9 +40,8 @@ cc_defaults {
},
header_libs: [
"libopenjdkjvmti_headers",
- "libart_runtime_headers", // for dex_instruction_list.h only
- // "libbase_headers",
],
+ include_dirs: ["art/libdexfile"], // for dex_instruction_list.h only
multilib: {
lib32: {
suffix: "32",