summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-20 02:22:07 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-20 02:22:07 +0000
commit3b42b7471a9043306321139c9b7ae31e916280c8 (patch)
tree6f801c8690ed6e4e8736781568c8ba029825f95a
parent0bd302a69360d088c60b62e199712d9d178a3d76 (diff)
parent16f474294d94a8a3d032d2ad706d7299fb6f490e (diff)
downloadart-android-u-qpr3-beta-1-gpl.tar.gz
Snap for 11335836 from 16f474294d94a8a3d032d2ad706d7299fb6f490e to 24Q2-beta-releaseandroid-u-qpr3-beta-1-gplandroid-u-qpr3-beta-1-gpl
Change-Id: I3bab9b05878119523e57bac0eb063bbcf9165674
-rw-r--r--OWNERS_boot_profile4
-rw-r--r--build/boot/Android.bp49
-rw-r--r--compiler/jit/jit_compiler.cc4
-rw-r--r--compiler/jit/jit_compiler.h2
-rw-r--r--compiler/optimizing/code_generator_arm64.cc26
-rw-r--r--compiler/optimizing/code_generator_arm64.h2
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc21
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h2
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc24
-rw-r--r--compiler/optimizing/code_generator_riscv64.h6
-rw-r--r--compiler/optimizing/code_generator_x86.cc26
-rw-r--r--compiler/optimizing/code_generator_x86.h2
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc24
-rw-r--r--compiler/optimizing/code_generator_x86_64.h2
-rw-r--r--compiler/optimizing/constant_folding.cc20
-rw-r--r--compiler/optimizing/constant_folding.h8
-rw-r--r--compiler/optimizing/constant_folding_test.cc4
-rw-r--r--compiler/optimizing/graph_visualizer.cc3
-rw-r--r--compiler/optimizing/inliner.cc68
-rw-r--r--compiler/optimizing/inliner.h12
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc721
-rw-r--r--compiler/optimizing/intrinsics_riscv64.cc290
-rw-r--r--compiler/optimizing/intrinsics_x86.cc1
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc1
-rw-r--r--compiler/optimizing/load_store_elimination.cc63
-rw-r--r--compiler/optimizing/nodes.cc41
-rw-r--r--compiler/optimizing/optimization.cc6
-rw-r--r--compiler/optimizing/optimization.h1
-rw-r--r--compiler/optimizing/optimizing_compiler.cc38
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h3
-rw-r--r--compiler/optimizing/profiling_info_builder.cc59
-rw-r--r--compiler/optimizing/profiling_info_builder.h10
-rw-r--r--libartbase/base/atomic.h8
-rw-r--r--libartservice/service/api/system-server-current.txt6
-rw-r--r--libartservice/service/java/com/android/server/art/ArtFileManager.java28
-rw-r--r--libartservice/service/java/com/android/server/art/ArtManagerLocal.java88
-rw-r--r--libartservice/service/java/com/android/server/art/DexUseManagerLocal.java62
-rw-r--r--libartservice/service/java/com/android/server/art/DexoptHelper.java6
-rw-r--r--libartservice/service/java/com/android/server/art/Dexopter.java25
-rw-r--r--libartservice/service/java/com/android/server/art/DumpHelper.java28
-rw-r--r--libartservice/service/java/com/android/server/art/PrimaryDexopter.java9
-rw-r--r--libartservice/service/java/com/android/server/art/SecondaryDexopter.java43
-rw-r--r--libartservice/service/java/com/android/server/art/Utils.java5
-rw-r--r--libartservice/service/java/com/android/server/art/model/Config.java24
-rw-r--r--libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java18
-rw-r--r--libartservice/service/javatests/com/android/server/art/DexUseManagerTest.java102
-rw-r--r--libartservice/service/javatests/com/android/server/art/DumpHelperTest.java18
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java48
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java16
-rw-r--r--libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java33
-rw-r--r--runtime/aot_class_linker.cc2
-rw-r--r--runtime/aot_class_linker.h7
-rw-r--r--runtime/app_info.cc2
-rw-r--r--runtime/app_info.h3
-rw-r--r--runtime/app_info_test.cc2
-rw-r--r--runtime/art_field-inl.h2
-rw-r--r--runtime/art_field.cc2
-rw-r--r--runtime/art_field.h5
-rw-r--r--runtime/art_method-alloc-inl.h2
-rw-r--r--runtime/art_method-inl.h2
-rw-r--r--runtime/art_method.cc2
-rw-r--r--runtime/art_method.h4
-rw-r--r--runtime/art_method_test.cc2
-rw-r--r--runtime/backtrace_helper.cc2
-rw-r--r--runtime/backtrace_helper.h4
-rw-r--r--runtime/barrier.cc2
-rw-r--r--runtime/barrier.h13
-rw-r--r--runtime/barrier_test.cc2
-rw-r--r--runtime/debug_print.cc2
-rw-r--r--runtime/debug_print.h5
-rw-r--r--runtime/debugger.cc2
-rw-r--r--runtime/debugger.h24
-rw-r--r--runtime/deoptimization_kind.h3
-rw-r--r--runtime/dex/dex_file_annotations.cc2
-rw-r--r--runtime/dex/dex_file_annotations.h24
-rw-r--r--runtime/dex2oat_environment_test.h3
-rw-r--r--runtime/dex_reference_collection.h2
-rw-r--r--runtime/dex_register_location.cc2
-rw-r--r--runtime/dex_register_location.h5
-rw-r--r--runtime/dexopt_test.cc2
-rw-r--r--runtime/dexopt_test.h3
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h2
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc2
-rw-r--r--runtime/entrypoints/entrypoint_utils.h2
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.cc2
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.h2
-rw-r--r--runtime/entrypoints/math_entrypoints.cc2
-rw-r--r--runtime/entrypoints/math_entrypoints_test.cc2
-rw-r--r--runtime/entrypoints/quick/callee_save_frame.h2
-rw-r--r--runtime/entrypoints/quick/quick_alloc_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_alloc_entrypoints.h2
-rw-r--r--runtime/entrypoints/quick/quick_cast_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_default_externs.h2
-rw-r--r--runtime/entrypoints/quick/quick_default_init_entrypoints.h2
-rw-r--r--runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints.h2
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints_enum.cc2
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints_enum.h2
-rw-r--r--runtime/entrypoints/quick/quick_field_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_fillarray_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_lock_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_string_builder_append_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_thread_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_throw_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc7
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc2
-rw-r--r--runtime/gc/allocation_listener.h2
-rw-r--r--runtime/gc/allocation_record.cc2
-rw-r--r--runtime/gc/allocation_record.h10
-rw-r--r--runtime/gc/allocator/art-dlmalloc.cc48
-rw-r--r--runtime/gc/allocator/art-dlmalloc.h22
-rw-r--r--runtime/gc/allocator_type.h4
-rw-r--r--runtime/gc/collector/concurrent_copying-inl.h2
-rw-r--r--runtime/gc/collector/concurrent_copying.cc2
-rw-r--r--runtime/gc/collector/concurrent_copying.h37
-rw-r--r--runtime/gc/collector/garbage_collector.cc2
-rw-r--r--runtime/gc/collector/garbage_collector.h3
-rw-r--r--runtime/gc/collector/gc_type.h4
-rw-r--r--runtime/gc/collector/immune_region.cc2
-rw-r--r--runtime/gc/collector/immune_region.h2
-rw-r--r--runtime/gc/collector/immune_spaces.cc2
-rw-r--r--runtime/gc/collector/immune_spaces.h2
-rw-r--r--runtime/gc/collector/immune_spaces_test.cc2
-rw-r--r--runtime/gc/collector/iteration.h3
-rw-r--r--runtime/gc/collector/mark_compact-inl.h2
-rw-r--r--runtime/gc/collector/mark_compact.cc2
-rw-r--r--runtime/gc/collector/mark_compact.h4
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h2
-rw-r--r--runtime/gc/collector/mark_sweep.cc2
-rw-r--r--runtime/gc/collector/mark_sweep.h2
-rw-r--r--runtime/gc/collector/object_byte_pair.h4
-rw-r--r--runtime/gc/collector/partial_mark_sweep.cc2
-rw-r--r--runtime/gc/collector/partial_mark_sweep.h4
-rw-r--r--runtime/gc/collector/semi_space-inl.h2
-rw-r--r--runtime/gc/collector/semi_space.cc2
-rw-r--r--runtime/gc/collector/semi_space.h2
-rw-r--r--runtime/gc/collector/sticky_mark_sweep.cc2
-rw-r--r--runtime/gc/collector/sticky_mark_sweep.h2
-rw-r--r--runtime/gc/collector_type.h4
-rw-r--r--runtime/gc/gc_cause.cc2
-rw-r--r--runtime/gc/gc_cause.h4
-rw-r--r--runtime/gc/gc_pause_listener.h4
-rw-r--r--runtime/gc/heap-inl.h2
-rw-r--r--runtime/gc/heap-visit-objects-inl.h2
-rw-r--r--runtime/gc/heap.cc2
-rw-r--r--runtime/gc/heap.h115
-rw-r--r--runtime/gc/heap_test.cc2
-rw-r--r--runtime/gc/heap_verification_test.cc2
-rw-r--r--runtime/gc/reference_processor.cc2
-rw-r--r--runtime/gc/reference_processor.h3
-rw-r--r--runtime/gc/reference_queue.cc2
-rw-r--r--runtime/gc/reference_queue.h3
-rw-r--r--runtime/gc/reference_queue_test.cc2
-rw-r--r--runtime/gc/scoped_gc_critical_section.cc2
-rw-r--r--runtime/gc/scoped_gc_critical_section.h11
-rw-r--r--runtime/gc/space/bump_pointer_space-inl.h2
-rw-r--r--runtime/gc/space/bump_pointer_space-walk-inl.h2
-rw-r--r--runtime/gc/space/bump_pointer_space.cc2
-rw-r--r--runtime/gc/space/bump_pointer_space.h4
-rw-r--r--runtime/gc/space/dlmalloc_space-inl.h2
-rw-r--r--runtime/gc/space/dlmalloc_space.cc52
-rw-r--r--runtime/gc/space/dlmalloc_space.h10
-rw-r--r--runtime/gc/space/dlmalloc_space_random_test.cc2
-rw-r--r--runtime/gc/space/dlmalloc_space_static_test.cc2
-rw-r--r--runtime/gc/space/image_space.cc2
-rw-r--r--runtime/gc/space/image_space.h16
-rw-r--r--runtime/gc/space/image_space_test.cc2
-rw-r--r--runtime/gc/space/large_object_space.cc2
-rw-r--r--runtime/gc/space/large_object_space.h2
-rw-r--r--runtime/gc/space/large_object_space_test.cc2
-rw-r--r--runtime/gc/space/malloc_space.cc2
-rw-r--r--runtime/gc/space/malloc_space.h2
-rw-r--r--runtime/gc/space/memory_tool_malloc_space-inl.h2
-rw-r--r--runtime/gc/space/memory_tool_malloc_space.h2
-rw-r--r--runtime/gc/space/memory_tool_settings.h2
-rw-r--r--runtime/gc/space/region_space-inl.h2
-rw-r--r--runtime/gc/space/region_space.cc2
-rw-r--r--runtime/gc/space/region_space.h24
-rw-r--r--runtime/gc/space/rosalloc_space-inl.h2
-rw-r--r--runtime/gc/space/rosalloc_space.cc2
-rw-r--r--runtime/gc/space/rosalloc_space.h2
-rw-r--r--runtime/gc/space/rosalloc_space_random_test.cc2
-rw-r--r--runtime/gc/space/rosalloc_space_static_test.cc2
-rw-r--r--runtime/gc/space/space-inl.h2
-rw-r--r--runtime/gc/space/space.cc2
-rw-r--r--runtime/gc/space/space.h4
-rw-r--r--runtime/gc/space/space_create_test.cc2
-rw-r--r--runtime/gc/space/space_test.h2
-rw-r--r--runtime/gc/space/zygote_space.cc2
-rw-r--r--runtime/gc/space/zygote_space.h2
-rw-r--r--runtime/gc/system_weak.h3
-rw-r--r--runtime/gc/system_weak_test.cc2
-rw-r--r--runtime/gc/task_processor.cc2
-rw-r--r--runtime/gc/task_processor.h3
-rw-r--r--runtime/gc/task_processor_test.cc2
-rw-r--r--runtime/gc/verification-inl.h2
-rw-r--r--runtime/gc/verification.cc2
-rw-r--r--runtime/gc/verification.h13
-rw-r--r--runtime/gc/weak_root_state.h4
-rw-r--r--runtime/gc_root-inl.h2
-rw-r--r--runtime/gc_root.h4
-rw-r--r--runtime/interpreter/interpreter.cc2
-rw-r--r--runtime/interpreter/interpreter.h3
-rw-r--r--runtime/interpreter/interpreter_cache-inl.h2
-rw-r--r--runtime/interpreter/interpreter_cache.cc2
-rw-r--r--runtime/interpreter/interpreter_cache.h4
-rw-r--r--runtime/interpreter/interpreter_common.cc2
-rw-r--r--runtime/interpreter/interpreter_common.h2
-rw-r--r--runtime/interpreter/interpreter_switch_impl-inl.h2
-rw-r--r--runtime/interpreter/interpreter_switch_impl.h2
-rw-r--r--runtime/interpreter/interpreter_switch_impl0.cc2
-rw-r--r--runtime/interpreter/interpreter_switch_impl1.cc2
-rw-r--r--runtime/interpreter/lock_count_data.cc2
-rw-r--r--runtime/interpreter/lock_count_data.h3
-rw-r--r--runtime/interpreter/mterp/nterp.cc2
-rw-r--r--runtime/interpreter/mterp/nterp.h3
-rw-r--r--runtime/interpreter/safe_math.h4
-rw-r--r--runtime/interpreter/safe_math_test.cc2
-rw-r--r--runtime/interpreter/shadow_frame-inl.h2
-rw-r--r--runtime/interpreter/shadow_frame.cc2
-rw-r--r--runtime/interpreter/shadow_frame.h2
-rw-r--r--runtime/interpreter/unstarted_runtime.cc2
-rw-r--r--runtime/interpreter/unstarted_runtime.h5
-rw-r--r--runtime/interpreter/unstarted_runtime_test.cc2
-rw-r--r--runtime/jit/debugger_interface.cc8
-rw-r--r--runtime/jit/debugger_interface.h4
-rw-r--r--runtime/jit/jit-inl.h2
-rw-r--r--runtime/jit/jit.cc2
-rw-r--r--runtime/jit/jit.h25
-rw-r--r--runtime/jit/jit_code_cache.cc2
-rw-r--r--runtime/jit/jit_code_cache.h30
-rw-r--r--runtime/jit/jit_memory_region.cc2
-rw-r--r--runtime/jit/jit_memory_region.h2
-rw-r--r--runtime/jit/jit_memory_region_test.cc2
-rw-r--r--runtime/jit/jit_scoped_code_cache_write.h2
-rw-r--r--runtime/jit/profile_saver.cc2
-rw-r--r--runtime/jit/profile_saver.h4
-rw-r--r--runtime/jit/profile_saver_options.h2
-rw-r--r--runtime/jit/profile_saver_test.cc2
-rw-r--r--runtime/jit/profiling_info.cc40
-rw-r--r--runtime/jit/profiling_info.h21
-rw-r--r--runtime/jit/profiling_info_test.cc2
-rw-r--r--runtime/jni/check_jni.cc2
-rw-r--r--runtime/jni/check_jni.h4
-rw-r--r--runtime/jni/java_vm_ext-inl.h2
-rw-r--r--runtime/jni/java_vm_ext.cc8
-rw-r--r--runtime/jni/java_vm_ext.h31
-rw-r--r--runtime/jni/java_vm_ext_test.cc2
-rw-r--r--runtime/jni/jni_env_ext-inl.h11
-rw-r--r--runtime/jni/jni_env_ext.cc2
-rw-r--r--runtime/jni/jni_env_ext.h10
-rw-r--r--runtime/jni/jni_id_manager.cc2
-rw-r--r--runtime/jni/jni_id_manager.h18
-rw-r--r--runtime/jni/jni_internal.cc2
-rw-r--r--runtime/jni/jni_internal.h4
-rw-r--r--runtime/jni/jni_internal_test.cc2
-rw-r--r--runtime/jni/local_reference_table-inl.h2
-rw-r--r--runtime/jni/local_reference_table.cc2
-rw-r--r--runtime/jni/local_reference_table.h7
-rw-r--r--runtime/jni/local_reference_table_test.cc2
-rw-r--r--runtime/metrics/statsd.cc7
-rw-r--r--runtime/native/dalvik_system_BaseDexClassLoader.cc2
-rw-r--r--runtime/native/dalvik_system_BaseDexClassLoader.h4
-rw-r--r--runtime/native/dalvik_system_DexFile.cc2
-rw-r--r--runtime/native/dalvik_system_DexFile.h4
-rw-r--r--runtime/native/dalvik_system_VMDebug.cc2
-rw-r--r--runtime/native/dalvik_system_VMDebug.h4
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc2
-rw-r--r--runtime/native/dalvik_system_VMRuntime.h4
-rw-r--r--runtime/native/dalvik_system_VMStack.cc2
-rw-r--r--runtime/native/dalvik_system_VMStack.h4
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc2
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.h4
-rw-r--r--runtime/native/java_lang_Class.cc2
-rw-r--r--runtime/native/java_lang_Class.h4
-rw-r--r--runtime/native/java_lang_Object.cc2
-rw-r--r--runtime/native/java_lang_Object.h4
-rw-r--r--runtime/native/java_lang_StackStreamFactory.cc2
-rw-r--r--runtime/native/java_lang_StackStreamFactory.h4
-rw-r--r--runtime/native/java_lang_String.cc2
-rw-r--r--runtime/native/java_lang_String.h4
-rw-r--r--runtime/native/java_lang_StringFactory.cc2
-rw-r--r--runtime/native/java_lang_StringFactory.h4
-rw-r--r--runtime/native/java_lang_System.cc2
-rw-r--r--runtime/native/java_lang_System.h4
-rw-r--r--runtime/native/java_lang_Thread.cc2
-rw-r--r--runtime/native/java_lang_Thread.h4
-rw-r--r--runtime/native/java_lang_Throwable.cc2
-rw-r--r--runtime/native/java_lang_Throwable.h4
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc2
-rw-r--r--runtime/native/java_lang_VMClassLoader.h4
-rw-r--r--runtime/native/java_lang_invoke_MethodHandle.cc2
-rw-r--r--runtime/native/java_lang_invoke_MethodHandle.h4
-rw-r--r--runtime/native/java_lang_invoke_MethodHandleImpl.cc2
-rw-r--r--runtime/native/java_lang_invoke_MethodHandleImpl.h4
-rw-r--r--runtime/native/java_lang_ref_FinalizerReference.cc2
-rw-r--r--runtime/native/java_lang_ref_FinalizerReference.h4
-rw-r--r--runtime/native/java_lang_ref_Reference.cc2
-rw-r--r--runtime/native/java_lang_ref_Reference.h4
-rw-r--r--runtime/native/java_lang_reflect_Array.cc2
-rw-r--r--runtime/native/java_lang_reflect_Array.h4
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc2
-rw-r--r--runtime/native/java_lang_reflect_Constructor.h4
-rw-r--r--runtime/native/java_lang_reflect_Executable.cc2
-rw-r--r--runtime/native/java_lang_reflect_Executable.h4
-rw-r--r--runtime/native/java_lang_reflect_Field.cc2
-rw-r--r--runtime/native/java_lang_reflect_Field.h4
-rw-r--r--runtime/native/java_lang_reflect_Method.cc2
-rw-r--r--runtime/native/java_lang_reflect_Method.h4
-rw-r--r--runtime/native/java_lang_reflect_Parameter.cc2
-rw-r--r--runtime/native/java_lang_reflect_Parameter.h4
-rw-r--r--runtime/native/java_lang_reflect_Proxy.cc2
-rw-r--r--runtime/native/java_lang_reflect_Proxy.h4
-rw-r--r--runtime/native/java_util_concurrent_atomic_AtomicLong.cc2
-rw-r--r--runtime/native/java_util_concurrent_atomic_AtomicLong.h4
-rw-r--r--runtime/native/jdk_internal_misc_Unsafe.cc2
-rw-r--r--runtime/native/jdk_internal_misc_Unsafe.h4
-rw-r--r--runtime/native/libcore_io_Memory.cc2
-rw-r--r--runtime/native/libcore_io_Memory.h4
-rw-r--r--runtime/native/libcore_util_CharsetUtils.cc2
-rw-r--r--runtime/native/libcore_util_CharsetUtils.h4
-rw-r--r--runtime/native/native_util.h2
-rw-r--r--runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc2
-rw-r--r--runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.h4
-rw-r--r--runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc2
-rw-r--r--runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h4
-rw-r--r--runtime/native/scoped_fast_native_object_access-inl.h2
-rw-r--r--runtime/native/scoped_fast_native_object_access.h3
-rw-r--r--runtime/native/string_array_utils.h3
-rw-r--r--runtime/native/sun_misc_Unsafe.cc2
-rw-r--r--runtime/native/sun_misc_Unsafe.h4
-rw-r--r--runtime/quick_exception_handler.cc43
-rw-r--r--runtime/thread-inl.h2
-rw-r--r--runtime/thread.cc6
-rw-r--r--runtime/thread.h9
-rw-r--r--runtime/thread_list.cc147
-rw-r--r--runtime/thread_list.h6
-rw-r--r--runtime/verifier/class_verifier.cc2
-rw-r--r--runtime/verifier/class_verifier.h26
-rw-r--r--runtime/verifier/instruction_flags.cc2
-rw-r--r--runtime/verifier/instruction_flags.h2
-rw-r--r--runtime/verifier/method_verifier-inl.h2
-rw-r--r--runtime/verifier/method_verifier.cc2
-rw-r--r--runtime/verifier/method_verifier.h32
-rw-r--r--runtime/verifier/method_verifier_test.cc2
-rw-r--r--runtime/verifier/reg_type-inl.h2
-rw-r--r--runtime/verifier/reg_type.cc2
-rw-r--r--runtime/verifier/reg_type.h2
-rw-r--r--runtime/verifier/reg_type_cache-inl.h2
-rw-r--r--runtime/verifier/reg_type_cache.cc2
-rw-r--r--runtime/verifier/reg_type_cache.h2
-rw-r--r--runtime/verifier/reg_type_test.cc2
-rw-r--r--runtime/verifier/register_line-inl.h2
-rw-r--r--runtime/verifier/register_line.cc2
-rw-r--r--runtime/verifier/register_line.h3
-rw-r--r--runtime/verifier/scoped_newline.h4
-rw-r--r--runtime/verifier/verifier_compiler_binding.h2
-rw-r--r--runtime/verifier/verifier_deps.cc2
-rw-r--r--runtime/verifier/verifier_deps.h37
-rw-r--r--runtime/verifier/verifier_enums.h4
-rw-r--r--test/2242-checker-lse-acquire-release-operations/src/Main.java622
-rw-r--r--test/2244-checker-remove-try-boundary/src/Main.java15
-rw-r--r--test/2247-checker-write-barrier-elimination/src/Main.java19
-rw-r--r--test/2271-profile-inline-cache/src/Main.java155
-rw-r--r--test/442-checker-constant-folding/src/Main.java186
-rw-r--r--test/485-checker-dce-loop-update/smali/TestCase.smali6
-rw-r--r--test/543-checker-dce-trycatch/smali/TestCase.smali6
-rw-r--r--test/708-jit-cache-churn/jit.cc56
-rw-r--r--test/708-jit-cache-churn/src/JitCacheChurnTest.java4
-rw-r--r--test/708-jit-cache-churn/src/Main.java3
-rw-r--r--test/912-classes/src-art/art/Test912.java1
-rw-r--r--test/Android.bp1
-rw-r--r--test/common/runtime_state.cc32
-rw-r--r--tools/veridex/Android.bp96
-rw-r--r--tools/veridex/Android.mk2
377 files changed, 2880 insertions, 2079 deletions
diff --git a/OWNERS_boot_profile b/OWNERS_boot_profile
new file mode 100644
index 0000000000..b4b2f80e79
--- /dev/null
+++ b/OWNERS_boot_profile
@@ -0,0 +1,4 @@
+# Owners of boot image and system server profiles.
+islamelbanna@google.com
+ngeoffray@google.com
+vmarko@google.com
diff --git a/build/boot/Android.bp b/build/boot/Android.bp
index 292bb6fbe4..e0bf395872 100644
--- a/build/boot/Android.bp
+++ b/build/boot/Android.bp
@@ -21,9 +21,52 @@ package {
default_applicable_licenses: ["art_license"],
}
+// TODO: b/319697968 - Remove the conditional logic and let art-bootclasspath-fragment always
+// depend on the exportable stubs once metalava fully supports flagged api handling.
+soong_config_module_type {
+ name: "art_bootclasspath_fragment_soong_config_defaults",
+ module_type: "java_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_hidden_api_exportable_stubs",
+ ],
+ properties: [
+ "core_platform_api.stub_libs",
+ ],
+}
+
+art_bootclasspath_fragment_soong_config_defaults {
+ name: "art-bootclasspath-fragment-soong-config-defaults",
+ soong_config_variables: {
+ release_hidden_api_exportable_stubs: {
+ // When "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag is set,
+ // depend on the exportable stubs
+ core_platform_api: {
+ stub_libs: [
+ // Core platform (aka. module_lib) stubs for all the non-coverage contents.
+ "art.module.public.api.stubs.exportable.module_lib",
+ ],
+ },
+ conditions_default: {
+ // When "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag is not set,
+ // depend on the everything stubs
+ core_platform_api: {
+ stub_libs: [
+ // Core platform (aka. module_lib) stubs for all the non-coverage contents.
+ "art.module.public.api.stubs.module_lib",
+ ],
+ },
+ },
+ },
+ },
+}
+
// Encapsulate the contributions made by the com.android.art to the bootclasspath.
bootclasspath_fragment {
name: "art-bootclasspath-fragment",
+ defaults: [
+ "art-bootclasspath-fragment-soong-config-defaults",
+ ],
image_name: "art",
// Must match the ART_APEX_JARS set in build/make/core/envsetup.mk
contents: [
@@ -41,12 +84,6 @@ bootclasspath_fragment {
"art.module.public.api",
],
},
- core_platform_api: {
- stub_libs: [
- // Core platform (aka. module_lib) stubs for all the non-coverage contents.
- "art.module.public.api.stubs.module_lib",
- ],
- },
// Additional properties to append when coverage is enabled, i.e. when
// EMMA_INSTRUMENT_FRAMEWORK=true
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index c14d5d37e8..523a666f8a 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -226,9 +226,5 @@ bool JitCompiler::IsBaselineCompiler() const {
return compiler_options_->IsBaseline();
}
-uint32_t JitCompiler::GetInlineMaxCodeUnits() const {
- return compiler_options_->GetInlineMaxCodeUnits();
-}
-
} // namespace jit
} // namespace art
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 66aa545dd7..5a919fb612 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -64,8 +64,6 @@ class JitCompiler : public JitCompilerInterface {
bool compress,
/*out*/ size_t* num_symbols) override;
- uint32_t GetInlineMaxCodeUnits() const override;
-
private:
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<Compiler> compiler_;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index f12df196e5..9027976165 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -847,8 +847,8 @@ class MethodEntryExitHooksSlowPathARM64 : public SlowPathCodeARM64 {
class CompileOptimizedSlowPathARM64 : public SlowPathCodeARM64 {
public:
- CompileOptimizedSlowPathARM64(HSuspendCheck* check, Register profiling_info)
- : SlowPathCodeARM64(check),
+ explicit CompileOptimizedSlowPathARM64(Register profiling_info)
+ : SlowPathCodeARM64(/* instruction= */ nullptr),
profiling_info_(profiling_info) {}
void EmitNativeCode(CodeGenerator* codegen) override {
@@ -861,18 +861,10 @@ class CompileOptimizedSlowPathARM64 : public SlowPathCodeARM64 {
__ Mov(counter, ProfilingInfo::GetOptimizeThreshold());
__ Strh(counter,
MemOperand(profiling_info_, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
- if (instruction_ != nullptr) {
- // Only saves live vector regs for SIMD.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
__ Ldr(lr, MemOperand(tr, entrypoint_offset));
// Note: we don't record the call here (and therefore don't generate a stack
// map), as the entrypoint should never be suspended.
__ Blr(lr);
- if (instruction_ != nullptr) {
- // Only restores live vector regs for SIMD.
- RestoreLiveRegisters(codegen, instruction_->GetLocations());
- }
__ B(GetExitLabel());
}
@@ -1288,7 +1280,7 @@ void InstructionCodeGeneratorARM64::VisitMethodEntryHook(HMethodEntryHook* instr
GenerateMethodEntryExitHook(instruction);
}
-void CodeGeneratorARM64::MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry) {
+void CodeGeneratorARM64::MaybeIncrementHotness(bool is_frame_entry) {
MacroAssembler* masm = GetVIXLAssembler();
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
UseScratchRegisterScope temps(masm);
@@ -1311,10 +1303,11 @@ void CodeGeneratorARM64::MaybeIncrementHotness(HSuspendCheck* suspend_check, boo
DCHECK(info != nullptr);
DCHECK(!HasEmptyFrame());
uint64_t address = reinterpret_cast64<uint64_t>(info);
+ vixl::aarch64::Label done;
UseScratchRegisterScope temps(masm);
Register counter = temps.AcquireW();
- SlowPathCodeARM64* slow_path = new (GetScopedAllocator()) CompileOptimizedSlowPathARM64(
- suspend_check, /* profiling_info= */ lr);
+ SlowPathCodeARM64* slow_path =
+ new (GetScopedAllocator()) CompileOptimizedSlowPathARM64(/* profiling_info= */ lr);
AddSlowPath(slow_path);
__ Ldr(lr, jit_patches_.DeduplicateUint64Literal(address));
__ Ldrh(counter, MemOperand(lr, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
@@ -1438,7 +1431,7 @@ void CodeGeneratorARM64::GenerateFrameEntry() {
__ Str(wzr, MemOperand(sp, GetStackOffsetOfShouldDeoptimizeFlag()));
}
}
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /* is_frame_entry= */ true);
+ MaybeIncrementHotness(/* is_frame_entry= */ true);
MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
}
@@ -3699,7 +3692,7 @@ void InstructionCodeGeneratorARM64::HandleGoto(HInstruction* got, HBasicBlock* s
HLoopInformation* info = block->GetLoopInformation();
if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
- codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /* is_frame_entry= */ false);
+ codegen_->MaybeIncrementHotness(/* is_frame_entry= */ false);
GenerateSuspendCheck(info->GetSuspendCheck(), successor);
return; // `GenerateSuspendCheck()` emitted the jump.
}
@@ -4604,8 +4597,7 @@ void CodeGeneratorARM64::MaybeGenerateInlineCacheCheck(HInstruction* instruction
if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
DCHECK(info != nullptr);
- InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
- info, GetCompilerOptions(), instruction->AsInvoke());
+ InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(info, instruction->AsInvoke());
if (cache != nullptr) {
uint64_t address = reinterpret_cast64<uint64_t>(cache);
vixl::aarch64::Label done;
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 9c7c42f4c7..7ff08f55cb 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -1017,7 +1017,7 @@ class CodeGeneratorARM64 : public CodeGenerator {
}
void MaybeGenerateInlineCacheCheck(HInstruction* instruction, vixl::aarch64::Register klass);
- void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
+ void MaybeIncrementHotness(bool is_frame_entry);
bool CanUseImplicitSuspendCheck() const;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 0f9dcb4a5a..00c14b0b46 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -971,9 +971,8 @@ class MethodEntryExitHooksSlowPathARMVIXL : public SlowPathCodeARMVIXL {
class CompileOptimizedSlowPathARMVIXL : public SlowPathCodeARMVIXL {
public:
- CompileOptimizedSlowPathARMVIXL(HSuspendCheck* suspend_check,
- vixl32::Register profiling_info)
- : SlowPathCodeARMVIXL(suspend_check),
+ explicit CompileOptimizedSlowPathARMVIXL(vixl32::Register profiling_info)
+ : SlowPathCodeARMVIXL(/* instruction= */ nullptr),
profiling_info_(profiling_info) {}
void EmitNativeCode(CodeGenerator* codegen) override {
@@ -2276,8 +2275,7 @@ void InstructionCodeGeneratorARMVIXL::VisitMethodEntryHook(HMethodEntryHook* ins
GenerateMethodEntryExitHook(instruction);
}
-void CodeGeneratorARMVIXL::MaybeIncrementHotness(HSuspendCheck* suspend_check,
- bool is_frame_entry) {
+void CodeGeneratorARMVIXL::MaybeIncrementHotness(bool is_frame_entry) {
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
UseScratchRegisterScope temps(GetVIXLAssembler());
vixl32::Register temp = temps.Acquire();
@@ -2308,8 +2306,8 @@ void CodeGeneratorARMVIXL::MaybeIncrementHotness(HSuspendCheck* suspend_check,
uint32_t address = reinterpret_cast32<uint32_t>(info);
UseScratchRegisterScope temps(GetVIXLAssembler());
vixl32::Register tmp = temps.Acquire();
- SlowPathCodeARMVIXL* slow_path = new (GetScopedAllocator()) CompileOptimizedSlowPathARMVIXL(
- suspend_check, /* profiling_info= */ lr);
+ SlowPathCodeARMVIXL* slow_path =
+ new (GetScopedAllocator()) CompileOptimizedSlowPathARMVIXL(/* profiling_info= */ lr);
AddSlowPath(slow_path);
__ Mov(lr, address);
__ Ldrh(tmp, MemOperand(lr, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
@@ -2384,7 +2382,7 @@ void CodeGeneratorARMVIXL::GenerateFrameEntry() {
if (HasEmptyFrame()) {
// Ensure that the CFI opcode list is not empty.
GetAssembler()->cfi().Nop();
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /* is_frame_entry= */ true);
+ MaybeIncrementHotness(/* is_frame_entry= */ true);
return;
}
@@ -2484,7 +2482,7 @@ void CodeGeneratorARMVIXL::GenerateFrameEntry() {
GetAssembler()->StoreToOffset(kStoreWord, temp, sp, GetStackOffsetOfShouldDeoptimizeFlag());
}
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /* is_frame_entry= */ true);
+ MaybeIncrementHotness(/* is_frame_entry= */ true);
MaybeGenerateMarkingRegisterCheck(/* code= */ 1);
}
@@ -2829,7 +2827,7 @@ void InstructionCodeGeneratorARMVIXL::HandleGoto(HInstruction* got, HBasicBlock*
HLoopInformation* info = block->GetLoopInformation();
if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
- codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /* is_frame_entry= */ false);
+ codegen_->MaybeIncrementHotness(/* is_frame_entry= */ false);
GenerateSuspendCheck(info->GetSuspendCheck(), successor);
return;
}
@@ -3689,8 +3687,7 @@ void CodeGeneratorARMVIXL::MaybeGenerateInlineCacheCheck(HInstruction* instructi
DCHECK_EQ(r0.GetCode(), klass.GetCode());
if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
- InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
- info, GetCompilerOptions(), instruction->AsInvoke());
+ InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(info, instruction->AsInvoke());
if (cache != nullptr) {
uint32_t address = reinterpret_cast32<uint32_t>(cache);
vixl32::Label done;
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 11b60b3fd2..00e0bfa399 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -885,7 +885,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
}
void MaybeGenerateInlineCacheCheck(HInstruction* instruction, vixl32::Register klass);
- void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
+ void MaybeIncrementHotness(bool is_frame_entry);
private:
// Encoding of thunk type and data for link-time generated thunks for Baker read barriers.
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 108c948345..0c0b8a9f14 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -266,8 +266,8 @@ void LocationsBuilderRISCV64::HandleInvoke(HInvoke* instruction) {
class CompileOptimizedSlowPathRISCV64 : public SlowPathCodeRISCV64 {
public:
- CompileOptimizedSlowPathRISCV64(HSuspendCheck* suspend_check, XRegister base, int32_t imm12)
- : SlowPathCodeRISCV64(suspend_check),
+ CompileOptimizedSlowPathRISCV64(XRegister base, int32_t imm12)
+ : SlowPathCodeRISCV64(/*instruction=*/ nullptr),
base_(base),
imm12_(imm12) {}
@@ -280,18 +280,10 @@ class CompileOptimizedSlowPathRISCV64 : public SlowPathCodeRISCV64 {
XRegister counter = srs.AllocateXRegister();
__ LoadConst32(counter, ProfilingInfo::GetOptimizeThreshold());
__ Sh(counter, base_, imm12_);
- if (instruction_ != nullptr) {
- // Only saves live vector regs for SIMD.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
__ Loadd(RA, TR, entrypoint_offset);
// Note: we don't record the call here (and therefore don't generate a stack
// map), as the entrypoint should never be suspended.
__ Jalr(RA);
- if (instruction_ != nullptr) {
- // Only restores live vector regs for SIMD.
- RestoreLiveRegisters(codegen, instruction_->GetLocations());
- }
__ J(GetExitLabel());
}
@@ -2017,7 +2009,7 @@ void InstructionCodeGeneratorRISCV64::HandleGoto(HInstruction* instruction,
HLoopInformation* info = block->GetLoopInformation();
if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
- codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /*is_frame_entry=*/ false);
+ codegen_->MaybeIncrementHotness(/*is_frame_entry=*/ false);
GenerateSuspendCheck(info->GetSuspendCheck(), successor);
return; // `GenerateSuspendCheck()` emitted the jump.
}
@@ -5702,8 +5694,7 @@ CodeGeneratorRISCV64::CodeGeneratorRISCV64(HGraph* graph,
AddAllocatedRegister(Location::RegisterLocation(RA));
}
-void CodeGeneratorRISCV64::MaybeIncrementHotness(HSuspendCheck* suspend_check,
- bool is_frame_entry) {
+void CodeGeneratorRISCV64::MaybeIncrementHotness(bool is_frame_entry) {
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
ScratchRegisterScope srs(GetAssembler());
XRegister method = is_frame_entry ? kArtMethodRegister : srs.AllocateXRegister();
@@ -5735,7 +5726,7 @@ void CodeGeneratorRISCV64::MaybeIncrementHotness(HSuspendCheck* suspend_check,
XRegister tmp = RA;
__ LoadConst64(tmp, base_address);
SlowPathCodeRISCV64* slow_path =
- new (GetScopedAllocator()) CompileOptimizedSlowPathRISCV64(suspend_check, tmp, imm12);
+ new (GetScopedAllocator()) CompileOptimizedSlowPathRISCV64(tmp, imm12);
AddSlowPath(slow_path);
__ Lhu(counter, tmp, imm12);
__ Beqz(counter, slow_path->GetEntryLabel()); // Can clobber `TMP` if taken.
@@ -5880,7 +5871,7 @@ void CodeGeneratorRISCV64::GenerateFrameEntry() {
__ Storew(Zero, SP, GetStackOffsetOfShouldDeoptimizeFlag());
}
}
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /*is_frame_entry=*/ true);
+ MaybeIncrementHotness(/*is_frame_entry=*/ true);
}
void CodeGeneratorRISCV64::GenerateFrameExit() {
@@ -6743,8 +6734,7 @@ void CodeGeneratorRISCV64::MaybeGenerateInlineCacheCheck(HInstruction* instructi
if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
DCHECK(info != nullptr);
- InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
- info, GetCompilerOptions(), instruction->AsInvoke());
+ InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(info, instruction->AsInvoke());
if (cache != nullptr) {
uint64_t address = reinterpret_cast64<uint64_t>(cache);
Riscv64Label done;
diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h
index 29ccf9dc0b..321403f7f2 100644
--- a/compiler/optimizing/code_generator_riscv64.h
+++ b/compiler/optimizing/code_generator_riscv64.h
@@ -76,9 +76,6 @@ static constexpr int32_t kFClassNaNMinValue = 0x100;
V(StringGetCharsNoCheck) \
V(StringStringIndexOf) \
V(StringStringIndexOfAfter) \
- V(StringNewStringFromBytes) \
- V(StringNewStringFromChars) \
- V(StringNewStringFromString) \
V(StringBufferAppend) \
V(StringBufferLength) \
V(StringBufferToString) \
@@ -94,7 +91,6 @@ static constexpr int32_t kFClassNaNMinValue = 0x100;
V(StringBuilderAppendDouble) \
V(StringBuilderLength) \
V(StringBuilderToString) \
- V(ThreadInterrupted) \
V(CRC32Update) \
V(CRC32UpdateBytes) \
V(CRC32UpdateByteBuffer) \
@@ -642,7 +638,7 @@ class CodeGeneratorRISCV64 : public CodeGenerator {
void GenerateMemoryBarrier(MemBarrierKind kind);
- void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
+ void MaybeIncrementHotness(bool is_frame_entry);
bool CanUseImplicitSuspendCheck() const;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ed40673ad1..71db5c99af 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -990,24 +990,16 @@ class MethodEntryExitHooksSlowPathX86 : public SlowPathCode {
class CompileOptimizedSlowPathX86 : public SlowPathCode {
public:
- CompileOptimizedSlowPathX86(HSuspendCheck* suspend_check, uint32_t counter_address)
- : SlowPathCode(suspend_check),
+ explicit CompileOptimizedSlowPathX86(uint32_t counter_address)
+ : SlowPathCode(/* instruction= */ nullptr),
counter_address_(counter_address) {}
void EmitNativeCode(CodeGenerator* codegen) override {
CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
__ Bind(GetEntryLabel());
__ movw(Address::Absolute(counter_address_), Immediate(ProfilingInfo::GetOptimizeThreshold()));
- if (instruction_ != nullptr) {
- // Only saves full width XMM for SIMD.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
x86_codegen->GenerateInvokeRuntime(
GetThreadOffset<kX86PointerSize>(kQuickCompileOptimized).Int32Value());
- if (instruction_ != nullptr) {
- // Only restores full width XMM for SIMD.
- RestoreLiveRegisters(codegen, instruction_->GetLocations());
- }
__ jmp(GetExitLabel());
}
@@ -1334,7 +1326,7 @@ void InstructionCodeGeneratorX86::VisitMethodEntryHook(HMethodEntryHook* instruc
GenerateMethodEntryExitHook(instruction);
}
-void CodeGeneratorX86::MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry) {
+void CodeGeneratorX86::MaybeIncrementHotness(bool is_frame_entry) {
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
Register reg = EAX;
if (is_frame_entry) {
@@ -1357,15 +1349,12 @@ void CodeGeneratorX86::MaybeIncrementHotness(HSuspendCheck* suspend_check, bool
}
if (GetGraph()->IsCompilingBaseline() && !Runtime::Current()->IsAotCompiler()) {
- // Note the slow path doesn't save SIMD registers, so if we were to
- // call it on loop back edge, we would need to fix this.
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
DCHECK(info != nullptr);
uint32_t address = reinterpret_cast32<uint32_t>(info) +
ProfilingInfo::BaselineHotnessCountOffset().Int32Value();
DCHECK(!HasEmptyFrame());
- SlowPathCode* slow_path =
- new (GetScopedAllocator()) CompileOptimizedSlowPathX86(suspend_check, address);
+ SlowPathCode* slow_path = new (GetScopedAllocator()) CompileOptimizedSlowPathX86(address);
AddSlowPath(slow_path);
// With multiple threads, this can overflow. This is OK, we will eventually get to see
// it reaching 0. Also, at this point we have no register available to look
@@ -1452,7 +1441,7 @@ void CodeGeneratorX86::GenerateFrameEntry() {
}
}
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /* is_frame_entry= */ true);
+ MaybeIncrementHotness(/* is_frame_entry= */ true);
}
void CodeGeneratorX86::GenerateFrameExit() {
@@ -1903,7 +1892,7 @@ void InstructionCodeGeneratorX86::HandleGoto(HInstruction* got, HBasicBlock* suc
HLoopInformation* info = block->GetLoopInformation();
if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
- codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /* is_frame_entry= */ false);
+ codegen_->MaybeIncrementHotness(/* is_frame_entry= */ false);
GenerateSuspendCheck(info->GetSuspendCheck(), successor);
return;
}
@@ -2859,8 +2848,7 @@ void CodeGeneratorX86::MaybeGenerateInlineCacheCheck(HInstruction* instruction,
if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
DCHECK(info != nullptr);
- InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
- info, GetCompilerOptions(), instruction->AsInvoke());
+ InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(info, instruction->AsInvoke());
if (cache != nullptr) {
uint32_t address = reinterpret_cast32<uint32_t>(cache);
if (kIsDebugBuild) {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index f455812bc7..5b59bfc7e3 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -728,7 +728,7 @@ class CodeGeneratorX86 : public CodeGenerator {
void GenerateExplicitNullCheck(HNullCheck* instruction) override;
void MaybeGenerateInlineCacheCheck(HInstruction* instruction, Register klass);
- void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
+ void MaybeIncrementHotness(bool is_frame_entry);
// When we don't know the proper offset for the value, we use kPlaceholder32BitOffset.
// The correct value will be inserted when processing Assembler fixups.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 05b1de9f0a..9d010190f7 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1043,8 +1043,8 @@ class MethodEntryExitHooksSlowPathX86_64 : public SlowPathCode {
class CompileOptimizedSlowPathX86_64 : public SlowPathCode {
public:
- CompileOptimizedSlowPathX86_64(HSuspendCheck* suspend_check, uint64_t counter_address)
- : SlowPathCode(suspend_check),
+ explicit CompileOptimizedSlowPathX86_64(uint64_t counter_address)
+ : SlowPathCode(/* instruction= */ nullptr),
counter_address_(counter_address) {}
void EmitNativeCode(CodeGenerator* codegen) override {
@@ -1052,16 +1052,8 @@ class CompileOptimizedSlowPathX86_64 : public SlowPathCode {
__ Bind(GetEntryLabel());
__ movq(CpuRegister(TMP), Immediate(counter_address_));
__ movw(Address(CpuRegister(TMP), 0), Immediate(ProfilingInfo::GetOptimizeThreshold()));
- if (instruction_ != nullptr) {
- // Only saves full width XMM for SIMD.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
x86_64_codegen->GenerateInvokeRuntime(
GetThreadOffset<kX86_64PointerSize>(kQuickCompileOptimized).Int32Value());
- if (instruction_ != nullptr) {
- // Only restores full width XMM for SIMD.
- RestoreLiveRegisters(codegen, instruction_->GetLocations());
- }
__ jmp(GetExitLabel());
}
@@ -1771,7 +1763,7 @@ void InstructionCodeGeneratorX86_64::VisitMethodExitHook(HMethodExitHook* instru
GenerateMethodEntryExitHook(instruction);
}
-void CodeGeneratorX86_64::MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry) {
+void CodeGeneratorX86_64::MaybeIncrementHotness(bool is_frame_entry) {
if (GetCompilerOptions().CountHotnessInCompiledCode()) {
NearLabel overflow;
Register method = kMethodRegisterArgument;
@@ -1794,8 +1786,7 @@ void CodeGeneratorX86_64::MaybeIncrementHotness(HSuspendCheck* suspend_check, bo
CHECK(!HasEmptyFrame());
uint64_t address = reinterpret_cast64<uint64_t>(info) +
ProfilingInfo::BaselineHotnessCountOffset().Int32Value();
- SlowPathCode* slow_path =
- new (GetScopedAllocator()) CompileOptimizedSlowPathX86_64(suspend_check, address);
+ SlowPathCode* slow_path = new (GetScopedAllocator()) CompileOptimizedSlowPathX86_64(address);
AddSlowPath(slow_path);
// Note: if the address was in the 32bit range, we could use
// Address::Absolute and avoid this movq.
@@ -1900,7 +1891,7 @@ void CodeGeneratorX86_64::GenerateFrameEntry() {
}
}
- MaybeIncrementHotness(/* suspend_check= */ nullptr, /* is_frame_entry= */ true);
+ MaybeIncrementHotness(/* is_frame_entry= */ true);
}
void CodeGeneratorX86_64::GenerateFrameExit() {
@@ -2087,7 +2078,7 @@ void InstructionCodeGeneratorX86_64::HandleGoto(HInstruction* got, HBasicBlock*
HLoopInformation* info = block->GetLoopInformation();
if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
- codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /* is_frame_entry= */ false);
+ codegen_->MaybeIncrementHotness(/* is_frame_entry= */ false);
GenerateSuspendCheck(info->GetSuspendCheck(), successor);
return;
}
@@ -3150,8 +3141,7 @@ void CodeGeneratorX86_64::MaybeGenerateInlineCacheCheck(HInstruction* instructio
if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
ProfilingInfo* info = GetGraph()->GetProfilingInfo();
DCHECK(info != nullptr);
- InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
- info, GetCompilerOptions(), instruction->AsInvoke());
+ InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(info, instruction->AsInvoke());
if (cache != nullptr) {
uint64_t address = reinterpret_cast64<uint64_t>(cache);
NearLabel done;
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 1698c2634a..e4d3eac6bc 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -695,7 +695,7 @@ class CodeGeneratorX86_64 : public CodeGenerator {
void GenerateExplicitNullCheck(HNullCheck* instruction) override;
void MaybeGenerateInlineCacheCheck(HInstruction* instruction, CpuRegister cls);
- void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
+ void MaybeIncrementHotness(bool is_frame_entry);
static void BlockNonVolatileXmmRegisters(LocationSummary* locations);
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index 66bbf548bb..64ef17898a 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -32,8 +32,8 @@ namespace art HIDDEN {
// as constants.
class HConstantFoldingVisitor final : public HGraphDelegateVisitor {
public:
- HConstantFoldingVisitor(HGraph* graph, OptimizingCompilerStats* stats, bool use_all_optimizations)
- : HGraphDelegateVisitor(graph, stats), use_all_optimizations_(use_all_optimizations) {}
+ explicit HConstantFoldingVisitor(HGraph* graph, OptimizingCompilerStats* stats)
+ : HGraphDelegateVisitor(graph, stats) {}
private:
void VisitBasicBlock(HBasicBlock* block) override;
@@ -66,9 +66,6 @@ class HConstantFoldingVisitor final : public HGraphDelegateVisitor {
void FoldNumberOfLeadingZerosIntrinsic(HInvoke* invoke);
void FoldNumberOfTrailingZerosIntrinsic(HInvoke* invoke);
- // Use all optimizations without restrictions.
- bool use_all_optimizations_;
-
DISALLOW_COPY_AND_ASSIGN(HConstantFoldingVisitor);
};
@@ -109,7 +106,7 @@ class InstructionWithAbsorbingInputSimplifier : public HGraphVisitor {
bool HConstantFolding::Run() {
- HConstantFoldingVisitor visitor(graph_, stats_, use_all_optimizations_);
+ HConstantFoldingVisitor visitor(graph_, stats_);
// Process basic blocks in reverse post-order in the dominator tree,
// so that an instruction turned into a constant, used as input of
// another instruction, may possibly be used to turn that second
@@ -232,11 +229,6 @@ void HConstantFoldingVisitor::PropagateValue(HBasicBlock* starting_block,
uses_before = variable->GetUses().SizeSlow();
}
- if (variable->GetUses().HasExactlyOneElement()) {
- // Nothing to do, since we only have the `if (variable)` use or the `condition` use.
- return;
- }
-
variable->ReplaceUsesDominatedBy(
starting_block->GetFirstInstruction(), constant, /* strictly_dominated= */ false);
@@ -249,12 +241,6 @@ void HConstantFoldingVisitor::PropagateValue(HBasicBlock* starting_block,
}
void HConstantFoldingVisitor::VisitIf(HIf* inst) {
- // This optimization can take a lot of compile time since we have a lot of If instructions in
- // graphs.
- if (!use_all_optimizations_) {
- return;
- }
-
// Consistency check: the true and false successors do not dominate each other.
DCHECK(!inst->IfTrueSuccessor()->Dominates(inst->IfFalseSuccessor()) &&
!inst->IfFalseSuccessor()->Dominates(inst->IfTrueSuccessor()));
diff --git a/compiler/optimizing/constant_folding.h b/compiler/optimizing/constant_folding.h
index 29648e907c..73ac3ceb81 100644
--- a/compiler/optimizing/constant_folding.h
+++ b/compiler/optimizing/constant_folding.h
@@ -43,18 +43,14 @@ class HConstantFolding : public HOptimization {
public:
HConstantFolding(HGraph* graph,
OptimizingCompilerStats* stats = nullptr,
- const char* name = kConstantFoldingPassName,
- bool use_all_optimizations = false)
- : HOptimization(graph, name, stats), use_all_optimizations_(use_all_optimizations) {}
+ const char* name = kConstantFoldingPassName)
+ : HOptimization(graph, name, stats) {}
bool Run() override;
static constexpr const char* kConstantFoldingPassName = "constant_folding";
private:
- // Use all optimizations without restrictions.
- bool use_all_optimizations_;
-
DISALLOW_COPY_AND_ASSIGN(HConstantFolding);
};
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index acdc8e6d3c..689d77111c 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -60,9 +60,7 @@ class ConstantFoldingTest : public CommonCompilerTest, public OptimizingUnitTest
std::string actual_before = printer_before.str();
EXPECT_EQ(expected_before, actual_before);
- HConstantFolding constant_folding(
- graph_, /* stats= */ nullptr, "constant_folding", /* use_all_optimizations= */ true);
- constant_folding.Run();
+ HConstantFolding(graph_, /* stats= */ nullptr, "constant_folding").Run();
GraphChecker graph_checker_cf(graph_);
graph_checker_cf.Run();
ASSERT_TRUE(graph_checker_cf.IsValid());
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index afbf941355..b7f7a0f550 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -867,8 +867,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
std::ostringstream oss;
oss << pass_name_;
if (!IsDebugDump()) {
- oss << " (" << (GetGraph()->IsCompilingBaseline() ? "baseline " : "")
- << (is_after_pass_ ? "after" : "before")
+ oss << " (" << (is_after_pass_ ? "after" : "before")
<< (graph_in_bad_state_ ? ", bad_state" : "") << ")";
}
PrintProperty("name", oss.str().c_str());
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index fcd899ed1c..e0bf028138 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -37,7 +37,6 @@
#include "mirror/object_array-alloc-inl.h"
#include "mirror/object_array-inl.h"
#include "nodes.h"
-#include "profiling_info_builder.h"
#include "reference_type_propagation.h"
#include "register_allocator_linear_scan.h"
#include "scoped_thread_state_change-inl.h"
@@ -533,15 +532,6 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) {
return result;
}
- if (graph_->IsCompilingBaseline()) {
- LOG_FAIL_NO_STAT() << "Call to " << invoke_instruction->GetMethodReference().PrettyMethod()
- << " not inlined because we are compiling baseline and we could not"
- << " statically resolve the target";
- // For baseline compilation, we will collect inline caches, so we should not
- // try to inline using them.
- return false;
- }
-
DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
// No try catch inlining allowed here, or recursively. For try catch inlining we are banking on
@@ -692,36 +682,17 @@ HInliner::InlineCacheType HInliner::GetInlineCacheJIT(
ArtMethod* caller = graph_->GetArtMethod();
// Under JIT, we should always know the caller.
DCHECK(caller != nullptr);
-
- InlineCache* cache = nullptr;
- // Start with the outer graph profiling info.
- ProfilingInfo* profiling_info = outermost_graph_->GetProfilingInfo();
- if (profiling_info != nullptr) {
- if (depth_ == 0) {
- cache = profiling_info->GetInlineCache(invoke_instruction->GetDexPc());
- } else {
- uint32_t dex_pc = ProfilingInfoBuilder::EncodeInlinedDexPc(
- this, codegen_->GetCompilerOptions(), invoke_instruction);
- if (dex_pc != kNoDexPc) {
- cache = profiling_info->GetInlineCache(dex_pc);
- }
- }
- }
-
- if (cache == nullptr) {
- // Check the current graph profiling info.
- profiling_info = graph_->GetProfilingInfo();
- if (profiling_info == nullptr) {
- return kInlineCacheNoData;
- }
-
- cache = profiling_info->GetInlineCache(invoke_instruction->GetDexPc());
+ ProfilingInfo* profiling_info = graph_->GetProfilingInfo();
+ if (profiling_info == nullptr) {
+ return kInlineCacheNoData;
}
+ InlineCache* cache = profiling_info->GetInlineCache(invoke_instruction->GetDexPc());
if (cache == nullptr) {
- // Either we never hit this invoke and we never compiled the callee,
- // or the method wasn't resolved when we performed baseline compilation.
- // Bail for now.
+ // This shouldn't happen, but we don't guarantee that method resolution
+ // between baseline compilation and optimizing compilation is identical. Be robust,
+ // warn about it, and return that we don't have any inline cache data.
+ LOG(WARNING) << "No inline cache found for " << caller->PrettyMethod();
return kInlineCacheNoData;
}
Runtime::Current()->GetJit()->GetCodeCache()->CopyInlineCacheInto(*cache, classes);
@@ -747,12 +718,6 @@ HInliner::InlineCacheType HInliner::GetInlineCacheAOT(
const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
DCHECK(inline_caches != nullptr);
-
- // Inlined inline caches are not supported in AOT, so we use the dex pc directly, and don't
- // call `InlineCache::EncodeDexPc`.
- // To support it, we would need to ensure `inline_max_code_units` remain the
- // same between dex2oat and runtime, for example by adding it to the boot
- // image oat header.
const auto it = inline_caches->find(invoke_instruction->GetDexPc());
if (it == inline_caches->end()) {
return kInlineCacheUninitialized;
@@ -2112,20 +2077,6 @@ bool HInliner::CanInlineBody(const HGraph* callee_graph,
<< " could not be inlined because it needs a BSS check";
return false;
}
-
- if (outermost_graph_->IsCompilingBaseline() &&
- (current->IsInvokeVirtual() || current->IsInvokeInterface()) &&
- ProfilingInfoBuilder::IsInlineCacheUseful(current->AsInvoke(), codegen_)) {
- uint32_t maximum_inlining_depth_for_baseline =
- InlineCache::MaxDexPcEncodingDepth(
- outermost_graph_->GetArtMethod(),
- codegen_->GetCompilerOptions().GetInlineMaxCodeUnits());
- if (depth_ + 1 > maximum_inlining_depth_for_baseline) {
- LOG_FAIL_NO_STAT() << "Reached maximum depth for inlining in baseline compilation: "
- << depth_ << " for " << callee_graph->GetArtMethod()->PrettyMethod();
- return false;
- }
- }
}
}
@@ -2237,7 +2188,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
// The current invoke is not a try block.
!invoke_instruction->GetBlock()->IsTryBlock();
RunOptimizations(callee_graph,
- invoke_instruction->GetEnvironment(),
code_item,
dex_compilation_unit,
try_catch_inlining_allowed_for_recursive_inline);
@@ -2277,7 +2227,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
}
void HInliner::RunOptimizations(HGraph* callee_graph,
- HEnvironment* caller_environment,
const dex::CodeItem* code_item,
const DexCompilationUnit& dex_compilation_unit,
bool try_catch_inlining_allowed_for_recursive_inline) {
@@ -2326,7 +2275,6 @@ void HInliner::RunOptimizations(HGraph* callee_graph,
total_number_of_dex_registers_ + accessor.RegistersSize(),
total_number_of_instructions_ + number_of_instructions,
this,
- caller_environment,
depth_ + 1,
try_catch_inlining_allowed_for_recursive_inline);
inliner.Run();
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 48600543c6..5e68dd866e 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -43,7 +43,6 @@ class HInliner : public HOptimization {
size_t total_number_of_dex_registers,
size_t total_number_of_instructions,
HInliner* parent,
- HEnvironment* caller_environment,
size_t depth,
bool try_catch_inlining_allowed,
const char* name = kInlinerPassName)
@@ -55,7 +54,6 @@ class HInliner : public HOptimization {
total_number_of_dex_registers_(total_number_of_dex_registers),
total_number_of_instructions_(total_number_of_instructions),
parent_(parent),
- caller_environment_(caller_environment),
depth_(depth),
inlining_budget_(0),
try_catch_inlining_allowed_(try_catch_inlining_allowed),
@@ -66,12 +64,6 @@ class HInliner : public HOptimization {
static constexpr const char* kInlinerPassName = "inliner";
- const HInliner* GetParent() const { return parent_; }
- const HEnvironment* GetCallerEnvironment() const { return caller_environment_; }
-
- const HGraph* GetOutermostGraph() const { return outermost_graph_; }
- const HGraph* GetGraph() const { return graph_; }
-
private:
enum InlineCacheType {
kInlineCacheNoData = 0,
@@ -117,7 +109,6 @@ class HInliner : public HOptimization {
// Run simple optimizations on `callee_graph`.
void RunOptimizations(HGraph* callee_graph,
- HEnvironment* caller_environment,
const dex::CodeItem* code_item,
const DexCompilationUnit& dex_compilation_unit,
bool try_catch_inlining_allowed_for_recursive_inline)
@@ -330,10 +321,9 @@ class HInliner : public HOptimization {
const size_t total_number_of_dex_registers_;
size_t total_number_of_instructions_;
- // The 'parent' inliner, that means the inlining optimization that requested
+ // The 'parent' inliner, that means the inlinigng optimization that requested
// `graph_` to be inlined.
const HInliner* const parent_;
- const HEnvironment* const caller_environment_;
const size_t depth_;
// The budget left for inlining, in number of instructions.
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 3183dac348..27a41762e2 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -114,6 +114,7 @@ class ReadBarrierSystemArrayCopySlowPathARM64 : public SlowPathCodeARM64 {
Register tmp_reg = WRegisterFrom(tmp_);
__ Bind(GetEntryLabel());
+ // The source range and destination pointer were initialized before entering the slow-path.
vixl::aarch64::Label slow_copy_loop;
__ Bind(&slow_copy_loop);
__ Ldr(tmp_reg, MemOperand(src_curr_addr, element_size, PostIndex));
@@ -2731,14 +2732,12 @@ void IntrinsicCodeGeneratorARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) {
// so if we choose to jump to the slow path we will end up in the native implementation.
static constexpr int32_t kSystemArrayCopyCharThreshold = 192;
-static void SetSystemArrayCopyLocationRequires(LocationSummary* locations,
- uint32_t at,
- HInstruction* input) {
+static Location LocationForSystemArrayCopyInput(HInstruction* input) {
HIntConstant* const_input = input->AsIntConstantOrNull();
- if (const_input != nullptr && !vixl::aarch64::Assembler::IsImmAddSub(const_input->GetValue())) {
- locations->SetInAt(at, Location::RequiresRegister());
+ if (const_input != nullptr && vixl::aarch64::Assembler::IsImmAddSub(const_input->GetValue())) {
+ return Location::ConstantLocation(const_input);
} else {
- locations->SetInAt(at, Location::RegisterOrConstant(input));
+ return Location::RequiresRegister();
}
}
@@ -2771,10 +2770,10 @@ void IntrinsicLocationsBuilderARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
// arraycopy(char[] src, int src_pos, char[] dst, int dst_pos, int length).
locations->SetInAt(0, Location::RequiresRegister());
- SetSystemArrayCopyLocationRequires(locations, 1, invoke->InputAt(1));
+ locations->SetInAt(1, LocationForSystemArrayCopyInput(invoke->InputAt(1)));
locations->SetInAt(2, Location::RequiresRegister());
- SetSystemArrayCopyLocationRequires(locations, 3, invoke->InputAt(3));
- SetSystemArrayCopyLocationRequires(locations, 4, invoke->InputAt(4));
+ locations->SetInAt(3, LocationForSystemArrayCopyInput(invoke->InputAt(3)));
+ locations->SetInAt(4, LocationForSystemArrayCopyInput(invoke->InputAt(4)));
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
@@ -2782,92 +2781,97 @@ void IntrinsicLocationsBuilderARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
}
static void CheckSystemArrayCopyPosition(MacroAssembler* masm,
- const Location& pos,
- const Register& input,
- const Location& length,
+ Register array,
+ Location pos,
+ Location length,
SlowPathCodeARM64* slow_path,
- const Register& temp,
- bool length_is_input_length = false) {
+ Register temp,
+ bool length_is_array_length,
+ bool position_sign_checked) {
const int32_t length_offset = mirror::Array::LengthOffset().Int32Value();
if (pos.IsConstant()) {
int32_t pos_const = pos.GetConstant()->AsIntConstant()->GetValue();
if (pos_const == 0) {
- if (!length_is_input_length) {
- // Check that length(input) >= length.
- __ Ldr(temp, MemOperand(input, length_offset));
+ if (!length_is_array_length) {
+ // Check that length(array) >= length.
+ __ Ldr(temp, MemOperand(array, length_offset));
__ Cmp(temp, OperandFrom(length, DataType::Type::kInt32));
__ B(slow_path->GetEntryLabel(), lt);
}
} else {
- // Check that length(input) >= pos.
- __ Ldr(temp, MemOperand(input, length_offset));
- __ Subs(temp, temp, pos_const);
- __ B(slow_path->GetEntryLabel(), lt);
+ // Calculate length(array) - pos.
+ // Both operands are known to be non-negative `int32_t`, so the difference cannot underflow
+ // as `int32_t`. If the result is negative, the B.LT below shall go to the slow path.
+ __ Ldr(temp, MemOperand(array, length_offset));
+ __ Sub(temp, temp, pos_const);
- // Check that (length(input) - pos) >= length.
+ // Check that (length(array) - pos) >= length.
__ Cmp(temp, OperandFrom(length, DataType::Type::kInt32));
__ B(slow_path->GetEntryLabel(), lt);
}
- } else if (length_is_input_length) {
+ } else if (length_is_array_length) {
// The only way the copy can succeed is if pos is zero.
__ Cbnz(WRegisterFrom(pos), slow_path->GetEntryLabel());
} else {
// Check that pos >= 0.
Register pos_reg = WRegisterFrom(pos);
- __ Tbnz(pos_reg, pos_reg.GetSizeInBits() - 1, slow_path->GetEntryLabel());
+ if (!position_sign_checked) {
+ __ Tbnz(pos_reg, pos_reg.GetSizeInBits() - 1, slow_path->GetEntryLabel());
+ }
- // Check that pos <= length(input) && (length(input) - pos) >= length.
- __ Ldr(temp, MemOperand(input, length_offset));
- __ Subs(temp, temp, pos_reg);
- // Ccmp if length(input) >= pos, else definitely bail to slow path (N!=V == lt).
- __ Ccmp(temp, OperandFrom(length, DataType::Type::kInt32), NFlag, ge);
+ // Calculate length(array) - pos.
+ // Both operands are known to be non-negative `int32_t`, so the difference cannot underflow
+ // as `int32_t`. If the result is negative, the B.LT below shall go to the slow path.
+ __ Ldr(temp, MemOperand(array, length_offset));
+ __ Sub(temp, temp, pos_reg);
+
+ // Check that (length(array) - pos) >= length.
+ __ Cmp(temp, OperandFrom(length, DataType::Type::kInt32));
__ B(slow_path->GetEntryLabel(), lt);
}
}
+static void GenArrayAddress(MacroAssembler* masm,
+ Register dest,
+ Register base,
+ Location pos,
+ DataType::Type type,
+ int32_t data_offset) {
+ if (pos.IsConstant()) {
+ int32_t constant = pos.GetConstant()->AsIntConstant()->GetValue();
+ __ Add(dest, base, DataType::Size(type) * constant + data_offset);
+ } else {
+ if (data_offset != 0) {
+ __ Add(dest, base, data_offset);
+ base = dest;
+ }
+ __ Add(dest, base, Operand(XRegisterFrom(pos), LSL, DataType::SizeShift(type)));
+ }
+}
+
// Compute base source address, base destination address, and end
// source address for System.arraycopy* intrinsics in `src_base`,
// `dst_base` and `src_end` respectively.
static void GenSystemArrayCopyAddresses(MacroAssembler* masm,
DataType::Type type,
- const Register& src,
- const Location& src_pos,
- const Register& dst,
- const Location& dst_pos,
- const Location& copy_length,
- const Register& src_base,
- const Register& dst_base,
- const Register& src_end) {
+ Register src,
+ Location src_pos,
+ Register dst,
+ Location dst_pos,
+ Location copy_length,
+ Register src_base,
+ Register dst_base,
+ Register src_end) {
// This routine is used by the SystemArrayCopy and the SystemArrayCopyChar intrinsics.
DCHECK(type == DataType::Type::kReference || type == DataType::Type::kUint16)
<< "Unexpected element type: " << type;
const int32_t element_size = DataType::Size(type);
- const int32_t element_size_shift = DataType::SizeShift(type);
const uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value();
- if (src_pos.IsConstant()) {
- int32_t constant = src_pos.GetConstant()->AsIntConstant()->GetValue();
- __ Add(src_base, src, element_size * constant + data_offset);
- } else {
- __ Add(src_base, src, data_offset);
- __ Add(src_base, src_base, Operand(XRegisterFrom(src_pos), LSL, element_size_shift));
- }
-
- if (dst_pos.IsConstant()) {
- int32_t constant = dst_pos.GetConstant()->AsIntConstant()->GetValue();
- __ Add(dst_base, dst, element_size * constant + data_offset);
- } else {
- __ Add(dst_base, dst, data_offset);
- __ Add(dst_base, dst_base, Operand(XRegisterFrom(dst_pos), LSL, element_size_shift));
- }
-
+ GenArrayAddress(masm, src_base, src, src_pos, type, data_offset);
+ GenArrayAddress(masm, dst_base, dst, dst_pos, type, data_offset);
if (src_end.IsValid()) {
- if (copy_length.IsConstant()) {
- int32_t constant = copy_length.GetConstant()->AsIntConstant()->GetValue();
- __ Add(src_end, src_base, element_size * constant);
- } else {
- __ Add(src_end, src_base, Operand(XRegisterFrom(copy_length), LSL, element_size_shift));
- }
+ GenArrayAddress(masm, src_end, src_base, copy_length, type, /*data_offset=*/ 0);
}
}
@@ -2913,20 +2917,22 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
Register src_stop_addr = WRegisterFrom(locations->GetTemp(2));
CheckSystemArrayCopyPosition(masm,
- src_pos,
src,
+ src_pos,
length,
slow_path,
src_curr_addr,
- false);
+ /*length_is_array_length=*/ false,
+ /*position_sign_checked=*/ false);
CheckSystemArrayCopyPosition(masm,
- dst_pos,
dst,
+ dst_pos,
length,
slow_path,
src_curr_addr,
- false);
+ /*length_is_array_length=*/ false,
+ /*position_sign_checked=*/ false);
src_curr_addr = src_curr_addr.X();
dst_curr_addr = dst_curr_addr.X();
@@ -3043,9 +3049,6 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
// We can choose to use the native implementation there for longer copy lengths.
static constexpr int32_t kSystemArrayCopyThreshold = 128;
-// CodeGenerator::CreateSystemArrayCopyLocationSummary use three temporary registers.
-// We want to use two temporary registers in order to reduce the register pressure in arm64.
-// So we don't use the CodeGenerator::CreateSystemArrayCopyLocationSummary.
void IntrinsicLocationsBuilderARM64::VisitSystemArrayCopy(HInvoke* invoke) {
// The only read barrier implementation supporting the
// SystemArrayCopy intrinsic is the Baker-style read barriers.
@@ -3053,67 +3056,27 @@ void IntrinsicLocationsBuilderARM64::VisitSystemArrayCopy(HInvoke* invoke) {
return;
}
- // Check to see if we have known failures that will cause us to have to bail out
- // to the runtime, and just generate the runtime call directly.
- HIntConstant* src_pos = invoke->InputAt(1)->AsIntConstantOrNull();
- HIntConstant* dest_pos = invoke->InputAt(3)->AsIntConstantOrNull();
-
- // The positions must be non-negative.
- if ((src_pos != nullptr && src_pos->GetValue() < 0) ||
- (dest_pos != nullptr && dest_pos->GetValue() < 0)) {
- // We will have to fail anyways.
- return;
- }
-
- // The length must be >= 0.
- HIntConstant* length = invoke->InputAt(4)->AsIntConstantOrNull();
- if (length != nullptr) {
- int32_t len = length->GetValue();
- if (len < 0 || len >= kSystemArrayCopyThreshold) {
- // Just call as normal.
- return;
- }
- }
-
- SystemArrayCopyOptimizations optimizations(invoke);
-
- if (optimizations.GetDestinationIsSource()) {
- if (src_pos != nullptr && dest_pos != nullptr && src_pos->GetValue() < dest_pos->GetValue()) {
- // We only support backward copying if source and destination are the same.
- return;
+ constexpr size_t kInitialNumTemps = 2u; // We need at least two temps.
+ LocationSummary* locations = CodeGenerator::CreateSystemArrayCopyLocationSummary(
+ invoke, kSystemArrayCopyThreshold, kInitialNumTemps);
+ if (locations != nullptr) {
+ locations->SetInAt(1, LocationForSystemArrayCopyInput(invoke->InputAt(1)));
+ locations->SetInAt(3, LocationForSystemArrayCopyInput(invoke->InputAt(3)));
+ locations->SetInAt(4, LocationForSystemArrayCopyInput(invoke->InputAt(4)));
+ if (codegen_->EmitBakerReadBarrier()) {
+ // Temporary register IP0, obtained from the VIXL scratch register
+ // pool, cannot be used in ReadBarrierSystemArrayCopySlowPathARM64
+ // (because that register is clobbered by ReadBarrierMarkRegX
+ // entry points). It cannot be used in calls to
+ // CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier
+ // either. For these reasons, get a third extra temporary register
+ // from the register allocator.
+ locations->AddTemp(Location::RequiresRegister());
+ } else {
+ // Cases other than Baker read barriers: the third temporary will
+ // be acquired from the VIXL scratch register pool.
}
}
-
- if (optimizations.GetDestinationIsPrimitiveArray() || optimizations.GetSourceIsPrimitiveArray()) {
- // We currently don't intrinsify primitive copying.
- return;
- }
-
- ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
- LocationSummary* locations =
- new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
- // arraycopy(Object src, int src_pos, Object dest, int dest_pos, int length).
- locations->SetInAt(0, Location::RequiresRegister());
- SetSystemArrayCopyLocationRequires(locations, 1, invoke->InputAt(1));
- locations->SetInAt(2, Location::RequiresRegister());
- SetSystemArrayCopyLocationRequires(locations, 3, invoke->InputAt(3));
- SetSystemArrayCopyLocationRequires(locations, 4, invoke->InputAt(4));
-
- locations->AddTemp(Location::RequiresRegister());
- locations->AddTemp(Location::RequiresRegister());
- if (codegen_->EmitBakerReadBarrier()) {
- // Temporary register IP0, obtained from the VIXL scratch register
- // pool, cannot be used in ReadBarrierSystemArrayCopySlowPathARM64
- // (because that register is clobbered by ReadBarrierMarkRegX
- // entry points). It cannot be used in calls to
- // CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier
- // either. For these reasons, get a third extra temporary register
- // from the register allocator.
- locations->AddTemp(Location::RequiresRegister());
- } else {
- // Cases other than Baker read barriers: the third temporary will
- // be acquired from the VIXL scratch register pool.
- }
}
void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
@@ -3147,38 +3110,37 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
vixl::aarch64::Label conditions_on_positions_validated;
SystemArrayCopyOptimizations optimizations(invoke);
- // If source and destination are the same, we go to slow path if we need to do
- // forward copying.
- if (src_pos.IsConstant()) {
- int32_t src_pos_constant = src_pos.GetConstant()->AsIntConstant()->GetValue();
- if (dest_pos.IsConstant()) {
- int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue();
- if (optimizations.GetDestinationIsSource()) {
- // Checked when building locations.
- DCHECK_GE(src_pos_constant, dest_pos_constant);
- } else if (src_pos_constant < dest_pos_constant) {
- __ Cmp(src, dest);
- __ B(intrinsic_slow_path->GetEntryLabel(), eq);
+ // If source and destination are the same, we go to slow path if we need to do forward copying.
+ // We do not need to do this check if the source and destination positions are the same.
+ if (!optimizations.GetSourcePositionIsDestinationPosition()) {
+ if (src_pos.IsConstant()) {
+ int32_t src_pos_constant = src_pos.GetConstant()->AsIntConstant()->GetValue();
+ if (dest_pos.IsConstant()) {
+ int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue();
+ if (optimizations.GetDestinationIsSource()) {
+ // Checked when building locations.
+ DCHECK_GE(src_pos_constant, dest_pos_constant);
+ } else if (src_pos_constant < dest_pos_constant) {
+ __ Cmp(src, dest);
+ __ B(intrinsic_slow_path->GetEntryLabel(), eq);
+ }
+ } else {
+ if (!optimizations.GetDestinationIsSource()) {
+ __ Cmp(src, dest);
+ __ B(&conditions_on_positions_validated, ne);
+ }
+ __ Cmp(WRegisterFrom(dest_pos), src_pos_constant);
+ __ B(intrinsic_slow_path->GetEntryLabel(), gt);
}
- // Checked when building locations.
- DCHECK(!optimizations.GetDestinationIsSource() ||
- (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue()));
} else {
if (!optimizations.GetDestinationIsSource()) {
__ Cmp(src, dest);
__ B(&conditions_on_positions_validated, ne);
}
- __ Cmp(WRegisterFrom(dest_pos), src_pos_constant);
- __ B(intrinsic_slow_path->GetEntryLabel(), gt);
+ __ Cmp(RegisterFrom(src_pos, invoke->InputAt(1)->GetType()),
+ OperandFrom(dest_pos, invoke->InputAt(3)->GetType()));
+ __ B(intrinsic_slow_path->GetEntryLabel(), lt);
}
- } else {
- if (!optimizations.GetDestinationIsSource()) {
- __ Cmp(src, dest);
- __ B(&conditions_on_positions_validated, ne);
- }
- __ Cmp(RegisterFrom(src_pos, invoke->InputAt(1)->GetType()),
- OperandFrom(dest_pos, invoke->InputAt(3)->GetType()));
- __ B(intrinsic_slow_path->GetEntryLabel(), lt);
}
__ Bind(&conditions_on_positions_validated);
@@ -3194,9 +3156,7 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
}
// We have already checked in the LocationsBuilder for the constant case.
- if (!length.IsConstant() &&
- !optimizations.GetCountIsSourceLength() &&
- !optimizations.GetCountIsDestinationLength()) {
+ if (!length.IsConstant()) {
// Merge the following two comparisons into one:
// If the length is negative, bail out (delegate to libcore's native implementation).
// If the length >= 128 then (currently) prefer native implementation.
@@ -3205,252 +3165,155 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
}
// Validity checks: source.
CheckSystemArrayCopyPosition(masm,
- src_pos,
src,
+ src_pos,
length,
intrinsic_slow_path,
temp1,
- optimizations.GetCountIsSourceLength());
+ optimizations.GetCountIsSourceLength(),
+ /*position_sign_checked=*/ false);
// Validity checks: dest.
+ bool dest_position_sign_checked = optimizations.GetSourcePositionIsDestinationPosition();
CheckSystemArrayCopyPosition(masm,
- dest_pos,
dest,
+ dest_pos,
length,
intrinsic_slow_path,
temp1,
- optimizations.GetCountIsDestinationLength());
- {
- // We use a block to end the scratch scope before the write barrier, thus
- // freeing the temporary registers so they can be used in `MarkGCCard`.
- UseScratchRegisterScope temps(masm);
- Location temp3_loc; // Used only for Baker read barrier.
- Register temp3;
+ optimizations.GetCountIsDestinationLength(),
+ dest_position_sign_checked);
+
+ auto check_non_primitive_array_class = [&](Register klass, Register temp) {
+ // No read barrier is needed for reading a chain of constant references for comparing
+ // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp = klass->component_type_
+ __ Ldr(temp, HeapOperand(klass, component_offset));
+ codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+ // Check that the component type is not null.
+ __ Cbz(temp, intrinsic_slow_path->GetEntryLabel());
+ // Check that the component type is not a primitive.
+ // /* uint16_t */ temp = static_cast<uint16>(klass->primitive_type_);
+ __ Ldr(temp, HeapOperand(temp, primitive_offset));
+ static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
+ __ Cbnz(temp, intrinsic_slow_path->GetEntryLabel());
+ };
+
+ if (!optimizations.GetDoesNotNeedTypeCheck()) {
+ // Check whether all elements of the source array are assignable to the component
+ // type of the destination array. We do two checks: the classes are the same,
+ // or the destination is Object[]. If none of these checks succeed, we go to the
+ // slow path.
+
if (codegen_->EmitBakerReadBarrier()) {
- temp3_loc = locations->GetTemp(2);
- temp3 = WRegisterFrom(temp3_loc);
+ Location temp3_loc = locations->GetTemp(2);
+ // /* HeapReference<Class> */ temp1 = dest->klass_
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ temp1_loc,
+ dest.W(),
+ class_offset,
+ temp3_loc,
+ /* needs_null_check= */ false,
+ /* use_load_acquire= */ false);
+ // Register `temp1` is not trashed by the read barrier emitted
+ // by GenerateFieldLoadWithBakerReadBarrier below, as that
+ // method produces a call to a ReadBarrierMarkRegX entry point,
+ // which saves all potentially live registers, including
+ // temporaries such a `temp1`.
+ // /* HeapReference<Class> */ temp2 = src->klass_
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ temp2_loc,
+ src.W(),
+ class_offset,
+ temp3_loc,
+ /* needs_null_check= */ false,
+ /* use_load_acquire= */ false);
} else {
- temp3 = temps.AcquireW();
+ // /* HeapReference<Class> */ temp1 = dest->klass_
+ __ Ldr(temp1, MemOperand(dest, class_offset));
+ codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
+ // /* HeapReference<Class> */ temp2 = src->klass_
+ __ Ldr(temp2, MemOperand(src, class_offset));
+ codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
}
- if (!optimizations.GetDoesNotNeedTypeCheck()) {
- // Check whether all elements of the source array are assignable to the component
- // type of the destination array. We do two checks: the classes are the same,
- // or the destination is Object[]. If none of these checks succeed, we go to the
- // slow path.
-
- if (codegen_->EmitBakerReadBarrier()) {
- if (!optimizations.GetSourceIsNonPrimitiveArray()) {
- // /* HeapReference<Class> */ temp1 = src->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp1_loc,
- src.W(),
- class_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- // Bail out if the source is not a non primitive array.
- // /* HeapReference<Class> */ temp1 = temp1->component_type_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp1_loc,
- temp1,
- component_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- __ Cbz(temp1, intrinsic_slow_path->GetEntryLabel());
- // If heap poisoning is enabled, `temp1` has been unpoisoned
- // by the previous call to GenerateFieldLoadWithBakerReadBarrier.
- // /* uint16_t */ temp1 = static_cast<uint16>(temp1->primitive_type_);
- __ Ldrh(temp1, HeapOperand(temp1, primitive_offset));
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Cbnz(temp1, intrinsic_slow_path->GetEntryLabel());
- }
-
- // /* HeapReference<Class> */ temp1 = dest->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp1_loc,
- dest.W(),
- class_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
-
- if (!optimizations.GetDestinationIsNonPrimitiveArray()) {
- // Bail out if the destination is not a non primitive array.
- //
- // Register `temp1` is not trashed by the read barrier emitted
- // by GenerateFieldLoadWithBakerReadBarrier below, as that
- // method produces a call to a ReadBarrierMarkRegX entry point,
- // which saves all potentially live registers, including
- // temporaries such a `temp1`.
- // /* HeapReference<Class> */ temp2 = temp1->component_type_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp2_loc,
- temp1,
- component_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- __ Cbz(temp2, intrinsic_slow_path->GetEntryLabel());
- // If heap poisoning is enabled, `temp2` has been unpoisoned
- // by the previous call to GenerateFieldLoadWithBakerReadBarrier.
- // /* uint16_t */ temp2 = static_cast<uint16>(temp2->primitive_type_);
- __ Ldrh(temp2, HeapOperand(temp2, primitive_offset));
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Cbnz(temp2, intrinsic_slow_path->GetEntryLabel());
- }
-
- // For the same reason given earlier, `temp1` is not trashed by the
- // read barrier emitted by GenerateFieldLoadWithBakerReadBarrier below.
- // /* HeapReference<Class> */ temp2 = src->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp2_loc,
- src.W(),
- class_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- // Note: if heap poisoning is on, we are comparing two unpoisoned references here.
- __ Cmp(temp1, temp2);
-
- if (optimizations.GetDestinationIsTypedObjectArray()) {
- vixl::aarch64::Label do_copy;
- __ B(&do_copy, eq);
- // /* HeapReference<Class> */ temp1 = temp1->component_type_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp1_loc,
- temp1,
- component_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- // /* HeapReference<Class> */ temp1 = temp1->super_class_
- // We do not need to emit a read barrier for the following
- // heap reference load, as `temp1` is only used in a
- // comparison with null below, and this reference is not
- // kept afterwards.
- __ Ldr(temp1, HeapOperand(temp1, super_offset));
- __ Cbnz(temp1, intrinsic_slow_path->GetEntryLabel());
- __ Bind(&do_copy);
- } else {
- __ B(intrinsic_slow_path->GetEntryLabel(), ne);
- }
- } else {
- // Non read barrier code.
-
- // /* HeapReference<Class> */ temp1 = dest->klass_
- __ Ldr(temp1, MemOperand(dest, class_offset));
- // /* HeapReference<Class> */ temp2 = src->klass_
- __ Ldr(temp2, MemOperand(src, class_offset));
- bool did_unpoison = false;
- if (!optimizations.GetDestinationIsNonPrimitiveArray() ||
- !optimizations.GetSourceIsNonPrimitiveArray()) {
- // One or two of the references need to be unpoisoned. Unpoison them
- // both to make the identity check valid.
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
- did_unpoison = true;
- }
-
- if (!optimizations.GetDestinationIsNonPrimitiveArray()) {
- // Bail out if the destination is not a non primitive array.
- // /* HeapReference<Class> */ temp3 = temp1->component_type_
- __ Ldr(temp3, HeapOperand(temp1, component_offset));
- __ Cbz(temp3, intrinsic_slow_path->GetEntryLabel());
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp3);
- // /* uint16_t */ temp3 = static_cast<uint16>(temp3->primitive_type_);
- __ Ldrh(temp3, HeapOperand(temp3, primitive_offset));
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Cbnz(temp3, intrinsic_slow_path->GetEntryLabel());
- }
-
- if (!optimizations.GetSourceIsNonPrimitiveArray()) {
- // Bail out if the source is not a non primitive array.
- // /* HeapReference<Class> */ temp3 = temp2->component_type_
- __ Ldr(temp3, HeapOperand(temp2, component_offset));
- __ Cbz(temp3, intrinsic_slow_path->GetEntryLabel());
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp3);
- // /* uint16_t */ temp3 = static_cast<uint16>(temp3->primitive_type_);
- __ Ldrh(temp3, HeapOperand(temp3, primitive_offset));
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Cbnz(temp3, intrinsic_slow_path->GetEntryLabel());
- }
-
- __ Cmp(temp1, temp2);
-
- if (optimizations.GetDestinationIsTypedObjectArray()) {
- vixl::aarch64::Label do_copy;
- __ B(&do_copy, eq);
- if (!did_unpoison) {
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
- }
- // /* HeapReference<Class> */ temp1 = temp1->component_type_
- __ Ldr(temp1, HeapOperand(temp1, component_offset));
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
- // /* HeapReference<Class> */ temp1 = temp1->super_class_
- __ Ldr(temp1, HeapOperand(temp1, super_offset));
- // No need to unpoison the result, we're comparing against null.
- __ Cbnz(temp1, intrinsic_slow_path->GetEntryLabel());
- __ Bind(&do_copy);
- } else {
- __ B(intrinsic_slow_path->GetEntryLabel(), ne);
- }
- }
- } else if (!optimizations.GetSourceIsNonPrimitiveArray()) {
+ __ Cmp(temp1, temp2);
+ if (optimizations.GetDestinationIsTypedObjectArray()) {
DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
+ vixl::aarch64::Label do_copy;
+ // For class match, we can skip the source type check regardless of the optimization flag.
+ __ B(&do_copy, eq);
+ // No read barrier is needed for reading a chain of constant references
+ // for comparing with null, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp1 = temp1->component_type_
+ __ Ldr(temp1, HeapOperand(temp1, component_offset));
+ codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
+ // /* HeapReference<Class> */ temp1 = temp1->super_class_
+ __ Ldr(temp1, HeapOperand(temp1, super_offset));
+ // No need to unpoison the result, we're comparing against null.
+ __ Cbnz(temp1, intrinsic_slow_path->GetEntryLabel());
// Bail out if the source is not a non primitive array.
- if (codegen_->EmitBakerReadBarrier()) {
- // /* HeapReference<Class> */ temp1 = src->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp1_loc,
- src.W(),
- class_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- // /* HeapReference<Class> */ temp2 = temp1->component_type_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- temp2_loc,
- temp1,
- component_offset,
- temp3_loc,
- /* needs_null_check= */ false,
- /* use_load_acquire= */ false);
- __ Cbz(temp2, intrinsic_slow_path->GetEntryLabel());
- // If heap poisoning is enabled, `temp2` has been unpoisoned
- // by the previous call to GenerateFieldLoadWithBakerReadBarrier.
- } else {
- // /* HeapReference<Class> */ temp1 = src->klass_
- __ Ldr(temp1, HeapOperand(src.W(), class_offset));
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp1);
- // /* HeapReference<Class> */ temp2 = temp1->component_type_
- __ Ldr(temp2, HeapOperand(temp1, component_offset));
- __ Cbz(temp2, intrinsic_slow_path->GetEntryLabel());
- codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+ if (!optimizations.GetSourceIsNonPrimitiveArray()) {
+ check_non_primitive_array_class(temp2, temp2);
+ }
+ __ Bind(&do_copy);
+ } else {
+ DCHECK(!optimizations.GetDestinationIsTypedObjectArray());
+ // For class match, we can skip the array type check completely if at least one of source
+ // and destination is known to be a non primitive array, otherwise one check is enough.
+ __ B(intrinsic_slow_path->GetEntryLabel(), ne);
+ if (!optimizations.GetDestinationIsNonPrimitiveArray() &&
+ !optimizations.GetSourceIsNonPrimitiveArray()) {
+ check_non_primitive_array_class(temp2, temp2);
}
- // /* uint16_t */ temp2 = static_cast<uint16>(temp2->primitive_type_);
- __ Ldrh(temp2, HeapOperand(temp2, primitive_offset));
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Cbnz(temp2, intrinsic_slow_path->GetEntryLabel());
+ }
+ } else if (!optimizations.GetSourceIsNonPrimitiveArray()) {
+ DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
+ // Bail out if the source is not a non primitive array.
+ // No read barrier is needed for reading a chain of constant references for comparing
+ // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp2 = src->klass_
+ __ Ldr(temp2, MemOperand(src, class_offset));
+ codegen_->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+ check_non_primitive_array_class(temp2, temp2);
+ }
+
+ if (length.IsConstant() && length.GetConstant()->AsIntConstant()->GetValue() == 0) {
+ // Null constant length: not need to emit the loop code at all.
+ } else {
+ vixl::aarch64::Label skip_copy_and_write_barrier;
+ if (length.IsRegister()) {
+ // Don't enter the copy loop if the length is null.
+ __ Cbz(WRegisterFrom(length), &skip_copy_and_write_barrier);
}
- if (length.IsConstant() && length.GetConstant()->AsIntConstant()->GetValue() == 0) {
- // Null constant length: not need to emit the loop code at all.
- } else {
+ {
+ // We use a block to end the scratch scope before the write barrier, thus
+ // freeing the temporary registers so they can be used in `MarkGCCard`.
+ UseScratchRegisterScope temps(masm);
+ bool emit_rb = codegen_->EmitBakerReadBarrier();
+ Register temp3;
+ Register tmp;
+ if (emit_rb) {
+ temp3 = WRegisterFrom(locations->GetTemp(2));
+ // Make sure `tmp` is not IP0, as it is clobbered by ReadBarrierMarkRegX entry points
+ // in ReadBarrierSystemArrayCopySlowPathARM64. Explicitly allocate the register IP1.
+ DCHECK(temps.IsAvailable(ip1));
+ temps.Exclude(ip1);
+ tmp = ip1.W();
+ } else {
+ temp3 = temps.AcquireW();
+ tmp = temps.AcquireW();
+ }
+
Register src_curr_addr = temp1.X();
Register dst_curr_addr = temp2.X();
Register src_stop_addr = temp3.X();
- vixl::aarch64::Label done;
const DataType::Type type = DataType::Type::kReference;
const int32_t element_size = DataType::Size(type);
- if (length.IsRegister()) {
- // Don't enter the copy loop if the length is null.
- __ Cbz(WRegisterFrom(length), &done);
- }
-
- if (codegen_->EmitBakerReadBarrier()) {
+ SlowPathCodeARM64* read_barrier_slow_path = nullptr;
+ if (emit_rb) {
// TODO: Also convert this intrinsic to the IsGcMarking strategy?
// SystemArrayCopy implementation for Baker read barriers (see
@@ -3471,21 +3334,6 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
// } while (src_ptr != end_ptr)
// }
- // Make sure `tmp` is not IP0, as it is clobbered by
- // ReadBarrierMarkRegX entry points in
- // ReadBarrierSystemArrayCopySlowPathARM64.
- DCHECK(temps.IsAvailable(ip0));
- temps.Exclude(ip0);
- Register tmp = temps.AcquireW();
- DCHECK_NE(LocationFrom(tmp).reg(), IP0);
- // Put IP0 back in the pool so that VIXL has at least one
- // scratch register available to emit macro-instructions (note
- // that IP1 is already used for `tmp`). Indeed some
- // macro-instructions used in GenSystemArrayCopyAddresses
- // (invoked hereunder) may require a scratch register (for
- // instance to emit a load with a large constant offset).
- temps.Include(ip0);
-
// /* int32_t */ monitor = src->monitor_
__ Ldr(tmp, HeapOperand(src.W(), monitor_offset));
// /* LockWord */ lock_word = LockWord(monitor)
@@ -3499,78 +3347,57 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) {
// on `tmp`.
__ Add(src.X(), src.X(), Operand(tmp.X(), LSR, 32));
- // Compute base source address, base destination address, and end
- // source address for System.arraycopy* intrinsics in `src_base`,
- // `dst_base` and `src_end` respectively.
- // Note that `src_curr_addr` is computed from from `src` (and
- // `src_pos`) here, and thus honors the artificial dependency
- // of `src` on `tmp`.
- GenSystemArrayCopyAddresses(masm,
- type,
- src,
- src_pos,
- dest,
- dest_pos,
- length,
- src_curr_addr,
- dst_curr_addr,
- src_stop_addr);
-
// Slow path used to copy array when `src` is gray.
- SlowPathCodeARM64* read_barrier_slow_path =
+ read_barrier_slow_path =
new (codegen_->GetScopedAllocator()) ReadBarrierSystemArrayCopySlowPathARM64(
invoke, LocationFrom(tmp));
codegen_->AddSlowPath(read_barrier_slow_path);
+ }
+ // Compute base source address, base destination address, and end
+ // source address for System.arraycopy* intrinsics in `src_base`,
+ // `dst_base` and `src_end` respectively.
+ // Note that `src_curr_addr` is computed from from `src` (and
+ // `src_pos`) here, and thus honors the artificial dependency
+ // of `src` on `tmp`.
+ GenSystemArrayCopyAddresses(masm,
+ type,
+ src,
+ src_pos,
+ dest,
+ dest_pos,
+ length,
+ src_curr_addr,
+ dst_curr_addr,
+ src_stop_addr);
+
+ if (emit_rb) {
// Given the numeric representation, it's enough to check the low bit of the rb_state.
static_assert(ReadBarrier::NonGrayState() == 0, "Expecting non-gray to have value 0");
static_assert(ReadBarrier::GrayState() == 1, "Expecting gray to have value 1");
__ Tbnz(tmp, LockWord::kReadBarrierStateShift, read_barrier_slow_path->GetEntryLabel());
+ }
- // Fast-path copy.
- // Iterate over the arrays and do a raw copy of the objects. We don't need to
- // poison/unpoison.
- vixl::aarch64::Label loop;
- __ Bind(&loop);
- __ Ldr(tmp, MemOperand(src_curr_addr, element_size, PostIndex));
- __ Str(tmp, MemOperand(dst_curr_addr, element_size, PostIndex));
- __ Cmp(src_curr_addr, src_stop_addr);
- __ B(&loop, ne);
-
+ // Iterate over the arrays and do a raw copy of the objects. We don't need to
+ // poison/unpoison.
+ vixl::aarch64::Label loop;
+ __ Bind(&loop);
+ __ Ldr(tmp, MemOperand(src_curr_addr, element_size, PostIndex));
+ __ Str(tmp, MemOperand(dst_curr_addr, element_size, PostIndex));
+ __ Cmp(src_curr_addr, src_stop_addr);
+ __ B(&loop, ne);
+
+ if (emit_rb) {
+ DCHECK(read_barrier_slow_path != nullptr);
__ Bind(read_barrier_slow_path->GetExitLabel());
- } else {
- // Non read barrier code.
- // Compute base source address, base destination address, and end
- // source address for System.arraycopy* intrinsics in `src_base`,
- // `dst_base` and `src_end` respectively.
- GenSystemArrayCopyAddresses(masm,
- type,
- src,
- src_pos,
- dest,
- dest_pos,
- length,
- src_curr_addr,
- dst_curr_addr,
- src_stop_addr);
- // Iterate over the arrays and do a raw copy of the objects. We don't need to
- // poison/unpoison.
- vixl::aarch64::Label loop;
- __ Bind(&loop);
- {
- Register tmp = temps.AcquireW();
- __ Ldr(tmp, MemOperand(src_curr_addr, element_size, PostIndex));
- __ Str(tmp, MemOperand(dst_curr_addr, element_size, PostIndex));
- }
- __ Cmp(src_curr_addr, src_stop_addr);
- __ B(&loop, ne);
}
- __ Bind(&done);
}
- }
- // We only need one card marking on the destination array.
- codegen_->MarkGCCard(dest.W(), Register(), /* emit_null_check= */ false);
+ // We only need one card marking on the destination array.
+ codegen_->MarkGCCard(dest.W(), Register(), /* emit_null_check= */ false);
+
+ __ Bind(&skip_copy_and_write_barrier);
+ }
__ Bind(intrinsic_slow_path->GetExitLabel());
}
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc
index 8b85ea4538..a43ab2f206 100644
--- a/compiler/optimizing/intrinsics_riscv64.cc
+++ b/compiler/optimizing/intrinsics_riscv64.cc
@@ -56,6 +56,7 @@ class ReadBarrierSystemArrayCopySlowPathRISCV64 : public SlowPathCodeRISCV64 {
XRegister tmp_reg = tmp_.AsRegister<XRegister>();
__ Bind(GetEntryLabel());
+ // The source range and destination pointer were initialized before entering the slow-path.
Riscv64Label slow_copy_loop;
__ Bind(&slow_copy_loop);
__ Loadwu(tmp_reg, src_curr_addr, 0);
@@ -928,6 +929,76 @@ void IntrinsicCodeGeneratorRISCV64::VisitStringIndexOfAfter(HInvoke* invoke) {
GenerateVisitStringIndexOf(invoke, GetAssembler(), codegen_, /* start_at_zero= */ false);
}
+void IntrinsicLocationsBuilderRISCV64::VisitStringNewStringFromBytes(HInvoke* invoke) {
+ LocationSummary* locations = new (allocator_) LocationSummary(
+ invoke, LocationSummary::kCallOnMainAndSlowPath, kIntrinsified);
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
+ locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3)));
+ locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
+}
+
+void IntrinsicCodeGeneratorRISCV64::VisitStringNewStringFromBytes(HInvoke* invoke) {
+ Riscv64Assembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+ XRegister byte_array = locations->InAt(0).AsRegister<XRegister>();
+
+ SlowPathCodeRISCV64* slow_path =
+ new (codegen_->GetScopedAllocator()) IntrinsicSlowPathRISCV64(invoke);
+ codegen_->AddSlowPath(slow_path);
+ __ Beqz(byte_array, slow_path->GetEntryLabel());
+
+ codegen_->InvokeRuntime(kQuickAllocStringFromBytes, invoke, invoke->GetDexPc(), slow_path);
+ CheckEntrypointTypes<kQuickAllocStringFromBytes, void*, void*, int32_t, int32_t, int32_t>();
+ __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderRISCV64::VisitStringNewStringFromChars(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kCallOnMainOnly, kIntrinsified);
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
+ locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
+}
+
+void IntrinsicCodeGeneratorRISCV64::VisitStringNewStringFromChars(HInvoke* invoke) {
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
+ codegen_->InvokeRuntime(kQuickAllocStringFromChars, invoke, invoke->GetDexPc());
+ CheckEntrypointTypes<kQuickAllocStringFromChars, void*, int32_t, int32_t, void*>();
+}
+
+void IntrinsicLocationsBuilderRISCV64::VisitStringNewStringFromString(HInvoke* invoke) {
+ LocationSummary* locations = new (allocator_) LocationSummary(
+ invoke, LocationSummary::kCallOnMainAndSlowPath, kIntrinsified);
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
+}
+
+void IntrinsicCodeGeneratorRISCV64::VisitStringNewStringFromString(HInvoke* invoke) {
+ Riscv64Assembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+ XRegister string_to_copy = locations->InAt(0).AsRegister<XRegister>();
+
+ SlowPathCodeRISCV64* slow_path =
+ new (codegen_->GetScopedAllocator()) IntrinsicSlowPathRISCV64(invoke);
+ codegen_->AddSlowPath(slow_path);
+ __ Beqz(string_to_copy, slow_path->GetEntryLabel());
+
+ codegen_->InvokeRuntime(kQuickAllocStringFromString, invoke, invoke->GetDexPc(), slow_path);
+ CheckEntrypointTypes<kQuickAllocStringFromString, void*, void*>();
+ __ Bind(slow_path->GetExitLabel());
+}
+
static void GenerateSet(CodeGeneratorRISCV64* codegen,
std::memory_order order,
Location value,
@@ -1497,112 +1568,116 @@ void IntrinsicCodeGeneratorRISCV64::VisitSystemArrayCopy(HInvoke* invoke) {
temp2,
optimizations.GetCountIsDestinationLength(),
dest_position_sign_checked);
- {
- // We use a block to end the scratch scope before the write barrier, thus
- // freeing the temporary registers so they can be used in `MarkGCCard`.
- ScratchRegisterScope srs(assembler);
- bool emit_rb = codegen_->EmitBakerReadBarrier();
- XRegister temp3 =
- emit_rb ? locations->GetTemp(2).AsRegister<XRegister>() : srs.AllocateXRegister();
-
- auto check_non_primitive_array_class = [&](XRegister klass, XRegister temp) {
- // No read barrier is needed for reading a chain of constant references for comparing
- // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
- // /* HeapReference<Class> */ temp = klass->component_type_
- __ Loadwu(temp, klass, component_offset);
- codegen_->MaybeUnpoisonHeapReference(temp);
- __ Beqz(temp, intrinsic_slow_path->GetEntryLabel());
- // /* uint16_t */ temp = static_cast<uint16>(klass->primitive_type_);
- __ Loadhu(temp, temp, primitive_offset);
- static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
- __ Bnez(temp, intrinsic_slow_path->GetEntryLabel());
- };
-
- if (!optimizations.GetDoesNotNeedTypeCheck()) {
- // Check whether all elements of the source array are assignable to the component
- // type of the destination array. We do two checks: the classes are the same,
- // or the destination is Object[]. If none of these checks succeed, we go to the
- // slow path.
- if (emit_rb) {
- // /* HeapReference<Class> */ temp1 = dest->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- Location::RegisterLocation(temp1),
- dest,
- class_offset,
- Location::RegisterLocation(temp3),
- /* needs_null_check= */ false);
- // /* HeapReference<Class> */ temp2 = src->klass_
- codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
- Location::RegisterLocation(temp2),
- src,
- class_offset,
- Location::RegisterLocation(temp3),
- /* needs_null_check= */ false);
- } else {
- // /* HeapReference<Class> */ temp1 = dest->klass_
- __ Loadwu(temp1, dest, class_offset);
- codegen_->MaybeUnpoisonHeapReference(temp1);
- // /* HeapReference<Class> */ temp2 = src->klass_
- __ Loadwu(temp2, src, class_offset);
- codegen_->MaybeUnpoisonHeapReference(temp2);
- }
+ auto check_non_primitive_array_class = [&](XRegister klass, XRegister temp) {
+ // No read barrier is needed for reading a chain of constant references for comparing
+ // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp = klass->component_type_
+ __ Loadwu(temp, klass, component_offset);
+ codegen_->MaybeUnpoisonHeapReference(temp);
+ // Check that the component type is not null.
+ __ Beqz(temp, intrinsic_slow_path->GetEntryLabel());
+ // Check that the component type is not a primitive.
+ // /* uint16_t */ temp = static_cast<uint16>(klass->primitive_type_);
+ __ Loadhu(temp, temp, primitive_offset);
+ static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
+ __ Bnez(temp, intrinsic_slow_path->GetEntryLabel());
+ };
- if (optimizations.GetDestinationIsTypedObjectArray()) {
- DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
- Riscv64Label do_copy;
- // For class match, we can skip the source type check regardless of the optimization flag.
- __ Beq(temp1, temp2, &do_copy);
- // /* HeapReference<Class> */ temp1 = temp1->component_type_
- // No read barrier is needed for reading a chain of constant references
- // for comparing with null, see `ReadBarrierOption`.
- __ Loadwu(temp1, temp1, component_offset);
- codegen_->MaybeUnpoisonHeapReference(temp1);
- // /* HeapReference<Class> */ temp1 = temp1->super_class_
- __ Loadwu(temp1, temp1, super_offset);
- // No need to unpoison the result, we're comparing against null.
- __ Bnez(temp1, intrinsic_slow_path->GetEntryLabel());
- // Bail out if the source is not a non primitive array.
- if (!optimizations.GetSourceIsNonPrimitiveArray()) {
- check_non_primitive_array_class(temp2, temp3);
- }
- __ Bind(&do_copy);
- } else {
- DCHECK(!optimizations.GetDestinationIsTypedObjectArray());
- // For class match, we can skip the array type check completely if at least one of source
- // and destination is known to be a non primitive array, otherwise one check is enough.
- __ Bne(temp1, temp2, intrinsic_slow_path->GetEntryLabel());
- if (!optimizations.GetDestinationIsNonPrimitiveArray() &&
- !optimizations.GetSourceIsNonPrimitiveArray()) {
- check_non_primitive_array_class(temp2, temp3);
- }
- }
- } else if (!optimizations.GetSourceIsNonPrimitiveArray()) {
- DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
- // Bail out if the source is not a non primitive array.
- // No read barrier is needed for reading a chain of constant references for comparing
- // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
- // /* HeapReference<Class> */ temp1 = src->klass_
+ if (!optimizations.GetDoesNotNeedTypeCheck()) {
+ // Check whether all elements of the source array are assignable to the component
+ // type of the destination array. We do two checks: the classes are the same,
+ // or the destination is Object[]. If none of these checks succeed, we go to the
+ // slow path.
+
+ if (codegen_->EmitBakerReadBarrier()) {
+ XRegister temp3 = locations->GetTemp(2).AsRegister<XRegister>();
+ // /* HeapReference<Class> */ temp1 = dest->klass_
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ Location::RegisterLocation(temp1),
+ dest,
+ class_offset,
+ Location::RegisterLocation(temp3),
+ /* needs_null_check= */ false);
+ // /* HeapReference<Class> */ temp2 = src->klass_
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ Location::RegisterLocation(temp2),
+ src,
+ class_offset,
+ Location::RegisterLocation(temp3),
+ /* needs_null_check= */ false);
+ } else {
+ // /* HeapReference<Class> */ temp1 = dest->klass_
+ __ Loadwu(temp1, dest, class_offset);
+ codegen_->MaybeUnpoisonHeapReference(temp1);
+ // /* HeapReference<Class> */ temp2 = src->klass_
__ Loadwu(temp2, src, class_offset);
codegen_->MaybeUnpoisonHeapReference(temp2);
- check_non_primitive_array_class(temp2, temp3);
}
- if (length.IsConstant() && length.GetConstant()->AsIntConstant()->GetValue() == 0) {
- // Null constant length: not need to emit the loop code at all.
+ if (optimizations.GetDestinationIsTypedObjectArray()) {
+ DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
+ Riscv64Label do_copy;
+ // For class match, we can skip the source type check regardless of the optimization flag.
+ __ Beq(temp1, temp2, &do_copy);
+ // No read barrier is needed for reading a chain of constant references
+ // for comparing with null, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp1 = temp1->component_type_
+ __ Loadwu(temp1, temp1, component_offset);
+ codegen_->MaybeUnpoisonHeapReference(temp1);
+ // /* HeapReference<Class> */ temp1 = temp1->super_class_
+ __ Loadwu(temp1, temp1, super_offset);
+ // No need to unpoison the result, we're comparing against null.
+ __ Bnez(temp1, intrinsic_slow_path->GetEntryLabel());
+ // Bail out if the source is not a non primitive array.
+ if (!optimizations.GetSourceIsNonPrimitiveArray()) {
+ check_non_primitive_array_class(temp2, temp2);
+ }
+ __ Bind(&do_copy);
} else {
+ DCHECK(!optimizations.GetDestinationIsTypedObjectArray());
+ // For class match, we can skip the array type check completely if at least one of source
+ // and destination is known to be a non primitive array, otherwise one check is enough.
+ __ Bne(temp1, temp2, intrinsic_slow_path->GetEntryLabel());
+ if (!optimizations.GetDestinationIsNonPrimitiveArray() &&
+ !optimizations.GetSourceIsNonPrimitiveArray()) {
+ check_non_primitive_array_class(temp2, temp2);
+ }
+ }
+ } else if (!optimizations.GetSourceIsNonPrimitiveArray()) {
+ DCHECK(optimizations.GetDestinationIsNonPrimitiveArray());
+ // Bail out if the source is not a non primitive array.
+ // No read barrier is needed for reading a chain of constant references for comparing
+ // with null, or for reading a constant primitive value, see `ReadBarrierOption`.
+ // /* HeapReference<Class> */ temp2 = src->klass_
+ __ Loadwu(temp2, src, class_offset);
+ codegen_->MaybeUnpoisonHeapReference(temp2);
+ check_non_primitive_array_class(temp2, temp2);
+ }
+
+ if (length.IsConstant() && length.GetConstant()->AsIntConstant()->GetValue() == 0) {
+ // Null constant length: not need to emit the loop code at all.
+ } else {
+ Riscv64Label skip_copy_and_write_barrier;
+ if (length.IsRegister()) {
+ // Don't enter the copy loop if the length is null.
+ __ Beqz(length.AsRegister<XRegister>(), &skip_copy_and_write_barrier);
+ }
+
+ {
+ // We use a block to end the scratch scope before the write barrier, thus
+ // freeing the scratch registers so they can be used in `MarkGCCard`.
+ ScratchRegisterScope srs(assembler);
+ bool emit_rb = codegen_->EmitBakerReadBarrier();
+ XRegister temp3 =
+ emit_rb ? locations->GetTemp(2).AsRegister<XRegister>() : srs.AllocateXRegister();
+
XRegister src_curr_addr = temp1;
XRegister dst_curr_addr = temp2;
XRegister src_stop_addr = temp3;
- Riscv64Label done;
const DataType::Type type = DataType::Type::kReference;
const int32_t element_size = DataType::Size(type);
- if (length.IsRegister()) {
- // Don't enter the copy loop if the length is null.
- __ Beqz(length.AsRegister<XRegister>(), &done);
- }
-
XRegister tmp = kNoXRegister;
SlowPathCodeRISCV64* read_barrier_slow_path = nullptr;
if (emit_rb) {
@@ -1688,17 +1763,18 @@ void IntrinsicCodeGeneratorRISCV64::VisitSystemArrayCopy(HInvoke* invoke) {
__ Addi(dst_curr_addr, dst_curr_addr, element_size);
// Bare: `TMP` shall not be clobbered.
__ Bne(src_curr_addr, src_stop_addr, &loop, /*is_bare=*/ true);
- __ Bind(&done);
if (emit_rb) {
DCHECK(read_barrier_slow_path != nullptr);
__ Bind(read_barrier_slow_path->GetExitLabel());
}
}
- }
- // We only need one card marking on the destination array.
- codegen_->MarkGCCard(dest, XRegister(kNoXRegister), /* emit_null_check= */ false);
+ // We only need one card marking on the destination array.
+ codegen_->MarkGCCard(dest, XRegister(kNoXRegister), /* emit_null_check= */ false);
+
+ __ Bind(&skip_copy_and_write_barrier);
+ }
__ Bind(intrinsic_slow_path->GetExitLabel());
}
@@ -4289,6 +4365,26 @@ void IntrinsicCodeGeneratorRISCV64::VisitThreadCurrentThread(HInvoke* invoke) {
__ Loadwu(out, TR, Thread::PeerOffset<kRiscv64PointerSize>().Int32Value());
}
+void IntrinsicLocationsBuilderRISCV64::VisitThreadInterrupted(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetOut(Location::RequiresRegister());
+}
+
+void IntrinsicCodeGeneratorRISCV64::VisitThreadInterrupted(HInvoke* invoke) {
+ LocationSummary* locations = invoke->GetLocations();
+ Riscv64Assembler* assembler = GetAssembler();
+ XRegister out = locations->Out().AsRegister<XRegister>();
+ Riscv64Label done;
+
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
+ __ Loadw(out, TR, Thread::InterruptedOffset<kRiscv64PointerSize>().Int32Value());
+ __ Beqz(out, &done);
+ __ Storew(Zero, TR, Thread::InterruptedOffset<kRiscv64PointerSize>().Int32Value());
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
+ __ Bind(&done);
+}
+
void IntrinsicLocationsBuilderRISCV64::VisitReachabilityFence(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 97c19a1665..5986a2f3a0 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -115,6 +115,7 @@ class ReadBarrierSystemArrayCopySlowPathX86 : public SlowPathCode {
Register value = locations->GetTemp(3).AsRegister<Register>();
__ Bind(GetEntryLabel());
+ // The `src_curr_addr` and `dst_curr_addr` were initialized before entering the slow-path.
GenArrayAddress(assembler, src_stop_addr, src_curr_addr, length, type, /*data_offset=*/ 0u);
NearLabel loop;
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index b65f57d71e..5177ac4d44 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -111,6 +111,7 @@ class ReadBarrierSystemArrayCopySlowPathX86_64 : public SlowPathCode {
CpuRegister src_stop_addr = locations->GetTemp(2).AsRegister<CpuRegister>();
__ Bind(GetEntryLabel());
+ // The `src_curr_addr` and `dst_curr_addr` were initialized before entering the slow-path.
GenArrayAddress(assembler, src_stop_addr, src_curr_addr, length, type, /*data_offset=*/ 0u);
NearLabel loop;
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 2e5ee84d76..e7b95c8d00 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -861,23 +861,33 @@ class LSEVisitor final : private HGraphDelegateVisitor {
}
void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
+ HInstruction* object = instruction->InputAt(0);
if (instruction->IsVolatile()) {
- HandleAcquireLoad(instruction);
- return;
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (!ref_info->IsSingletonAndRemovable()) {
+ HandleAcquireLoad(instruction);
+ return;
+ }
+ // Treat it as a normal load if it is a removable singleton.
}
- HInstruction* object = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(object, &field));
}
void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
+ HInstruction* object = instruction->InputAt(0);
if (instruction->IsVolatile()) {
- HandleReleaseStore(instruction);
- return;
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (!ref_info->IsSingletonAndRemovable()) {
+ HandleReleaseStore(instruction);
+ return;
+ }
+ // Treat it as a normal store if it is a removable singleton.
}
- HInstruction* object = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
HInstruction* value = instruction->InputAt(1);
size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field);
@@ -890,8 +900,8 @@ class LSEVisitor final : private HGraphDelegateVisitor {
return;
}
- HInstruction* cls = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
+ HInstruction* cls = instruction->InputAt(0);
VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(cls, &field));
}
@@ -901,14 +911,30 @@ class LSEVisitor final : private HGraphDelegateVisitor {
return;
}
- HInstruction* cls = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
+ HInstruction* cls = instruction->InputAt(0);
HInstruction* value = instruction->InputAt(1);
size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field);
VisitSetLocation(instruction, idx, value);
}
void VisitMonitorOperation(HMonitorOperation* monitor_op) override {
+ HInstruction* object = monitor_op->InputAt(0);
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (ref_info->IsSingletonAndRemovable()) {
+ // If the object is a removable singleton, we know that no other threads will have
+ // access to it, and we can remove the MonitorOperation instruction.
+ // MONITOR_ENTER throws when encountering a null object. If `object` is a removable
+ // singleton, it is guaranteed to be non-null so we don't have to worry about the NullCheck.
+ DCHECK(!object->CanBeNull());
+ monitor_op->GetBlock()->RemoveInstruction(monitor_op);
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedMonitorOp);
+ return;
+ }
+
+ // We detected a monitor operation that we couldn't remove. See also LSEVisitor::Run().
+ monitor_op->GetBlock()->GetGraph()->SetHasMonitorOperations(true);
if (monitor_op->IsEnter()) {
HandleAcquireLoad(monitor_op);
} else {
@@ -2439,8 +2465,7 @@ void LSEVisitor::ProcessLoopPhiWithUnknownInput(PhiPlaceholder loop_phi_with_unk
if (load_or_store->GetBlock() != block) {
break; // End of instructions from the current block.
}
- bool is_store = load_or_store->GetSideEffects().DoesAnyWrite();
- DCHECK_EQ(is_store, IsStore(load_or_store));
+ const bool is_store = IsStore(load_or_store);
HInstruction* stored_value = nullptr;
if (is_store) {
auto it = store_records_.find(load_or_store);
@@ -2772,6 +2797,10 @@ void LSEVisitor::FindStoresWritingOldValues() {
}
void LSEVisitor::Run() {
+ // 0. Set HasMonitorOperations to false. If we encounter some MonitorOperations that we can't
+ // remove, we will set it to true in VisitMonitorOperation.
+ GetGraph()->SetHasMonitorOperations(false);
+
// 1. Process blocks and instructions in reverse post order.
for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
VisitBasicBlock(block);
@@ -2813,14 +2842,22 @@ void LSEVisitor::FinishFullLSE() {
load->ReplaceWith(substitute);
load->GetBlock()->RemoveInstruction(load);
+ if ((load->IsInstanceFieldGet() && load->AsInstanceFieldGet()->IsVolatile()) ||
+ (load->IsStaticFieldGet() && load->AsStaticFieldGet()->IsVolatile())) {
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedVolatileLoad);
+ }
}
// Remove all the stores we can.
for (const LoadStoreRecord& record : loads_and_stores_) {
- bool is_store = record.load_or_store->GetSideEffects().DoesAnyWrite();
- DCHECK_EQ(is_store, IsStore(record.load_or_store));
- if (is_store && !kept_stores_.IsBitSet(record.load_or_store->GetId())) {
+ if (IsStore(record.load_or_store) && !kept_stores_.IsBitSet(record.load_or_store->GetId())) {
record.load_or_store->GetBlock()->RemoveInstruction(record.load_or_store);
+ if ((record.load_or_store->IsInstanceFieldSet() &&
+ record.load_or_store->AsInstanceFieldSet()->IsVolatile()) ||
+ (record.load_or_store->IsStaticFieldSet() &&
+ record.load_or_store->AsStaticFieldSet()->IsVolatile())) {
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedVolatileStore);
+ }
}
}
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 2cfe5b3ae2..e6cb3a2379 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1575,14 +1575,46 @@ void HInstruction::ReplaceWith(HInstruction* other) {
void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator,
HInstruction* replacement,
bool strictly_dominated) {
+ // Get the dominated blocks first to faster calculation of domination afterwards.
+ HGraph* graph = GetBlock()->GetGraph();
+ ArenaBitVector visited_blocks(graph->GetAllocator(),
+ graph->GetBlocks().size(),
+ /* expandable= */ false,
+ kArenaAllocMisc);
+ visited_blocks.ClearAllBits();
+ ScopedArenaAllocator allocator(graph->GetArenaStack());
+ ScopedArenaQueue<const HBasicBlock*> worklist(allocator.Adapter(kArenaAllocMisc));
+ HBasicBlock* dominator_block = dominator->GetBlock();
+ worklist.push(dominator_block);
+
+ while (!worklist.empty()) {
+ const HBasicBlock* current = worklist.front();
+ worklist.pop();
+ visited_blocks.SetBit(current->GetBlockId());
+ for (HBasicBlock* dominated : current->GetDominatedBlocks()) {
+ if (visited_blocks.IsBitSet(dominated->GetBlockId())) {
+ continue;
+ }
+ worklist.push(dominated);
+ }
+ }
+
const HUseList<HInstruction*>& uses = GetUses();
for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
HInstruction* user = it->GetUser();
+ HBasicBlock* block = user->GetBlock();
size_t index = it->GetIndex();
// Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
++it;
- const bool dominated =
- strictly_dominated ? dominator->StrictlyDominates(user) : dominator->Dominates(user);
+ bool dominated = false;
+ if (dominator_block == block) {
+ // Trickier case, call the other methods.
+ dominated =
+ strictly_dominated ? dominator->StrictlyDominates(user) : dominator->Dominates(user);
+ } else {
+ // Block domination.
+ dominated = visited_blocks.IsBitSet(block->GetBlockId());
+ }
if (dominated) {
user->ReplaceInput(replacement, index);
@@ -1590,9 +1622,8 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator,
// If the input flows from a block dominated by `dominator`, we can replace it.
// We do not perform this for catch phis as we don't have control flow support
// for their inputs.
- const ArenaVector<HBasicBlock*>& predecessors = user->GetBlock()->GetPredecessors();
- HBasicBlock* predecessor = predecessors[index];
- if (dominator->GetBlock()->Dominates(predecessor)) {
+ HBasicBlock* predecessor = block->GetPredecessors()[index];
+ if (visited_blocks.IsBitSet(predecessor->GetBlockId())) {
user->ReplaceInput(replacement, index);
}
}
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index a4df48c0ee..9c1506afa5 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -80,7 +80,6 @@ const char* OptimizationPassName(OptimizationPass pass) {
return BoundsCheckElimination::kBoundsCheckEliminationPassName;
case OptimizationPass::kLoadStoreElimination:
return LoadStoreElimination::kLoadStoreEliminationPassName;
- case OptimizationPass::kAggressiveConstantFolding:
case OptimizationPass::kConstantFolding:
return HConstantFolding::kConstantFoldingPassName;
case OptimizationPass::kDeadCodeElimination:
@@ -238,10 +237,6 @@ ArenaVector<HOptimization*> ConstructOptimizations(
case OptimizationPass::kConstantFolding:
opt = new (allocator) HConstantFolding(graph, stats, pass_name);
break;
- case OptimizationPass::kAggressiveConstantFolding:
- opt = new (allocator)
- HConstantFolding(graph, stats, pass_name, /* use_all_optimizations_ = */ true);
- break;
case OptimizationPass::kDeadCodeElimination:
opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
break;
@@ -257,7 +252,6 @@ ArenaVector<HOptimization*> ConstructOptimizations(
accessor.RegistersSize(),
/* total_number_of_instructions= */ 0,
/* parent= */ nullptr,
- /* caller_environment= */ nullptr,
/* depth= */ 0,
/* try_catch_inlining_allowed= */ true,
pass_name);
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index 57c5f4639c..55aa8f914b 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -67,7 +67,6 @@ class HOptimization : public ArenaObject<kArenaAllocOptimization> {
// field is preferred over a string lookup at places where performance matters.
// TODO: generate this table and lookup methods below automatically?
enum class OptimizationPass {
- kAggressiveConstantFolding,
kAggressiveInstructionSimplifier,
kBoundsCheckElimination,
kCHAGuardOptimization,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 5868f22ab8..8909a59ddf 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -368,10 +368,10 @@ class OptimizingCompiler final : public Compiler {
const DexCompilationUnit& dex_compilation_unit,
PassObserver* pass_observer) const;
- bool RunRequiredPasses(HGraph* graph,
- CodeGenerator* codegen,
- const DexCompilationUnit& dex_compilation_unit,
- PassObserver* pass_observer) const;
+ bool RunBaselineOptimizations(HGraph* graph,
+ CodeGenerator* codegen,
+ const DexCompilationUnit& dex_compilation_unit,
+ PassObserver* pass_observer) const;
std::vector<uint8_t> GenerateJitDebugInfo(const debug::MethodDebugInfo& method_debug_info);
@@ -444,10 +444,10 @@ static bool IsInstructionSetSupported(InstructionSet instruction_set) {
instruction_set == InstructionSet::kX86_64;
}
-bool OptimizingCompiler::RunRequiredPasses(HGraph* graph,
- CodeGenerator* codegen,
- const DexCompilationUnit& dex_compilation_unit,
- PassObserver* pass_observer) const {
+bool OptimizingCompiler::RunBaselineOptimizations(HGraph* graph,
+ CodeGenerator* codegen,
+ const DexCompilationUnit& dex_compilation_unit,
+ PassObserver* pass_observer) const {
switch (codegen->GetCompilerOptions().GetInstructionSet()) {
#if defined(ART_ENABLE_CODEGEN_arm)
case InstructionSet::kThumb2:
@@ -666,7 +666,7 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph,
OptDef(OptimizationPass::kGlobalValueNumbering),
// Simplification (TODO: only if GVN occurred).
OptDef(OptimizationPass::kSelectGenerator),
- OptDef(OptimizationPass::kAggressiveConstantFolding,
+ OptDef(OptimizationPass::kConstantFolding,
"constant_folding$after_gvn"),
OptDef(OptimizationPass::kInstructionSimplifier,
"instruction_simplifier$after_gvn"),
@@ -904,15 +904,21 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
}
}
- if (compilation_kind == CompilationKind::kBaseline && compiler_options.ProfileBranches()) {
- // Branch profiling currently doesn't support running optimizations.
- RunRequiredPasses(graph, codegen.get(), dex_compilation_unit, &pass_observer);
+ if (compilation_kind == CompilationKind::kBaseline) {
+ RunBaselineOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer);
} else {
RunOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer);
PassScope scope(WriteBarrierElimination::kWBEPassName, &pass_observer);
WriteBarrierElimination(graph, compilation_stats_.get()).Run();
}
+ RegisterAllocator::Strategy regalloc_strategy =
+ compiler_options.GetRegisterAllocationStrategy();
+ AllocateRegisters(graph,
+ codegen.get(),
+ &pass_observer,
+ regalloc_strategy,
+ compilation_stats_.get());
// If we are compiling baseline and we haven't created a profiling info for
// this method already, do it now.
if (jit != nullptr &&
@@ -929,14 +935,6 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
}
}
- RegisterAllocator::Strategy regalloc_strategy =
- compiler_options.GetRegisterAllocationStrategy();
- AllocateRegisters(graph,
- codegen.get(),
- &pass_observer,
- regalloc_strategy,
- compilation_stats_.get());
-
codegen->Compile();
pass_observer.DumpDisassembly();
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 4549af3cbf..60d18d2f24 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -50,6 +50,9 @@ enum class MethodCompilationStat {
kRemovedDeadPhi,
kRemovedTry,
kRemovedNullCheck,
+ kRemovedVolatileLoad,
+ kRemovedVolatileStore,
+ kRemovedMonitorOp,
kNotCompiledSkipped,
kNotCompiledInvalidBytecode,
kNotCompiledThrowCatchLoop,
diff --git a/compiler/optimizing/profiling_info_builder.cc b/compiler/optimizing/profiling_info_builder.cc
index 19795f5466..7888753830 100644
--- a/compiler/optimizing/profiling_info_builder.cc
+++ b/compiler/optimizing/profiling_info_builder.cc
@@ -20,7 +20,6 @@
#include "code_generator.h"
#include "driver/compiler_options.h"
#include "dex/code_item_accessors-inl.h"
-#include "inliner.h"
#include "jit/profiling_info.h"
#include "optimizing_compiler_stats.h"
#include "scoped_thread_state_change-inl.h"
@@ -43,53 +42,10 @@ void ProfilingInfoBuilder::Run() {
ProfilingInfo::Create(soa.Self(), GetGraph()->GetArtMethod(), inline_caches_));
}
-
-uint32_t ProfilingInfoBuilder::EncodeInlinedDexPc(const HInliner* inliner,
- const CompilerOptions& compiler_options,
- HInvoke* invoke) {
- DCHECK(inliner->GetCallerEnvironment() != nullptr);
- DCHECK(inliner->GetParent() != nullptr);
- std::vector<uint32_t> temp_vector;
- temp_vector.push_back(invoke->GetDexPc());
- while (inliner->GetCallerEnvironment() != nullptr) {
- temp_vector.push_back(inliner->GetCallerEnvironment()->GetDexPc());
- inliner = inliner->GetParent();
- }
-
- DCHECK_EQ(inliner->GetOutermostGraph(), inliner->GetGraph());
- return InlineCache::EncodeDexPc(
- inliner->GetOutermostGraph()->GetArtMethod(),
- temp_vector,
- compiler_options.GetInlineMaxCodeUnits());
-}
-
-static uint32_t EncodeDexPc(HInvoke* invoke, const CompilerOptions& compiler_options) {
- std::vector<uint32_t> dex_pcs;
- ArtMethod* outer_method = nullptr;
- for (HEnvironment* environment = invoke->GetEnvironment();
- environment != nullptr;
- environment = environment->GetParent()) {
- outer_method = environment->GetMethod();
- dex_pcs.push_back(environment->GetDexPc());
- }
-
- ScopedObjectAccess soa(Thread::Current());
- return InlineCache::EncodeDexPc(
- outer_method,
- dex_pcs,
- compiler_options.GetInlineMaxCodeUnits());
-}
-
void ProfilingInfoBuilder::HandleInvoke(HInvoke* invoke) {
+ DCHECK(!invoke->GetEnvironment()->IsFromInlinedInvoke());
if (IsInlineCacheUseful(invoke, codegen_)) {
- uint32_t dex_pc = EncodeDexPc(invoke, compiler_options_);
- if (dex_pc != kNoDexPc) {
- inline_caches_.push_back(dex_pc);
- } else {
- ScopedObjectAccess soa(Thread::Current());
- LOG(WARNING) << "Could not encode dex pc for "
- << invoke->GetResolvedMethod()->PrettyMethod();
- }
+ inline_caches_.push_back(invoke->GetDexPc());
}
}
@@ -125,15 +81,10 @@ bool ProfilingInfoBuilder::IsInlineCacheUseful(HInvoke* invoke, CodeGenerator* c
return true;
}
-InlineCache* ProfilingInfoBuilder::GetInlineCache(ProfilingInfo* info,
- const CompilerOptions& compiler_options,
- HInvoke* instruction) {
+InlineCache* ProfilingInfoBuilder::GetInlineCache(ProfilingInfo* info, HInvoke* instruction) {
+ DCHECK(!instruction->GetEnvironment()->IsFromInlinedInvoke());
ScopedObjectAccess soa(Thread::Current());
- uint32_t dex_pc = EncodeDexPc(instruction, compiler_options);
- if (dex_pc == kNoDexPc) {
- return nullptr;
- }
- return info->GetInlineCache(dex_pc);
+ return info->GetInlineCache(instruction->GetDexPc());
}
} // namespace art
diff --git a/compiler/optimizing/profiling_info_builder.h b/compiler/optimizing/profiling_info_builder.h
index c8dc59a03c..2185b0eed3 100644
--- a/compiler/optimizing/profiling_info_builder.h
+++ b/compiler/optimizing/profiling_info_builder.h
@@ -24,7 +24,6 @@ namespace art HIDDEN {
class CodeGenerator;
class CompilerOptions;
-class HInliner;
class InlineCache;
class ProfilingInfo;
@@ -43,13 +42,8 @@ class ProfilingInfoBuilder : public HGraphDelegateVisitor {
static constexpr const char* kProfilingInfoBuilderPassName =
"profiling_info_builder";
- static InlineCache* GetInlineCache(ProfilingInfo* info,
- const CompilerOptions& compiler_options,
- HInvoke* invoke);
+ static InlineCache* GetInlineCache(ProfilingInfo* info, HInvoke* invoke);
static bool IsInlineCacheUseful(HInvoke* invoke, CodeGenerator* codegen);
- static uint32_t EncodeInlinedDexPc(
- const HInliner* inliner, const CompilerOptions& compiler_options, HInvoke* invoke)
- REQUIRES_SHARED(Locks::mutator_lock_);
private:
void VisitInvokeVirtual(HInvokeVirtual* invoke) override;
@@ -58,7 +52,7 @@ class ProfilingInfoBuilder : public HGraphDelegateVisitor {
void HandleInvoke(HInvoke* invoke);
CodeGenerator* codegen_;
- const CompilerOptions& compiler_options_;
+ [[maybe_unused]] const CompilerOptions& compiler_options_;
std::vector<uint32_t> inline_caches_;
DISALLOW_COPY_AND_ASSIGN(ProfilingInfoBuilder);
diff --git a/libartbase/base/atomic.h b/libartbase/base/atomic.h
index 226a088a40..91f1982720 100644
--- a/libartbase/base/atomic.h
+++ b/libartbase/base/atomic.h
@@ -125,6 +125,14 @@ class PACKED(sizeof(T)) Atomic : public std::atomic<T> {
}
};
+// Increment a debug- or statistics-only counter when there is a single writer, especially if
+// concurrent reads are uncommon. Usually appreciably faster in this case.
+// NOT suitable as an approximate counter with multiple writers.
+template <typename T>
+void IncrementStatsCounter(std::atomic<T>* a) {
+ a->store(a->load(std::memory_order_relaxed) + 1, std::memory_order_relaxed);
+}
+
using AtomicInteger = Atomic<int32_t>;
static_assert(sizeof(AtomicInteger) == sizeof(int32_t), "Weird AtomicInteger size");
diff --git a/libartservice/service/api/system-server-current.txt b/libartservice/service/api/system-server-current.txt
index 9c1220edbc..de687d1add 100644
--- a/libartservice/service/api/system-server-current.txt
+++ b/libartservice/service/api/system-server-current.txt
@@ -6,6 +6,7 @@ package com.android.server.art {
ctor public ArtManagerLocal(@NonNull android.content.Context);
method public void addDexoptDoneCallback(boolean, @NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.DexoptDoneCallback);
method public void cancelBackgroundDexoptJob();
+ method public void clearAdjustCompilerFilterCallback();
method @NonNull public void clearAppProfiles(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String);
method public void clearBatchDexoptStartCallback();
method public void clearScheduleBackgroundDexoptJobCallback();
@@ -22,6 +23,7 @@ package com.android.server.art {
method public void printShellCommandHelp(@NonNull java.io.PrintWriter);
method public void removeDexoptDoneCallback(@NonNull com.android.server.art.ArtManagerLocal.DexoptDoneCallback);
method public int scheduleBackgroundDexoptJob();
+ method public void setAdjustCompilerFilterCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback);
method public void setBatchDexoptStartCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.BatchDexoptStartCallback);
method public void setScheduleBackgroundDexoptJobCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.ScheduleBackgroundDexoptJobCallback);
method @NonNull public android.os.ParcelFileDescriptor snapshotAppProfile(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String, @Nullable String) throws com.android.server.art.ArtManagerLocal.SnapshotProfileException;
@@ -30,6 +32,10 @@ package com.android.server.art {
method public void unscheduleBackgroundDexoptJob();
}
+ public static interface ArtManagerLocal.AdjustCompilerFilterCallback {
+ method @NonNull public String onAdjustCompilerFilter(@NonNull String, @NonNull String, @NonNull String);
+ }
+
public static interface ArtManagerLocal.BatchDexoptStartCallback {
method public void onBatchDexoptStart(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull com.android.server.art.model.BatchDexoptParams.Builder, @NonNull android.os.CancellationSignal);
}
diff --git a/libartservice/service/java/com/android/server/art/ArtFileManager.java b/libartservice/service/java/com/android/server/art/ArtFileManager.java
index 3db91642b6..51e8462b0c 100644
--- a/libartservice/service/java/com/android/server/art/ArtFileManager.java
+++ b/libartservice/service/java/com/android/server/art/ArtFileManager.java
@@ -69,13 +69,14 @@ public class ArtFileManager {
}
/**
- * @param excludeNotFound If true, excludes secondary dex files that are not found on the
- * filesystem.
+ * @param excludeObsoleteDexesAndLoaders If true, excludes secondary dex files and loaders based
+ * on file visibility. See details in {@link
+ * DexUseManagerLocal#getCheckedSecondaryDexInfo}.
*/
@NonNull
public List<Pair<DetailedDexInfo, Abi>> getDexAndAbis(@NonNull PackageState pkgState,
@NonNull AndroidPackage pkg, boolean forPrimaryDex, boolean forSecondaryDex,
- boolean excludeNotFound) {
+ boolean excludeObsoleteDexesAndLoaders) {
List<Pair<DetailedDexInfo, Abi>> dexAndAbis = new ArrayList<>();
if (forPrimaryDex) {
for (DetailedPrimaryDexInfo dexInfo :
@@ -86,9 +87,9 @@ public class ArtFileManager {
}
}
if (forSecondaryDex) {
- List<? extends SecondaryDexInfo> dexInfos = excludeNotFound
- ? mInjector.getDexUseManager().getFilteredDetailedSecondaryDexInfo(
- pkgState.getPackageName())
+ List<? extends SecondaryDexInfo> dexInfos = excludeObsoleteDexesAndLoaders
+ ? mInjector.getDexUseManager().getCheckedSecondaryDexInfo(
+ pkgState.getPackageName(), true /* excludeObsoleteDexesAndLoaders */)
: mInjector.getDexUseManager().getSecondaryDexInfo(pkgState.getPackageName());
for (SecondaryDexInfo dexInfo : dexInfos) {
for (Abi abi : Utils.getAllAbisForNames(dexInfo.abiNames(), pkgState)) {
@@ -141,7 +142,7 @@ public class ArtFileManager {
for (Pair<DetailedDexInfo, Abi> pair :
getDexAndAbis(pkgState, pkg, true /* forPrimaryDex */, true /* forSecondaryDex */,
- true /* excludeNotFound */)) {
+ true /* excludeObsoleteDexesAndLoaders */)) {
DetailedDexInfo dexInfo = pair.first;
Abi abi = pair.second;
try {
@@ -178,9 +179,14 @@ public class ArtFileManager {
return UsableArtifactLists.create(artifacts, vdexFiles, runtimeArtifacts);
}
+ /**
+ * @param excludeForObsoleteDexesAndLoaders If true, excludes profiles for secondary dex files
+ * and loaders based on file visibility. See details in {@link
+ * DexUseManagerLocal#getCheckedSecondaryDexInfo}.
+ */
@NonNull
public ProfileLists getProfiles(@NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
- boolean alsoForSecondaryDex, boolean excludeDexNotFound) {
+ boolean alsoForSecondaryDex, boolean excludeForObsoleteDexesAndLoaders) {
List<ProfilePath> refProfiles = new ArrayList<>();
List<ProfilePath> curProfiles = new ArrayList<>();
@@ -190,9 +196,9 @@ public class ArtFileManager {
PrimaryDexUtils.getCurProfiles(mInjector.getUserManager(), pkgState, dexInfo));
}
if (alsoForSecondaryDex) {
- List<? extends SecondaryDexInfo> dexInfos = excludeDexNotFound
- ? mInjector.getDexUseManager().getFilteredDetailedSecondaryDexInfo(
- pkgState.getPackageName())
+ List<? extends SecondaryDexInfo> dexInfos = excludeForObsoleteDexesAndLoaders
+ ? mInjector.getDexUseManager().getCheckedSecondaryDexInfo(
+ pkgState.getPackageName(), true /* excludeForObsoleteDexesAndLoaders */)
: mInjector.getDexUseManager().getSecondaryDexInfo(pkgState.getPackageName());
for (SecondaryDexInfo dexInfo : dexInfos) {
refProfiles.add(AidlUtils.buildProfilePathForSecondaryRef(dexInfo.dexPath()));
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index b8e05494f6..ee253f9ff0 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -248,7 +248,8 @@ public final class ArtManagerLocal {
AndroidPackage pkg = Utils.getPackageOrThrow(pkgState);
List<Pair<DetailedDexInfo, Abi>> dexAndAbis = mInjector.getArtFileManager().getDexAndAbis(
pkgState, pkg, (flags & ArtFlags.FLAG_FOR_PRIMARY_DEX) != 0,
- (flags & ArtFlags.FLAG_FOR_SECONDARY_DEX) != 0, false /* excludeNotFound */);
+ (flags & ArtFlags.FLAG_FOR_SECONDARY_DEX) != 0,
+ false /* excludeObsoleteDexesAndLoaders */);
try {
List<DexContainerFileDexoptStatus> statuses = new ArrayList<>();
@@ -305,8 +306,8 @@ public final class ArtManagerLocal {
// We want to delete as many profiles as possible, so this deletes profiles of all known
// secondary dex files. If there are unknown secondary dex files, their profiles will be
// deleted by `cleanup`.
- ProfileLists list = mInjector.getArtFileManager().getProfiles(
- pkgState, pkg, true /* alsoForSecondaryDex */, false /* excludeDexNotFound */);
+ ProfileLists list = mInjector.getArtFileManager().getProfiles(pkgState, pkg,
+ true /* alsoForSecondaryDex */, false /* excludeForObsoleteDexesAndLoaders */);
for (ProfilePath profile : list.allProfiles()) {
mInjector.getArtd().deleteProfile(profile);
}
@@ -804,7 +805,8 @@ public final class ArtManagerLocal {
if (Utils.canDexoptPackage(appPkgState, null /* appHibernationManager */)) {
AndroidPackage appPkg = Utils.getPackageOrThrow(appPkgState);
ProfileLists list = mInjector.getArtFileManager().getProfiles(appPkgState, appPkg,
- false /* alsoForSecondaryDex */, true /* excludeDexNotFound */);
+ false /* alsoForSecondaryDex */,
+ true /* excludeForObsoleteDexesAndLoaders */);
profiles.addAll(list.allProfiles());
}
});
@@ -908,8 +910,8 @@ public final class ArtManagerLocal {
artifactsSize += artd.getRuntimeArtifactsSize(runtimeArtifacts);
}
- ProfileLists profileLists = mInjector.getArtFileManager().getProfiles(
- pkgState, pkg, true /* alsoForSecondaryDex */, true /* excludeDexNotFound */);
+ ProfileLists profileLists = mInjector.getArtFileManager().getProfiles(pkgState, pkg,
+ true /* alsoForSecondaryDex */, true /* excludeForObsoleteDexesAndLoaders */);
for (ProfilePath profile : profileLists.refProfiles()) {
refProfilesSize += artd.getProfileSize(profile);
}
@@ -926,6 +928,28 @@ public final class ArtManagerLocal {
}
/**
+ * Overrides the compiler filter of a package. The callback is called whenever a package is
+ * going to be dexopted. This method is thread-safe.
+ */
+ @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public void setAdjustCompilerFilterCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AdjustCompilerFilterCallback callback) {
+ mInjector.getConfig().setAdjustCompilerFilterCallback(executor, callback);
+ }
+
+ /**
+ * Clears the callback set by {@link
+ * #setAdjustCompilerFilterCallback(Executor, AdjustCompilerFilterCallback)}. This
+ * method is thread-safe.
+ */
+ @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public void clearAdjustCompilerFilterCallback() {
+ mInjector.getConfig().clearAdjustCompilerFilterCallback();
+ }
+
+ /**
* Cleans up obsolete profiles and artifacts.
*
* This is done in a mark-and-sweep approach.
@@ -960,7 +984,8 @@ public final class ArtManagerLocal {
}
AndroidPackage pkg = Utils.getPackageOrThrow(pkgState);
ProfileLists profileLists = mInjector.getArtFileManager().getProfiles(pkgState, pkg,
- true /* alsoForSecondaryDex */, true /* excludeDexNotFound */);
+ true /* alsoForSecondaryDex */,
+ true /* excludeForObsoleteDexesAndLoaders */);
profilesToKeep.addAll(profileLists.allProfiles());
if (!Utils.shouldSkipDexoptDueToHibernation(
pkgState, mInjector.getAppHibernationManager())) {
@@ -1240,6 +1265,55 @@ public final class ArtManagerLocal {
void onDexoptDone(@NonNull DexoptResult result);
}
+ /** @hide */
+ @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+ @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public interface AdjustCompilerFilterCallback {
+ /**
+ * Returns the adjusted compiler filter for the given package. If a package doesn't need
+ * adjustment, this callback must return {@code originalCompilerFilter}. The callback must
+ * be able to handle unknown {@code originalCompilerFilter} and unknown {@code reason}
+ * because more compiler filters and reasons may be added in the future.
+ *
+ * The returned compiler filter overrides any compiler filter set by {@link
+ * DexoptParams.Builder#setCompilerFilter}, no matter the dexopt is initiated by a
+ * {@link #dexoptPackage} API call or any automatic batch dexopt (e.g., dexopt on boot and
+ * background dexopt).
+ *
+ * This callback is useful for:
+ * - Consistently overriding the compiler filter regardless of the dexopt initiator, for
+ * some performance-sensitive packages.
+ * - Providing a compiler filter for specific packages during batch dexopt.
+ *
+ * The actual compiler filter to be used for dexopt will be determined in the following
+ * order:
+ *
+ * 1. The default compiler filter for the given reason.
+ * 2. The compiler filter set explicitly by {@link DexoptParams.Builder#setCompilerFilter}.
+ * 3. ART Service's internal adjustments to upgrade the compiler filter, based on whether
+ * the package is System UI, etc.
+ * 4. The adjustments made by this callback.
+ * 5. ART Service's internal adjustments to downgrade the compiler filter, based on whether
+ * the profile is available, etc.
+ *
+ * @param packageName the name of the package to be dexopted
+ * @param originalCompilerFilter the compiler filter before adjustment. This is the result
+ * of step 3 described above. It would be the input to step 5 described above if
+ * it wasn't for this callback.
+ * @param reason the compilation reason of this dexopt operation. It is a string defined in
+ * {@link ReasonMapping} or a custom string passed to {@link
+ * DexoptParams.Builder#Builder(String)}
+ *
+ * @return the compiler filter after adjustment. This will be the input to step 5 described
+ * above
+ */
+ @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+ @NonNull
+ String onAdjustCompilerFilter(@NonNull String packageName,
+ @NonNull String originalCompilerFilter, @NonNull String reason);
+ }
+
/**
* Represents an error that happens when snapshotting profiles.
*
diff --git a/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java b/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java
index b9d0afe0d9..e9ef1a3e37 100644
--- a/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java
@@ -230,23 +230,30 @@ public class DexUseManagerLocal {
* method doesn't take dex file visibility into account, so it can only be used for debugging
* purpose, such as dumpsys.
*
- * @see #getFilteredDetailedSecondaryDexInfo(String)
+ * @see #getCheckedSecondaryDexInfo(String)
* @hide
*/
public @NonNull List<? extends SecondaryDexInfo> getSecondaryDexInfo(
@NonNull String packageName) {
- return getSecondaryDexInfoImpl(packageName, false /* checkDexFile */);
+ return getSecondaryDexInfoImpl(
+ packageName, false /* checkDexFile */, false /* excludeObsoleteDexesAndLoaders */);
}
/**
* Same as above, but requires disk IO, and returns the detailed information, including dex file
- * visibility, filtered by dex file existence and visibility.
+ * visibility.
+ *
+ * @param excludeObsoleteDexesAndLoaders If true, excludes secondary dex files and loaders based
+ * on file visibility. More specifically, excludes loaders that can no longer load a
+ * secondary dex file due to a file visibility change, and excludes secondary dex files
+ * that are not found or only have obsolete loaders
*
* @hide
*/
- public @NonNull List<DetailedSecondaryDexInfo> getFilteredDetailedSecondaryDexInfo(
- @NonNull String packageName) {
- return getSecondaryDexInfoImpl(packageName, true /* checkDexFile */);
+ public @NonNull List<CheckedSecondaryDexInfo> getCheckedSecondaryDexInfo(
+ @NonNull String packageName, boolean excludeObsoleteDexesAndLoaders) {
+ return getSecondaryDexInfoImpl(
+ packageName, true /* checkDexFile */, excludeObsoleteDexesAndLoaders);
}
/**
@@ -282,20 +289,22 @@ public class DexUseManagerLocal {
}
/**
- * @param checkDexFile if true, check the existence and visibility of the dex files, and filter
- * the results accordingly. Note that the value of the {@link
- * DetailedSecondaryDexInfo#isDexFilePublic()} field is undefined if this argument is
- * false.
+ * @param checkDexFile if true, check the existence and visibility of the dex files. Note that
+ * the value of the {@link CheckedSecondaryDexInfo#fileVisibility()} field is undefined
+ * if this argument is false
+ * @param excludeObsoleteDexesAndLoaders see {@link #getCheckedSecondaryDexInfo}. Only takes
+ * effect if {@code checkDexFile} is true
*/
- private @NonNull List<DetailedSecondaryDexInfo> getSecondaryDexInfoImpl(
- @NonNull String packageName, boolean checkDexFile) {
+ private @NonNull List<CheckedSecondaryDexInfo> getSecondaryDexInfoImpl(
+ @NonNull String packageName, boolean checkDexFile,
+ boolean excludeObsoleteDexesAndLoaders) {
synchronized (mLock) {
PackageDexUse packageDexUse =
mDexUse.mPackageDexUseByOwningPackageName.get(packageName);
if (packageDexUse == null) {
return List.of();
}
- var results = new ArrayList<DetailedSecondaryDexInfo>();
+ var results = new ArrayList<CheckedSecondaryDexInfo>();
for (var entry : packageDexUse.mSecondaryDexUseByDexFile.entrySet()) {
String dexPath = entry.getKey();
SecondaryDexUse secondaryDexUse = entry.getValue();
@@ -303,12 +312,13 @@ public class DexUseManagerLocal {
@FileVisibility
int visibility = checkDexFile ? getDexFileVisibility(dexPath)
: FileVisibility.OTHER_READABLE;
- if (visibility == FileVisibility.NOT_FOUND) {
+ if (visibility == FileVisibility.NOT_FOUND && excludeObsoleteDexesAndLoaders) {
continue;
}
Map<DexLoader, SecondaryDexUseRecord> filteredRecordByLoader;
- if (visibility == FileVisibility.OTHER_READABLE) {
+ if (visibility == FileVisibility.OTHER_READABLE
+ || !excludeObsoleteDexesAndLoaders) {
filteredRecordByLoader = secondaryDexUse.mRecordByLoader;
} else {
// Only keep the entry that belongs to the same app.
@@ -347,10 +357,9 @@ public class DexUseManagerLocal {
.map(record -> Utils.assertNonEmpty(record.mAbiName))
.collect(Collectors.toSet());
Set<DexLoader> loaders = Set.copyOf(filteredRecordByLoader.keySet());
- results.add(DetailedSecondaryDexInfo.create(dexPath,
+ results.add(CheckedSecondaryDexInfo.create(dexPath,
Objects.requireNonNull(secondaryDexUse.mUserHandle), clc, distinctAbiNames,
- loaders, isUsedByOtherApps(loaders, packageName),
- visibility == FileVisibility.OTHER_READABLE));
+ loaders, isUsedByOtherApps(loaders, packageName), visibility));
}
return Collections.unmodifiableList(results);
}
@@ -857,22 +866,19 @@ public class DexUseManagerLocal {
*/
@Immutable
@AutoValue
- public abstract static class DetailedSecondaryDexInfo
+ public abstract static class CheckedSecondaryDexInfo
extends SecondaryDexInfo implements DetailedDexInfo {
- static DetailedSecondaryDexInfo create(@NonNull String dexPath,
+ static CheckedSecondaryDexInfo create(@NonNull String dexPath,
@NonNull UserHandle userHandle, @NonNull String displayClassLoaderContext,
@NonNull Set<String> abiNames, @NonNull Set<DexLoader> loaders,
- boolean isUsedByOtherApps, boolean isDexFilePublic) {
- return new AutoValue_DexUseManagerLocal_DetailedSecondaryDexInfo(dexPath, userHandle,
+ boolean isUsedByOtherApps, @FileVisibility int fileVisibility) {
+ return new AutoValue_DexUseManagerLocal_CheckedSecondaryDexInfo(dexPath, userHandle,
displayClassLoaderContext, Collections.unmodifiableSet(abiNames),
- Collections.unmodifiableSet(loaders), isUsedByOtherApps, isDexFilePublic);
+ Collections.unmodifiableSet(loaders), isUsedByOtherApps, fileVisibility);
}
- /**
- * Returns true if the filesystem permission of the dex file has the "read" bit for "others"
- * (S_IROTH).
- */
- public abstract boolean isDexFilePublic();
+ /** Indicates the visibility of the dex file. */
+ public abstract @FileVisibility int fileVisibility();
}
private static class DexUse {
diff --git a/libartservice/service/java/com/android/server/art/DexoptHelper.java b/libartservice/service/java/com/android/server/art/DexoptHelper.java
index c04a9811c8..fda43ca919 100644
--- a/libartservice/service/java/com/android/server/art/DexoptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexoptHelper.java
@@ -347,14 +347,16 @@ public class DexoptHelper {
PrimaryDexopter getPrimaryDexopter(@NonNull PackageState pkgState,
@NonNull AndroidPackage pkg, @NonNull DexoptParams params,
@NonNull CancellationSignal cancellationSignal) {
- return new PrimaryDexopter(mContext, pkgState, pkg, params, cancellationSignal);
+ return new PrimaryDexopter(
+ mContext, mConfig, pkgState, pkg, params, cancellationSignal);
}
@NonNull
SecondaryDexopter getSecondaryDexopter(@NonNull PackageState pkgState,
@NonNull AndroidPackage pkg, @NonNull DexoptParams params,
@NonNull CancellationSignal cancellationSignal) {
- return new SecondaryDexopter(mContext, pkgState, pkg, params, cancellationSignal);
+ return new SecondaryDexopter(
+ mContext, mConfig, pkgState, pkg, params, cancellationSignal);
}
@NonNull
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index fff39351c0..8713ff19bb 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -16,11 +16,13 @@
package com.android.server.art;
+import static com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback;
import static com.android.server.art.OutputArtifacts.PermissionSettings;
import static com.android.server.art.ProfilePath.TmpProfilePath;
import static com.android.server.art.Utils.Abi;
import static com.android.server.art.Utils.InitProfileResult;
import static com.android.server.art.model.ArtFlags.DexoptFlags;
+import static com.android.server.art.model.Config.Callback;
import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
import android.R;
@@ -45,6 +47,7 @@ import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalManagerRegistry;
import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
import com.android.server.art.model.DetailedDexInfo;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
@@ -300,6 +303,8 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
return results;
}
+ // The javadoc on `AdjustCompilerFilterCallback.onAdjustCompilerFilter` may need updating when
+ // this method is changed.
@NonNull
private String adjustCompilerFilter(
@NonNull String targetCompilerFilter, @NonNull DexInfoType dexInfo) {
@@ -312,6 +317,17 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
targetCompilerFilter = "speed-profile";
}
+ Callback<AdjustCompilerFilterCallback, Void> callback =
+ mInjector.getConfig().getAdjustCompilerFilterCallback();
+ if (callback != null) {
+ // Local variables passed to the lambda must be final or effectively final.
+ final String originalCompilerFilter = targetCompilerFilter;
+ targetCompilerFilter = Utils.executeAndWait(callback.executor(), () -> {
+ return callback.get().onAdjustCompilerFilter(
+ mPkgState.getPackageName(), originalCompilerFilter, mParams.getReason());
+ });
+ }
+
// Code below should only downgrade the compiler filter. Don't upgrade the compiler filter
// beyond this point!
@@ -688,9 +704,11 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public static class Injector {
@NonNull private final Context mContext;
+ @NonNull private final Config mConfig;
- public Injector(@NonNull Context context) {
+ public Injector(@NonNull Context context, @NonNull Config config) {
mContext = context;
+ mConfig = config;
// Call the getters for various dependencies, to ensure correct initialization order.
getUserManager();
@@ -747,5 +765,10 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
}
return -1;
}
+
+ @NonNull
+ public Config getConfig() {
+ return mConfig;
+ }
}
}
diff --git a/libartservice/service/java/com/android/server/art/DumpHelper.java b/libartservice/service/java/com/android/server/art/DumpHelper.java
index 2a640ec48d..d9523b9fae 100644
--- a/libartservice/service/java/com/android/server/art/DumpHelper.java
+++ b/libartservice/service/java/com/android/server/art/DumpHelper.java
@@ -16,8 +16,8 @@
package com.android.server.art;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.DexUseManagerLocal.DexLoader;
-import static com.android.server.art.DexUseManagerLocal.SecondaryDexInfo;
import static com.android.server.art.model.DexoptStatus.DexContainerFileDexoptStatus;
import android.annotation.NonNull;
@@ -99,11 +99,13 @@ public class DumpHelper {
mInjector.getArtManagerLocal()
.getDexoptStatus(snapshot, packageName)
.getDexContainerFileDexoptStatuses();
- Map<String, SecondaryDexInfo> secondaryDexInfoByDexPath =
+ Map<String, CheckedSecondaryDexInfo> secondaryDexInfoByDexPath =
mInjector.getDexUseManager()
- .getSecondaryDexInfo(packageName)
+ .getCheckedSecondaryDexInfo(
+ packageName, false /* excludeObsoleteDexesAndLoaders */)
.stream()
- .collect(Collectors.toMap(SecondaryDexInfo::dexPath, Function.identity()));
+ .collect(Collectors.toMap(
+ CheckedSecondaryDexInfo::dexPath, Function.identity()));
// Use LinkedHashMap to keep the order. They are ordered by their split indexes.
var primaryStatusesByDexPath =
@@ -157,9 +159,9 @@ public class DumpHelper {
private void dumpSecondaryDex(@NonNull IndentingPrintWriter ipw,
@NonNull PackageManagerLocal.FilteredSnapshot snapshot,
List<DexContainerFileDexoptStatus> fileStatuses, @NonNull String packageName,
- @NonNull SecondaryDexInfo info) {
+ @NonNull CheckedSecondaryDexInfo info) {
String dexPath = fileStatuses.get(0).getDexContainerFile();
- @FileVisibility int visibility = getDexFileVisibility(dexPath);
+ @FileVisibility int visibility = info.fileVisibility();
ipw.println(dexPath
+ (visibility == FileVisibility.NOT_FOUND
? " (removed)"
@@ -236,15 +238,6 @@ public class DumpHelper {
return result.toString();
}
- private @FileVisibility int getDexFileVisibility(@NonNull String dexPath) {
- try {
- return mInjector.getArtd().getDexFileVisibility(dexPath);
- } catch (ServiceSpecificException | RemoteException e) {
- Log.e(TAG, "Failed to get visibility of " + dexPath, e);
- return FileVisibility.NOT_FOUND;
- }
- }
-
/** Injector pattern for testing purpose. */
@VisibleForTesting
public static class Injector {
@@ -264,10 +257,5 @@ public class DumpHelper {
return Objects.requireNonNull(
LocalManagerRegistry.getManager(DexUseManagerLocal.class));
}
-
- @NonNull
- public IArtd getArtd() {
- return Utils.getArtd();
- }
}
}
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
index c6e64b69e1..38fca5f5f0 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
@@ -38,6 +38,7 @@ import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.pm.PackageStateModulesUtils;
import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
import com.android.server.pm.PackageManagerLocal;
@@ -59,10 +60,10 @@ public class PrimaryDexopter extends Dexopter<DetailedPrimaryDexInfo> {
private final int mSharedGid;
- public PrimaryDexopter(@NonNull Context context, @NonNull PackageState pkgState,
- @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
- @NonNull CancellationSignal cancellationSignal) {
- this(new Injector(context), pkgState, pkg, params, cancellationSignal);
+ public PrimaryDexopter(@NonNull Context context, @NonNull Config config,
+ @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+ @NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
+ this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
}
@VisibleForTesting
diff --git a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
index 892147de68..2841ee278b 100644
--- a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.DexUseManagerLocal.DetailedSecondaryDexInfo;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.OutputArtifacts.PermissionSettings;
import static com.android.server.art.OutputArtifacts.PermissionSettings.SeContext;
import static com.android.server.art.Utils.Abi;
@@ -30,6 +30,7 @@ import android.os.CancellationSignal;
import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.art.model.Config;
import com.android.server.art.model.DexoptParams;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -38,13 +39,13 @@ import java.util.List;
/** @hide */
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-public class SecondaryDexopter extends Dexopter<DetailedSecondaryDexInfo> {
+public class SecondaryDexopter extends Dexopter<CheckedSecondaryDexInfo> {
private static final String TAG = ArtManagerLocal.TAG;
- public SecondaryDexopter(@NonNull Context context, @NonNull PackageState pkgState,
- @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
- @NonNull CancellationSignal cancellationSignal) {
- this(new Injector(context), pkgState, pkg, params, cancellationSignal);
+ public SecondaryDexopter(@NonNull Context context, @NonNull Config config,
+ @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+ @NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
+ this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
}
@VisibleForTesting
@@ -63,29 +64,29 @@ public class SecondaryDexopter extends Dexopter<DetailedSecondaryDexInfo> {
@Override
@NonNull
- protected List<DetailedSecondaryDexInfo> getDexInfoList() {
- return mInjector.getDexUseManager().getFilteredDetailedSecondaryDexInfo(
- mPkgState.getPackageName());
+ protected List<CheckedSecondaryDexInfo> getDexInfoList() {
+ return mInjector.getDexUseManager().getCheckedSecondaryDexInfo(
+ mPkgState.getPackageName(), true /* excludeObsoleteDexesAndLoaders */);
}
@Override
- protected boolean isDexoptable(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected boolean isDexoptable(@NonNull CheckedSecondaryDexInfo dexInfo) {
return true;
}
@Override
- protected boolean needsToBeShared(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected boolean needsToBeShared(@NonNull CheckedSecondaryDexInfo dexInfo) {
return dexInfo.isUsedByOtherApps();
}
@Override
- protected boolean isDexFilePublic(@NonNull DetailedSecondaryDexInfo dexInfo) {
- return dexInfo.isDexFilePublic();
+ protected boolean isDexFilePublic(@NonNull CheckedSecondaryDexInfo dexInfo) {
+ return dexInfo.fileVisibility() == FileVisibility.OTHER_READABLE;
}
@Override
@NonNull
- protected List<ProfilePath> getExternalProfiles(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected List<ProfilePath> getExternalProfiles(@NonNull CheckedSecondaryDexInfo dexInfo) {
// A secondary dex file doesn't have any external profile to use.
return List.of();
}
@@ -93,7 +94,7 @@ public class SecondaryDexopter extends Dexopter<DetailedSecondaryDexInfo> {
@Override
@NonNull
protected PermissionSettings getPermissionSettings(
- @NonNull DetailedSecondaryDexInfo dexInfo, boolean canBePublic) {
+ @NonNull CheckedSecondaryDexInfo dexInfo, boolean canBePublic) {
int uid = getUid(dexInfo);
// We need the "execute" bit for "others" even though `canBePublic` is false because the
// directory can contain other artifacts that needs to be public.
@@ -109,38 +110,38 @@ public class SecondaryDexopter extends Dexopter<DetailedSecondaryDexInfo> {
@Override
@NonNull
- protected List<Abi> getAllAbis(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected List<Abi> getAllAbis(@NonNull CheckedSecondaryDexInfo dexInfo) {
return Utils.getAllAbisForNames(dexInfo.abiNames(), mPkgState);
}
@Override
@NonNull
- protected ProfilePath buildRefProfilePath(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected ProfilePath buildRefProfilePath(@NonNull CheckedSecondaryDexInfo dexInfo) {
return AidlUtils.buildProfilePathForSecondaryRef(dexInfo.dexPath());
}
@Override
@NonNull
protected OutputProfile buildOutputProfile(
- @NonNull DetailedSecondaryDexInfo dexInfo, boolean isPublic) {
+ @NonNull CheckedSecondaryDexInfo dexInfo, boolean isPublic) {
int uid = getUid(dexInfo);
return AidlUtils.buildOutputProfileForSecondary(dexInfo.dexPath(), uid, uid, isPublic);
}
@Override
@NonNull
- protected List<ProfilePath> getCurProfiles(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected List<ProfilePath> getCurProfiles(@NonNull CheckedSecondaryDexInfo dexInfo) {
// A secondary dex file can only be loaded by one user, so there is only one profile.
return List.of(AidlUtils.buildProfilePathForSecondaryCur(dexInfo.dexPath()));
}
@Override
@Nullable
- protected DexMetadataPath buildDmPath(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ protected DexMetadataPath buildDmPath(@NonNull CheckedSecondaryDexInfo dexInfo) {
return null;
}
- private int getUid(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ private int getUid(@NonNull CheckedSecondaryDexInfo dexInfo) {
return dexInfo.userHandle().getUid(mPkgState.getAppId());
}
}
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index 57d57b59b0..82418beb02 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -65,6 +65,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
/** @hide */
@@ -274,6 +275,10 @@ public final class Utils {
getFuture(CompletableFuture.runAsync(runnable, executor));
}
+ public static <T> T executeAndWait(@NonNull Executor executor, @NonNull Supplier<T> supplier) {
+ return getFuture(CompletableFuture.supplyAsync(supplier, executor));
+ }
+
public static <T> T getFuture(Future<T> future) {
try {
return future.get();
diff --git a/libartservice/service/java/com/android/server/art/model/Config.java b/libartservice/service/java/com/android/server/art/model/Config.java
index 49bc9308da..2ea82303aa 100644
--- a/libartservice/service/java/com/android/server/art/model/Config.java
+++ b/libartservice/service/java/com/android/server/art/model/Config.java
@@ -16,6 +16,7 @@
package com.android.server.art.model;
+import static com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback;
import static com.android.server.art.ArtManagerLocal.BatchDexoptStartCallback;
import static com.android.server.art.ArtManagerLocal.DexoptDoneCallback;
import static com.android.server.art.ArtManagerLocal.ScheduleBackgroundDexoptJobCallback;
@@ -62,6 +63,14 @@ public class Config {
private LinkedHashMap<DexoptDoneCallback, Callback<DexoptDoneCallback, Boolean>>
mDexoptDoneCallbacks = new LinkedHashMap<>();
+ /**
+ * @see ArtManagerLocal#setAdjustCompilerFilterCallback(Executor,
+ * AdjustCompilerFilterCallback)
+ */
+ @GuardedBy("this")
+ @Nullable
+ private Callback<AdjustCompilerFilterCallback, Void> mAdjustCompilerFilterCallback = null;
+
public synchronized void setBatchDexoptStartCallback(
@NonNull Executor executor, @NonNull BatchDexoptStartCallback callback) {
mBatchDexoptStartCallback = Callback.create(callback, executor);
@@ -109,6 +118,21 @@ public class Config {
return new ArrayList<>(mDexoptDoneCallbacks.values());
}
+ public synchronized void setAdjustCompilerFilterCallback(
+ @NonNull Executor executor, @NonNull AdjustCompilerFilterCallback callback) {
+ mAdjustCompilerFilterCallback = Callback.create(callback, executor);
+ }
+
+ public synchronized void clearAdjustCompilerFilterCallback() {
+ mAdjustCompilerFilterCallback = null;
+ }
+
+ @Nullable
+ public synchronized Callback<AdjustCompilerFilterCallback, Void>
+ getAdjustCompilerFilterCallback() {
+ return mAdjustCompilerFilterCallback;
+ }
+
@AutoValue
public static abstract class Callback<CallbackType, ExtraType> {
public abstract @NonNull CallbackType get();
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index 94fbdaccd9..6e78de9127 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -18,7 +18,7 @@ package com.android.server.art;
import static android.os.ParcelFileDescriptor.AutoCloseInputStream;
-import static com.android.server.art.DexUseManagerLocal.DetailedSecondaryDexInfo;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
import static com.android.server.art.model.DexoptResult.PackageDexoptResult;
import static com.android.server.art.model.DexoptStatus.DexContainerFileDexoptStatus;
@@ -129,8 +129,8 @@ public class ArtManagerLocalTest {
@Mock private StorageManager mStorageManager;
private PackageState mPkgState1;
private AndroidPackage mPkg1;
- private DetailedSecondaryDexInfo mPkg1SecondaryDexInfo1;
- private DetailedSecondaryDexInfo mPkg1SecondaryDexInfoNotFound;
+ private CheckedSecondaryDexInfo mPkg1SecondaryDexInfo1;
+ private CheckedSecondaryDexInfo mPkg1SecondaryDexInfoNotFound;
private Config mConfig;
// True if the artifacts should be in dalvik-cache.
@@ -218,9 +218,15 @@ public class ArtManagerLocalTest {
.when(mDexUseManager)
.getSecondaryDexInfo(eq(PKG_NAME_1));
lenient()
+ .doReturn(List.of(mPkg1SecondaryDexInfo1, mPkg1SecondaryDexInfoNotFound))
+ .when(mDexUseManager)
+ .getCheckedSecondaryDexInfo(
+ eq(PKG_NAME_1), eq(false) /* excludeObsoleteDexesAndLoaders */);
+ lenient()
.doReturn(List.of(mPkg1SecondaryDexInfo1))
.when(mDexUseManager)
- .getFilteredDetailedSecondaryDexInfo(eq(PKG_NAME_1));
+ .getCheckedSecondaryDexInfo(
+ eq(PKG_NAME_1), eq(true) /* excludeObsoleteDexesAndLoaders */);
simulateStorageNotLow();
@@ -1283,8 +1289,8 @@ public class ArtManagerLocalTest {
return getDexoptStatusResult;
}
- private DetailedSecondaryDexInfo createSecondaryDexInfo(String dexPath) throws Exception {
- var dexInfo = mock(DetailedSecondaryDexInfo.class);
+ private CheckedSecondaryDexInfo createSecondaryDexInfo(String dexPath) throws Exception {
+ var dexInfo = mock(CheckedSecondaryDexInfo.class);
lenient().when(dexInfo.dexPath()).thenReturn(dexPath);
lenient().when(dexInfo.abiNames()).thenReturn(Set.of("arm64-v8a"));
lenient().when(dexInfo.classLoaderContext()).thenReturn("CLC");
diff --git a/libartservice/service/javatests/com/android/server/art/DexUseManagerTest.java b/libartservice/service/javatests/com/android/server/art/DexUseManagerTest.java
index c8ece398b9..5662090aeb 100644
--- a/libartservice/service/javatests/com/android/server/art/DexUseManagerTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexUseManagerTest.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.DexUseManagerLocal.DetailedSecondaryDexInfo;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.DexUseManagerLocal.DexLoader;
import static com.android.server.art.DexUseManagerLocal.SecondaryDexInfo;
@@ -87,11 +87,11 @@ public class DexUseManagerTest {
private final UserHandle mUserHandle = Binder.getCallingUserHandle();
/**
- * The default value of `isDexFilePublic` returned by `getSecondaryDexInfo`. The value doesn't
+ * The default value of `fileVisibility` returned by `getSecondaryDexInfo`. The value doesn't
* matter because it's undefined, but it's needed for deep equality check, to make the test
* simpler.
*/
- private final boolean mDefaultIsDexFilePublic = true;
+ private final @FileVisibility int mDefaultFileVisibility = FileVisibility.OTHER_READABLE;
@Mock private PackageManagerLocal.FilteredSnapshot mSnapshot;
@Mock private DexUseManagerLocal.Injector mInjector;
@@ -325,10 +325,10 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("arm64-v8a"),
Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */)),
- false /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ false /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
assertThat(dexInfoList.get(0).classLoaderContext()).isEqualTo("CLC");
}
@@ -341,10 +341,10 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mDeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mDeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("arm64-v8a"),
Set.of(DexLoader.create(OWNING_PKG_NAME, true /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ true /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
assertThat(dexInfoList.get(0).classLoaderContext()).isEqualTo("CLC");
}
@@ -356,10 +356,10 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("armeabi-v7a"),
Set.of(DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ true /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
assertThat(dexInfoList.get(0).classLoaderContext()).isEqualTo("CLC");
}
@@ -371,10 +371,10 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
SecondaryDexInfo.UNSUPPORTED_CLASS_LOADER_CONTEXT, Set.of("armeabi-v7a"),
Set.of(DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ true /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
assertThat(dexInfoList.get(0).classLoaderContext()).isNull();
}
@@ -388,12 +388,12 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
SecondaryDexInfo.VARYING_CLASS_LOADER_CONTEXTS,
Set.of("arm64-v8a", "armeabi-v7a"),
Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */),
DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ true /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
assertThat(dexInfoList.get(0).classLoaderContext()).isNull();
}
@@ -489,7 +489,7 @@ public class DexUseManagerTest {
List<? extends SecondaryDexInfo> dexInfoList =
mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME);
assertThat(dexInfoList)
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"UpdatedCLC", Set.of("arm64-v8a", "armeabi-v7a"),
Set.of(DexLoader.create(OWNING_PKG_NAME,
false /* isolatedProcess */),
@@ -497,21 +497,21 @@ public class DexUseManagerTest {
true /* isolatedProcess */),
DexLoader.create(LOADING_PKG_NAME,
false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic),
- DetailedSecondaryDexInfo.create(mCeDir + "/bar.apk", mUserHandle,
+ true /* isUsedByOtherApps */, mDefaultFileVisibility),
+ CheckedSecondaryDexInfo.create(mCeDir + "/bar.apk", mUserHandle,
SecondaryDexInfo.VARYING_CLASS_LOADER_CONTEXTS,
Set.of("arm64-v8a", "armeabi-v7a"),
Set.of(DexLoader.create(
OWNING_PKG_NAME, false /* isolatedProcess */),
DexLoader.create(
LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic),
- DetailedSecondaryDexInfo.create(mCeDir + "/baz.apk", mUserHandle,
+ true /* isUsedByOtherApps */, mDefaultFileVisibility),
+ CheckedSecondaryDexInfo.create(mCeDir + "/baz.apk", mUserHandle,
SecondaryDexInfo.UNSUPPORTED_CLASS_LOADER_CONTEXT,
Set.of("arm64-v8a"),
Set.of(DexLoader.create(
OWNING_PKG_NAME, false /* isolatedProcess */)),
- false /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ false /* isUsedByOtherApps */, mDefaultFileVisibility));
assertThat(mDexUseManager.getSecondaryDexContainerFileUseInfo(OWNING_PKG_NAME))
.containsExactly(DexContainerFileUseInfo.create(mCeDir + "/foo.apk", mUserHandle,
@@ -525,7 +525,7 @@ public class DexUseManagerTest {
}
@Test
- public void testFilteredDetailedSecondaryDexPublic() throws Exception {
+ public void testCheckedSecondaryDexPublic() throws Exception {
when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk"))
.thenReturn(FileVisibility.OTHER_READABLE);
@@ -534,16 +534,17 @@ public class DexUseManagerTest {
mDexUseManager.notifyDexContainersLoaded(
mSnapshot, LOADING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
- assertThat(mDexUseManager.getFilteredDetailedSecondaryDexInfo(OWNING_PKG_NAME))
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, true /* excludeObsoleteDexesAndLoaders */))
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("arm64-v8a", "armeabi-v7a"),
Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */),
DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, true /* isDexFilePublic */));
+ true /* isUsedByOtherApps */, FileVisibility.OTHER_READABLE));
}
@Test
- public void testFilteredDetailedSecondaryDexPrivate() throws Exception {
+ public void testCheckedSecondaryDexPrivate() throws Exception {
when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk"))
.thenReturn(FileVisibility.NOT_OTHER_READABLE);
@@ -556,36 +557,57 @@ public class DexUseManagerTest {
mDexUseManager.notifyDexContainersLoaded(
mSnapshot, OWNING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
- assertThat(mDexUseManager.getFilteredDetailedSecondaryDexInfo(OWNING_PKG_NAME))
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, true /* excludeObsoleteDexesAndLoaders */))
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("arm64-v8a"),
Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */)),
- false /* isUsedByOtherApps */, false /* isDexFilePublic */));
+ false /* isUsedByOtherApps */, FileVisibility.NOT_OTHER_READABLE));
+
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, false /* excludeObsoleteDexesAndLoaders */))
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ "CLC", Set.of("arm64-v8a", "armeabi-v7a"),
+ Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */),
+ DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */),
+ DexLoader.create(OWNING_PKG_NAME, true /* isolatedProcess */)),
+ true /* isUsedByOtherApps */, FileVisibility.NOT_OTHER_READABLE));
}
@Test
- public void testFilteredDetailedSecondaryDexFilteredDueToVisibility() throws Exception {
- when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk"))
- .thenReturn(FileVisibility.NOT_OTHER_READABLE);
-
- mDexUseManager.notifyDexContainersLoaded(
- mSnapshot, LOADING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
+ public void testCheckedSecondaryDexNotFound() throws Exception {
+ when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk")).thenReturn(FileVisibility.NOT_FOUND);
- when(Process.isIsolatedUid(anyInt())).thenReturn(true);
mDexUseManager.notifyDexContainersLoaded(
mSnapshot, OWNING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
- assertThat(mDexUseManager.getFilteredDetailedSecondaryDexInfo(OWNING_PKG_NAME)).isEmpty();
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, true /* excludeObsoleteDexesAndLoaders */))
+ .isEmpty();
+
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, false /* excludeObsoleteDexesAndLoaders */))
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ "CLC", Set.of("arm64-v8a"),
+ Set.of(DexLoader.create(OWNING_PKG_NAME, false /* isolatedProcess */)),
+ false /* isUsedByOtherApps */, FileVisibility.NOT_FOUND));
}
@Test
- public void testFilteredDetailedSecondaryDexFilteredDueToNotFound() throws Exception {
- when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk")).thenReturn(FileVisibility.NOT_FOUND);
+ public void testCheckedSecondaryDexFilteredDueToVisibility() throws Exception {
+ when(mArtd.getDexFileVisibility(mCeDir + "/foo.apk"))
+ .thenReturn(FileVisibility.NOT_OTHER_READABLE);
mDexUseManager.notifyDexContainersLoaded(
+ mSnapshot, LOADING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
+
+ when(Process.isIsolatedUid(anyInt())).thenReturn(true);
+ mDexUseManager.notifyDexContainersLoaded(
mSnapshot, OWNING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
- assertThat(mDexUseManager.getFilteredDetailedSecondaryDexInfo(OWNING_PKG_NAME)).isEmpty();
+ assertThat(mDexUseManager.getCheckedSecondaryDexInfo(
+ OWNING_PKG_NAME, true /* excludeObsoleteDexesAndLoaders */))
+ .isEmpty();
}
@Test
@@ -746,10 +768,10 @@ public class DexUseManagerTest {
mSnapshot, LOADING_PKG_NAME, Map.of(mCeDir + "/foo.apk", "CLC"));
assertThat(mDexUseManager.getSecondaryDexInfo(OWNING_PKG_NAME))
- .containsExactly(DetailedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
+ .containsExactly(CheckedSecondaryDexInfo.create(mCeDir + "/foo.apk", mUserHandle,
"CLC", Set.of("armeabi-v7a"),
Set.of(DexLoader.create(LOADING_PKG_NAME, false /* isolatedProcess */)),
- true /* isUsedByOtherApps */, mDefaultIsDexFilePublic));
+ true /* isUsedByOtherApps */, mDefaultFileVisibility));
}
private AndroidPackage createPackage(String packageName) {
diff --git a/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java b/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java
index 694bba7136..be2887d20f 100644
--- a/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java
@@ -16,6 +16,7 @@
package com.android.server.art;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.DexUseManagerLocal.DexLoader;
import static com.android.server.art.DexUseManagerLocal.SecondaryDexInfo;
import static com.android.server.art.model.DexoptStatus.DexContainerFileDexoptStatus;
@@ -68,7 +69,6 @@ public class DumpHelperTest {
@Mock private ArtManagerLocal mArtManagerLocal;
@Mock private DexUseManagerLocal mDexUseManagerLocal;
@Mock private PackageManagerLocal.FilteredSnapshot mSnapshot;
- @Mock private IArtd mArtd;
private DumpHelper mDumpHelper;
@@ -85,7 +85,6 @@ public class DumpHelperTest {
lenient().when(mInjector.getArtManagerLocal()).thenReturn(mArtManagerLocal);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManagerLocal);
- lenient().when(mInjector.getArtd()).thenReturn(mArtd);
Map<String, PackageState> pkgStates = createPackageStates();
lenient().when(mSnapshot.getPackageStates()).thenReturn(pkgStates);
@@ -214,7 +213,7 @@ public class DumpHelperTest {
.thenReturn(Set.of(DexLoader.create(PKG_NAME_FOO, false /* isolatedProcess */),
DexLoader.create(PKG_NAME_BAR, false /* isolatedProcess */)));
- var info1 = mock(SecondaryDexInfo.class);
+ var info1 = mock(CheckedSecondaryDexInfo.class);
lenient().when(info1.dexPath()).thenReturn("/data/user_de/0/foo/1.apk");
lenient()
.when(info1.displayClassLoaderContext())
@@ -239,11 +238,9 @@ public class DumpHelperTest {
lenient().when(info1.loaders()).thenReturn(loaders);
// The output should show the dex path with "(removed)".
- lenient()
- .when(mArtd.getDexFileVisibility("/data/user_de/0/foo/1.apk"))
- .thenReturn(FileVisibility.NOT_FOUND);
+ lenient().when(info1.fileVisibility()).thenReturn(FileVisibility.NOT_FOUND);
- var info2 = mock(SecondaryDexInfo.class);
+ var info2 = mock(CheckedSecondaryDexInfo.class);
lenient().when(info2.dexPath()).thenReturn("/data/user_de/0/foo/2.apk");
lenient().when(info2.displayClassLoaderContext()).thenReturn("PCL[]");
lenient()
@@ -255,14 +252,13 @@ public class DumpHelperTest {
lenient()
.when(info2.loaders())
.thenReturn(Set.of(DexLoader.create(PKG_NAME_FOO, false /* isolatedProcess */)));
- lenient()
- .when(mArtd.getDexFileVisibility("/data/user_de/0/foo/2.apk"))
- .thenReturn(FileVisibility.OTHER_READABLE);
+ lenient().when(info2.fileVisibility()).thenReturn(FileVisibility.OTHER_READABLE);
lenient()
.doReturn(List.of(info1, info2))
.when(mDexUseManagerLocal)
- .getSecondaryDexInfo(PKG_NAME_FOO);
+ .getCheckedSecondaryDexInfo(
+ PKG_NAME_FOO, false /* excludeObsoleteDexesAndLoaders */);
}
private void setUpForBar() {
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index efe567fe0e..b9b8bd31e4 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -168,6 +168,32 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
params.mExpectedCompilerFilter = "speed";
list.add(params);
+ // It respects the adjustment made by the callback.
+ params = new Params();
+ params.mRequestedCompilerFilter = "speed-profile";
+ params.mExpectedCallbackInputCompilerFilter = "speed-profile";
+ params.mCallbackReturnedCompilerFilter = "speed";
+ params.mExpectedCompilerFilter = "speed";
+ list.add(params);
+
+ // It upgrades the compiler filter before calling the callback.
+ params = new Params();
+ params.mRequestedCompilerFilter = "speed-profile";
+ params.mIsSystemUi = true;
+ params.mExpectedCallbackInputCompilerFilter = "speed";
+ params.mCallbackReturnedCompilerFilter = "speed";
+ params.mExpectedCompilerFilter = "speed";
+ list.add(params);
+
+ // It downgrades the compiler filter after calling the callback.
+ params = new Params();
+ params.mRequestedCompilerFilter = "speed-profile";
+ params.mExpectedCallbackInputCompilerFilter = "speed-profile";
+ params.mCallbackReturnedCompilerFilter = "speed-profile";
+ params.mIsUseEmbeddedDex = true;
+ params.mExpectedCompilerFilter = "verify";
+ list.add(params);
+
return list;
}
@@ -198,6 +224,17 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
lenient().when(mArtd.isInDalvikCache(any())).thenReturn(mParams.mIsInDalvikCache);
+ if (mParams.mCallbackReturnedCompilerFilter != null) {
+ mConfig.setAdjustCompilerFilterCallback(
+ Runnable::run, (packageName, originalCompilerFilter, reason) -> {
+ assertThat(packageName).isEqualTo(PKG_NAME);
+ assertThat(originalCompilerFilter)
+ .isEqualTo(mParams.mExpectedCallbackInputCompilerFilter);
+ assertThat(reason).isEqualTo("install");
+ return mParams.mCallbackReturnedCompilerFilter;
+ });
+ }
+
mDexoptParams =
new DexoptParams.Builder("install")
.setCompilerFilter(mParams.mRequestedCompilerFilter)
@@ -334,6 +371,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
// Options.
public String mRequestedCompilerFilter = "verify";
+ public String mCallbackReturnedCompilerFilter = null;
public boolean mForce = false;
public boolean mShouldDowngrade = false;
public boolean mSkipIfStorageLow = false;
@@ -343,6 +381,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
public boolean mAlwaysDebuggable = false;
// Expectations.
+ public String mExpectedCallbackInputCompilerFilter = "verify";
public String mExpectedCompilerFilter = "verify";
public int mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
| DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
@@ -358,19 +397,22 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
+ "isLauncher=%b,"
+ "isUseEmbeddedDex=%b,"
+ "requestedCompilerFilter=%s,"
+ + "callbackReturnedCompilerFilter=%s,"
+ "force=%b,"
+ "shouldDowngrade=%b,"
+ "skipIfStorageLow=%b,"
+ "ignoreProfile=%b,"
+ "alwaysDebuggable=%b"
+ " => "
- + "targetCompilerFilter=%s,"
+ + "expectedCallbackInputCompilerFilter=%s,"
+ + "expectedCompilerFilter=%s,"
+ "expectedDexoptTrigger=%d,"
+ "expectedIsDebuggable=%b,"
+ "expectedIsHiddenApiPolicyEnabled=%b",
mIsInDalvikCache, mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable,
- mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter, mForce,
- mShouldDowngrade, mSkipIfStorageLow, mIgnoreProfile, mAlwaysDebuggable,
+ mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter,
+ mCallbackReturnedCompilerFilter, mForce, mShouldDowngrade, mSkipIfStorageLow,
+ mIgnoreProfile, mAlwaysDebuggable, mExpectedCallbackInputCompilerFilter,
mExpectedCompilerFilter, mExpectedDexoptTrigger, mExpectedIsDebuggable,
mExpectedIsHiddenApiPolicyEnabled);
}
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
index 60b64262e5..7a8287fe4c 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -31,6 +31,7 @@ import android.os.UserManager;
import android.os.storage.StorageManager;
import com.android.modules.utils.pm.PackageStateModulesUtils;
+import com.android.server.art.model.Config;
import com.android.server.art.testing.StaticMockitoRule;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.AndroidPackageSplit;
@@ -68,9 +69,17 @@ public class PrimaryDexopterTestBase {
protected PackageUserState mPkgUserStateNotInstalled;
protected PackageUserState mPkgUserStateInstalled;
protected CancellationSignal mCancellationSignal;
+ protected Config mConfig;
@Before
public void setUp() throws Exception {
+ mPkgUserStateNotInstalled = createPackageUserState(false /* installed */);
+ mPkgUserStateInstalled = createPackageUserState(true /* installed */);
+ mPkgState = createPackageState();
+ mPkg = mPkgState.getAndroidPackage();
+ mCancellationSignal = new CancellationSignal();
+ mConfig = new Config();
+
lenient().when(mInjector.getArtd()).thenReturn(mArtd);
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
@@ -78,6 +87,7 @@ public class PrimaryDexopterTestBase {
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
lenient().when(mInjector.getArtVersion()).thenReturn(ART_VERSION);
+ lenient().when(mInjector.getConfig()).thenReturn(mConfig);
lenient()
.when(SystemProperties.get("dalvik.vm.systemuicompilerfilter"))
@@ -104,12 +114,6 @@ public class PrimaryDexopterTestBase {
lenient().when(mDexUseManager.isPrimaryDexUsedByOtherApps(any(), any())).thenReturn(false);
lenient().when(mStorageManager.getAllocatableBytes(any())).thenReturn(1l);
-
- mPkgUserStateNotInstalled = createPackageUserState(false /* installed */);
- mPkgUserStateInstalled = createPackageUserState(true /* installed */);
- mPkgState = createPackageState();
- mPkg = mPkgState.getAndroidPackage();
- mCancellationSignal = new CancellationSignal();
}
private AndroidPackage createPackage() {
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index 3ef256c08d..f80503d09b 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.DexUseManagerLocal.DetailedSecondaryDexInfo;
+import static com.android.server.art.DexUseManagerLocal.CheckedSecondaryDexInfo;
import static com.android.server.art.OutputArtifacts.PermissionSettings;
import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
import static com.android.server.art.testing.TestingUtils.deepEq;
@@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
import com.android.server.art.testing.StaticMockitoRule;
@@ -105,11 +106,17 @@ public class SecondaryDexopterTest {
private PackageState mPkgState;
private AndroidPackage mPkg;
private CancellationSignal mCancellationSignal;
+ protected Config mConfig;
private SecondaryDexopter mSecondaryDexopter;
@Before
public void setUp() throws Exception {
+ mPkgState = createPackageState();
+ mPkg = mPkgState.getAndroidPackage();
+ mCancellationSignal = new CancellationSignal();
+ mConfig = new Config();
+
lenient()
.when(SystemProperties.getBoolean(eq("dalvik.vm.always_debuggable"), anyBoolean()))
.thenReturn(false);
@@ -129,16 +136,14 @@ public class SecondaryDexopterTest {
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
+ lenient().when(mInjector.getConfig()).thenReturn(mConfig);
- List<DetailedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();
+ List<CheckedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();
lenient()
- .when(mDexUseManager.getFilteredDetailedSecondaryDexInfo(eq(PKG_NAME)))
+ .when(mDexUseManager.getCheckedSecondaryDexInfo(
+ eq(PKG_NAME), eq(true) /* excludeObsoleteDexesAndLoaders */))
.thenReturn(secondaryDexInfo);
- mPkgState = createPackageState();
- mPkg = mPkgState.getAndroidPackage();
- mCancellationSignal = new CancellationSignal();
-
prepareProfiles();
// Dexopt is always needed and successful.
@@ -235,33 +240,33 @@ public class SecondaryDexopterTest {
return pkgState;
}
- private List<DetailedSecondaryDexInfo> createSecondaryDexInfo() throws Exception {
+ private List<CheckedSecondaryDexInfo> createSecondaryDexInfo() throws Exception {
// This should be compiled with profile.
- var dex1Info = mock(DetailedSecondaryDexInfo.class);
+ var dex1Info = mock(CheckedSecondaryDexInfo.class);
lenient().when(dex1Info.dexPath()).thenReturn(DEX_1);
lenient().when(dex1Info.userHandle()).thenReturn(USER_HANDLE);
lenient().when(dex1Info.classLoaderContext()).thenReturn("CLC_FOR_DEX_1");
lenient().when(dex1Info.abiNames()).thenReturn(Set.of("arm64-v8a"));
lenient().when(dex1Info.isUsedByOtherApps()).thenReturn(false);
- lenient().when(dex1Info.isDexFilePublic()).thenReturn(true);
+ lenient().when(dex1Info.fileVisibility()).thenReturn(FileVisibility.OTHER_READABLE);
// This should be compiled without profile because it's used by other apps.
- var dex2Info = mock(DetailedSecondaryDexInfo.class);
+ var dex2Info = mock(CheckedSecondaryDexInfo.class);
lenient().when(dex2Info.dexPath()).thenReturn(DEX_2);
lenient().when(dex2Info.userHandle()).thenReturn(USER_HANDLE);
lenient().when(dex2Info.classLoaderContext()).thenReturn("CLC_FOR_DEX_2");
lenient().when(dex2Info.abiNames()).thenReturn(Set.of("arm64-v8a", "armeabi-v7a"));
lenient().when(dex2Info.isUsedByOtherApps()).thenReturn(true);
- lenient().when(dex2Info.isDexFilePublic()).thenReturn(true);
+ lenient().when(dex2Info.fileVisibility()).thenReturn(FileVisibility.OTHER_READABLE);
// This should be compiled with verify because the class loader context is invalid.
- var dex3Info = mock(DetailedSecondaryDexInfo.class);
+ var dex3Info = mock(CheckedSecondaryDexInfo.class);
lenient().when(dex3Info.dexPath()).thenReturn(DEX_3);
lenient().when(dex3Info.userHandle()).thenReturn(USER_HANDLE);
lenient().when(dex3Info.classLoaderContext()).thenReturn(null);
lenient().when(dex3Info.abiNames()).thenReturn(Set.of("arm64-v8a"));
lenient().when(dex3Info.isUsedByOtherApps()).thenReturn(false);
- lenient().when(dex3Info.isDexFilePublic()).thenReturn(false);
+ lenient().when(dex3Info.fileVisibility()).thenReturn(FileVisibility.NOT_OTHER_READABLE);
return List.of(dex1Info, dex2Info, dex3Info);
}
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index 9b2e8767ef..dfdc3d73c5 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -25,7 +25,7 @@
#include "runtime.h"
#include "verifier/verifier_enums.h"
-namespace art {
+namespace art HIDDEN {
AotClassLinker::AotClassLinker(InternTable* intern_table)
: ClassLinker(intern_table, /*fast_class_not_found_exceptions=*/ false) {}
diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h
index be4ab2b938..1cf91636bb 100644
--- a/runtime/aot_class_linker.h
+++ b/runtime/aot_class_linker.h
@@ -17,10 +17,11 @@
#ifndef ART_RUNTIME_AOT_CLASS_LINKER_H_
#define ART_RUNTIME_AOT_CLASS_LINKER_H_
+#include "base/macros.h"
#include "sdk_checker.h"
#include "class_linker.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class Heap;
@@ -33,10 +34,10 @@ class AotClassLinker : public ClassLinker {
explicit AotClassLinker(InternTable *intern_table);
~AotClassLinker();
-static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap)
+ EXPORT static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap)
REQUIRES_SHARED(Locks::mutator_lock_);
- void SetSdkChecker(std::unique_ptr<SdkChecker>&& sdk_checker_);
+ EXPORT void SetSdkChecker(std::unique_ptr<SdkChecker>&& sdk_checker_);
const SdkChecker* GetSdkChecker() const;
bool DenyAccessBasedOnPublicSdk([[maybe_unused]] ArtMethod* art_method) const override
diff --git a/runtime/app_info.cc b/runtime/app_info.cc
index 3fef5651b0..5ec57c7660 100644
--- a/runtime/app_info.cc
+++ b/runtime/app_info.cc
@@ -21,7 +21,7 @@
#include "base/safe_map.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
static constexpr const char* kUnknownValue = "unknown";
diff --git a/runtime/app_info.h b/runtime/app_info.h
index 0b8132aa6f..20cec94a78 100644
--- a/runtime/app_info.h
+++ b/runtime/app_info.h
@@ -19,10 +19,11 @@
#include <vector>
+#include "base/macros.h"
#include "base/mutex.h"
#include <base/safe_map.h>
-namespace art {
+namespace art HIDDEN {
// Constants used by VMRuntime.java to interface with the runtime.
// We could get them from the well known class but it's simpler to
diff --git a/runtime/app_info_test.cc b/runtime/app_info_test.cc
index 51dd42f6fb..39d07aa516 100644
--- a/runtime/app_info_test.cc
+++ b/runtime/app_info_test.cc
@@ -20,7 +20,7 @@
#include "gtest/gtest.h"
-namespace art {
+namespace art HIDDEN {
TEST(AppInfoTest, RegisterAppInfo) {
AppInfo app_info;
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 43f2831f99..7137658387 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -32,7 +32,7 @@
#include "obj_ptr-inl.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
inline bool ArtField::IsProxyField() {
// No read barrier needed, we're reading the constant declaring class only to read
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index c248bf73a1..dcfd7582fe 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -29,7 +29,7 @@
#include "scoped_thread_state_change-inl.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
void ArtField::SetOffset(MemberOffset num_bytes) {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 906eda408f..49899dafd6 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_ART_FIELD_H_
#define ART_RUNTIME_ART_FIELD_H_
+#include "base/macros.h"
#include "dex/modifiers.h"
#include "dex/primitive.h"
#include "gc_root.h"
@@ -25,7 +26,7 @@
#include "read_barrier_option.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
class DexFile;
template<typename T> class LengthPrefixedArray;
@@ -39,7 +40,7 @@ class Object;
class String;
} // namespace mirror
-class ArtField final {
+class EXPORT ArtField final {
public:
// Visit declaring classes of all the art-fields in 'array' that reside
// in [start_boundary, end_boundary).
diff --git a/runtime/art_method-alloc-inl.h b/runtime/art_method-alloc-inl.h
index 13051b156e..f91063c2d3 100644
--- a/runtime/art_method-alloc-inl.h
+++ b/runtime/art_method-alloc-inl.h
@@ -23,7 +23,7 @@
#include "handle_scope.h"
#include "mirror/class-alloc-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace detail {
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 46c78d2b21..cca20879c2 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -46,7 +46,7 @@
#include "runtime-inl.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace detail {
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 6bb33a13bb..dee62659e3 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -53,7 +53,7 @@
#include "scoped_thread_state_change-inl.h"
#include "vdex_file.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/art_method.h b/runtime/art_method.h
index e5384235fb..dff49e247b 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -39,7 +39,7 @@
#include "offsets.h"
#include "read_barrier_option.h"
-namespace art {
+namespace art HIDDEN {
class CodeItemDataAccessor;
class CodeItemDebugInfoAccessor;
@@ -84,7 +84,7 @@ template <char Shorty> struct HandleShortyTraits;
template <> struct HandleShortyTraits<'L'>;
} // namespace detail
-class ArtMethod final {
+class EXPORT ArtMethod final {
public:
// Should the class state be checked on sensitive operations?
DECLARE_RUNTIME_DEBUG_FLAG(kCheckDeclaringClassState);
diff --git a/runtime/art_method_test.cc b/runtime/art_method_test.cc
index b1e9ed3879..8176cca062 100644
--- a/runtime/art_method_test.cc
+++ b/runtime/art_method_test.cc
@@ -23,7 +23,7 @@
#include "mirror/class-alloc-inl.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
namespace {
// Helper function to avoid `ASSERT_EQ` with floating point types.
diff --git a/runtime/backtrace_helper.cc b/runtime/backtrace_helper.cc
index 260843d7dc..16beb8ee9e 100644
--- a/runtime/backtrace_helper.cc
+++ b/runtime/backtrace_helper.cc
@@ -38,7 +38,7 @@
#endif
-namespace art {
+namespace art HIDDEN {
// We only really support libunwindstack on linux which is unfortunate but since this is only for
// gcstress this isn't a huge deal.
diff --git a/runtime/backtrace_helper.h b/runtime/backtrace_helper.h
index 9be2550b92..9be08ca195 100644
--- a/runtime/backtrace_helper.h
+++ b/runtime/backtrace_helper.h
@@ -20,11 +20,13 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/macros.h"
+
namespace unwindstack {
class Unwinder;
}
-namespace art {
+namespace art HIDDEN {
// Using libunwindstack
class BacktraceCollector {
diff --git a/runtime/barrier.cc b/runtime/barrier.cc
index a6cc9ba053..6a9bdfcd8f 100644
--- a/runtime/barrier.cc
+++ b/runtime/barrier.cc
@@ -23,7 +23,7 @@
#include "base/time_utils.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
Barrier::Barrier(int count, bool verify_count_on_shutdown)
: count_(count),
diff --git a/runtime/barrier.h b/runtime/barrier.h
index 4c94a144bd..d2ff5b239d 100644
--- a/runtime/barrier.h
+++ b/runtime/barrier.h
@@ -30,8 +30,9 @@
#include <memory>
#include "base/locks.h"
+#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
class ConditionVariable;
class LOCKABLE Mutex;
@@ -39,18 +40,18 @@ class LOCKABLE Mutex;
// TODO: Maybe give this a better name.
class Barrier {
public:
- enum LockHandling {
+ enum EXPORT LockHandling {
kAllowHoldingLocks,
kDisallowHoldingLocks,
};
// If verify_count_on_shutdown is true, the destructor verifies that the count is zero in the
// destructor. This means that all expected threads went through the barrier.
- explicit Barrier(int count, bool verify_count_on_shutdown = true);
- virtual ~Barrier();
+ EXPORT explicit Barrier(int count, bool verify_count_on_shutdown = true);
+ EXPORT virtual ~Barrier();
// Pass through the barrier, decrement the count but do not block.
- void Pass(Thread* self) REQUIRES(!GetLock());
+ EXPORT void Pass(Thread* self) REQUIRES(!GetLock());
// Increment the barrier but do not block. The caller should ensure that it
// decrements/passes it eventually.
void IncrementNoWait(Thread* self) REQUIRES(!GetLock());
@@ -67,7 +68,7 @@ class Barrier {
// Increment the count by delta, wait on condition while count is non zero. If LockHandling is
// kAllowHoldingLocks we will not check that all locks are released when waiting.
template <Barrier::LockHandling locks = kDisallowHoldingLocks>
- void Increment(Thread* self, int delta) REQUIRES(!GetLock());
+ EXPORT void Increment(Thread* self, int delta) REQUIRES(!GetLock());
// Increment the count by delta, wait on condition while count is non zero, with a timeout.
// Returns true if time out occurred.
diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc
index e53241cb76..fbb263990c 100644
--- a/runtime/barrier_test.cc
+++ b/runtime/barrier_test.cc
@@ -24,7 +24,7 @@
#include "thread-current-inl.h"
#include "thread_pool.h"
-namespace art {
+namespace art HIDDEN {
class CheckWaitTask : public Task {
public:
CheckWaitTask(Barrier* barrier, AtomicInteger* count1, AtomicInteger* count2)
diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc
index fd9e050a7d..ef4143a177 100644
--- a/runtime/debug_print.cc
+++ b/runtime/debug_print.cc
@@ -31,7 +31,7 @@
#include "thread-current-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
std::string DescribeSpace(ObjPtr<mirror::Class> klass) {
std::ostringstream oss;
diff --git a/runtime/debug_print.h b/runtime/debug_print.h
index 7c6840284d..b4c3bba431 100644
--- a/runtime/debug_print.h
+++ b/runtime/debug_print.h
@@ -18,13 +18,14 @@
#define ART_RUNTIME_DEBUG_PRINT_H_
#include "base/locks.h"
+#include "base/macros.h"
#include "mirror/object.h"
// Helper functions for printing extra information for certain hard to diagnose bugs.
-namespace art {
+namespace art HIDDEN {
-std::string DescribeSpace(ObjPtr<mirror::Class> klass)
+EXPORT std::string DescribeSpace(ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index e5535156c1..3a30cb87e4 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -83,7 +83,7 @@
#include "thread_pool.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/debugger.h b/runtime/debugger.h
index a79add9b8e..fd261ab51a 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -27,18 +27,19 @@
#include "base/array_ref.h"
#include "base/locks.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "jni.h"
#include "runtime.h"
#include "runtime_callbacks.h"
#include "thread.h"
#include "thread_state.h"
-namespace art {
+namespace art HIDDEN {
class Dbg {
public:
- static void SetJdwpAllowed(bool allowed);
- static bool IsJdwpAllowed();
+ EXPORT static void SetJdwpAllowed(bool allowed);
+ EXPORT static bool IsJdwpAllowed();
// Invoked by the GC in case we need to keep DDMS informed.
static void GcDidFinish() REQUIRES(!Locks::mutator_lock_);
@@ -82,15 +83,14 @@ class Dbg {
REQUIRES_SHARED(Locks::mutator_lock_);
static void DdmSetThreadNotification(bool enable)
REQUIRES(!Locks::thread_list_lock_);
- static bool DdmHandleChunk(
- JNIEnv* env,
- uint32_t type,
- const ArrayRef<const jbyte>& data,
- /*out*/uint32_t* out_type,
- /*out*/std::vector<uint8_t>* out_data);
-
- static void DdmConnected() REQUIRES_SHARED(Locks::mutator_lock_);
- static void DdmDisconnected() REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT static bool DdmHandleChunk(JNIEnv* env,
+ uint32_t type,
+ const ArrayRef<const jbyte>& data,
+ /*out*/ uint32_t* out_type,
+ /*out*/ std::vector<uint8_t>* out_data);
+
+ EXPORT static void DdmConnected() REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT static void DdmDisconnected() REQUIRES_SHARED(Locks::mutator_lock_);
/*
* Allocation tracking support.
diff --git a/runtime/deoptimization_kind.h b/runtime/deoptimization_kind.h
index 65a1cf1f2f..76a11b349c 100644
--- a/runtime/deoptimization_kind.h
+++ b/runtime/deoptimization_kind.h
@@ -18,8 +18,9 @@
#define ART_RUNTIME_DEOPTIMIZATION_KIND_H_
#include "base/logging.h"
+#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
enum class DeoptimizationKind {
kAotInlineCache = 0,
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 827ced9545..76cea993b2 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -41,7 +41,7 @@
#include "thread.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h
index cffeb25e57..3a79e11256 100644
--- a/runtime/dex/dex_file_annotations.h
+++ b/runtime/dex/dex_file_annotations.h
@@ -23,7 +23,7 @@
#include "mirror/object_array.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class ClassLoader;
@@ -40,7 +40,7 @@ ObjPtr<mirror::Object> GetAnnotationForField(ArtField* field,
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
-ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field)
+EXPORT ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -67,8 +67,8 @@ bool GetParametersMetadataForMethod(
ArtMethod* method,
/*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
/*out*/ MutableHandle<mirror::IntArray>* access_flags) REQUIRES_SHARED(Locks::mutator_lock_);
-ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_);
+EXPORT ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(
+ ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
// Check whether `method` is annotated with `annotation_class`.
// If `lookup_in_resolved_boot_classes` is true, look up any of the
// method's annotations' classes in the bootstrap class loader's
@@ -83,14 +83,14 @@ bool IsMethodAnnotationPresent(ArtMethod* method,
// is annotated with @dalvik.annotation.optimization.FastNative or
// @dalvik.annotation.optimization.CriticalNative with build visibility.
// If yes, return the associated access flags, i.e. kAccFastNative or kAccCriticalNative.
-uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
- const dex::ClassDef& class_def,
- uint32_t method_index);
+EXPORT uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
+ const dex::ClassDef& class_def,
+ uint32_t method_index);
// Is the method from the `dex_file` with the given `field_index`
// annotated with @dalvik.annotation.optimization.NeverCompile?
-bool MethodIsNeverCompile(const DexFile& dex_file,
- const dex::ClassDef& class_def,
- uint32_t method_index);
+EXPORT bool MethodIsNeverCompile(const DexFile& dex_file,
+ const dex::ClassDef& class_def,
+ uint32_t method_index);
// Is the method from the `dex_file` with the given `field_index`
// annotated with @dalvik.annotation.optimization.NeverInline?
bool MethodIsNeverInline(const DexFile& dex_file,
@@ -137,9 +137,9 @@ bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>*
REQUIRES_SHARED(Locks::mutator_lock_);
bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags)
REQUIRES_SHARED(Locks::mutator_lock_);
-ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
+EXPORT ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
-const char* GetSourceDebugExtension(Handle<mirror::Class> klass)
+EXPORT const char* GetSourceDebugExtension(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Class> GetNestHost(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 54a007f891..202f8cf92a 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -23,6 +23,7 @@
#include <vector>
#include "base/file_utils.h"
+#include "base/macros.h"
#include "base/os.h"
#include "base/stl_util.h"
#include "base/utils.h"
@@ -38,7 +39,7 @@
#include "runtime.h"
#include "ziparchive/zip_writer.h"
-namespace art {
+namespace art HIDDEN {
static constexpr bool kDebugArgs = false;
diff --git a/runtime/dex_reference_collection.h b/runtime/dex_reference_collection.h
index 047771f4a5..d571cf0ce4 100644
--- a/runtime/dex_reference_collection.h
+++ b/runtime/dex_reference_collection.h
@@ -22,7 +22,7 @@
#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
class DexFile;
diff --git a/runtime/dex_register_location.cc b/runtime/dex_register_location.cc
index f3b09733b9..a425b683d4 100644
--- a/runtime/dex_register_location.cc
+++ b/runtime/dex_register_location.cc
@@ -16,7 +16,7 @@
#include "dex_register_location.h"
-namespace art {
+namespace art HIDDEN {
std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
diff --git a/runtime/dex_register_location.h b/runtime/dex_register_location.h
index 98b4d41e2d..f33fd44608 100644
--- a/runtime/dex_register_location.h
+++ b/runtime/dex_register_location.h
@@ -21,9 +21,10 @@
#include <cstdint>
#include "base/dchecked_vector.h"
+#include "base/macros.h"
#include "base/memory_region.h"
-namespace art {
+namespace art HIDDEN {
// Dex register location container used by DexRegisterMap and StackMapStream.
class DexRegisterLocation {
@@ -85,7 +86,7 @@ class DexRegisterLocation {
friend class DexRegisterMap; // Allow creation of uninitialized array of locations.
};
-std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind);
+EXPORT std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind);
std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg);
} // namespace art
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 3eee9e03e0..970590fda8 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -38,7 +38,7 @@
#include "oat_file_assistant.h"
#include "profile/profile_compilation_info.h"
-namespace art {
+namespace art HIDDEN {
void DexoptTest::SetUp() {
ReserveImageSpace();
Dex2oatEnvironmentTest::SetUp();
diff --git a/runtime/dexopt_test.h b/runtime/dexopt_test.h
index a2363939ea..cf32785c0b 100644
--- a/runtime/dexopt_test.h
+++ b/runtime/dexopt_test.h
@@ -20,9 +20,10 @@
#include <string>
#include <vector>
+#include "base/macros.h"
#include "dex2oat_environment_test.h"
-namespace art {
+namespace art HIDDEN {
class DexoptTest : public Dex2oatEnvironmentTest {
public:
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 4a1dfba786..a854e0c5ac 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -47,7 +47,7 @@
#include "thread.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
inline std::string GetResolvedMethodErrorString(ClassLinker* class_linker,
ArtMethod* inlined_method,
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index aa27df4dc5..96a2231930 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -43,7 +43,7 @@
#include "scoped_thread_state_change-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
void CheckReferenceResult(Handle<mirror::Object> o, Thread* self) {
if (o == nullptr) {
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index cfa744d278..3dfeaae024 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -29,7 +29,7 @@
#include "handle.h"
#include "jvalue.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Array;
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index 359614bf92..885764f180 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -33,7 +33,7 @@
#include "stack_map.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
static inline uint32_t GetInvokeStaticMethodIndex(ArtMethod* caller, uint32_t dex_pc)
REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/entrypoints/jni/jni_entrypoints.h b/runtime/entrypoints/jni/jni_entrypoints.h
index def9ddba73..4b515db50d 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.h
+++ b/runtime/entrypoints/jni/jni_entrypoints.h
@@ -25,7 +25,7 @@
#define JNI_ENTRYPOINT_OFFSET(ptr_size, x) \
Thread::JniEntryPointOffset<ptr_size>(OFFSETOF_MEMBER(JniEntryPoints, x))
-namespace art {
+namespace art HIDDEN {
// Pointers to functions that are called by JNI trampolines via thread-local storage.
struct JniEntryPoints {
diff --git a/runtime/entrypoints/math_entrypoints.cc b/runtime/entrypoints/math_entrypoints.cc
index b0eaf1ed03..5db8dbfe9d 100644
--- a/runtime/entrypoints/math_entrypoints.cc
+++ b/runtime/entrypoints/math_entrypoints.cc
@@ -18,7 +18,7 @@
#include "entrypoint_utils-inl.h"
-namespace art {
+namespace art HIDDEN {
extern "C" double art_l2d(int64_t l) {
return static_cast<double>(l);
diff --git a/runtime/entrypoints/math_entrypoints_test.cc b/runtime/entrypoints/math_entrypoints_test.cc
index fe61f5dd11..337f9f0925 100644
--- a/runtime/entrypoints/math_entrypoints_test.cc
+++ b/runtime/entrypoints/math_entrypoints_test.cc
@@ -20,7 +20,7 @@
#include "base/common_art_test.h"
-namespace art {
+namespace art HIDDEN {
class MathEntrypointsTest : public CommonArtTest {};
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 7d9b844b0c..81219234b8 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -32,7 +32,7 @@
#include "arch/x86/callee_save_frame_x86.h"
#include "arch/x86_64/callee_save_frame_x86_64.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
class ScopedQuickEntrypointChecks {
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index 7b3d84915a..82595ed636 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -27,7 +27,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/string-alloc-inl.h"
-namespace art {
+namespace art HIDDEN {
static constexpr bool kUseTlabFastPath = true;
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.h b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
index c4d8a808b2..94f4a27691 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
@@ -21,7 +21,7 @@
#include "gc/allocator_type.h"
#include "quick_entrypoints.h"
-namespace art {
+namespace art HIDDEN {
void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
diff --git a/runtime/entrypoints/quick/quick_cast_entrypoints.cc b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
index 083d5786ce..a32c483431 100644
--- a/runtime/entrypoints/quick/quick_cast_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
@@ -17,7 +17,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
// Assignable test for code, won't throw. Null and equality tests already performed
extern "C" size_t artIsAssignableFromCode(mirror::Class* klass, mirror::Class* ref_class)
diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h
index cb3caac9ab..5119b27076 100644
--- a/runtime/entrypoints/quick/quick_default_externs.h
+++ b/runtime/entrypoints/quick/quick_default_externs.h
@@ -19,7 +19,7 @@
#include <cstdint>
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Array;
class Class;
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
index ea077889ee..46840e60ed 100644
--- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
@@ -24,7 +24,7 @@
#include "quick_default_externs.h"
#include "quick_entrypoints.h"
-namespace art {
+namespace art HIDDEN {
static void DefaultInitEntryPoints(JniEntryPoints* jpoints,
QuickEntryPoints* qpoints,
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 277bc7bf06..29060457fd 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -23,7 +23,7 @@
#include "runtime.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
NO_RETURN static void artDeoptimizeImpl(Thread* self,
DeoptimizationKind kind,
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 9973d1aa47..f29143f79a 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -32,7 +32,7 @@
#include "oat_file-inl.h"
#include "runtime.h"
-namespace art {
+namespace art HIDDEN {
static void StoreObjectInBss(ArtMethod* outer_method,
const OatFile* oat_file,
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 0e73c63828..fe01424c7c 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -27,7 +27,7 @@
#define QUICK_ENTRYPOINT_OFFSET(ptr_size, x) \
Thread::QuickEntryPointOffset<ptr_size>(OFFSETOF_MEMBER(QuickEntryPoints, x))
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Array;
diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.cc b/runtime/entrypoints/quick/quick_entrypoints_enum.cc
index 5387e44d9b..80d9313dcf 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_enum.cc
+++ b/runtime/entrypoints/quick/quick_entrypoints_enum.cc
@@ -16,7 +16,7 @@
#include "quick_entrypoints_enum.h"
-namespace art {
+namespace art HIDDEN {
bool EntrypointRequiresStackMap(QuickEntrypointEnum trampoline) {
// Entrypoints that do not require a stackmap. In general leaf methods
diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.h b/runtime/entrypoints/quick/quick_entrypoints_enum.h
index 017cba68ea..c84ca20d56 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_enum.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_enum.h
@@ -20,7 +20,7 @@
#include "quick_entrypoints.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
// Define an enum for the entrypoints. Names are prepended a 'kQuick'.
enum QuickEntrypointEnum { // NOLINT(whitespace/braces)
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index edf58faf6a..39b21ead02 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -26,7 +26,7 @@
#include "mirror/class-inl.h"
#include "mirror/object_reference.h"
-namespace art {
+namespace art HIDDEN {
// Fast path field resolution that can't initialize classes or throw exceptions.
inline ArtField* FindFieldFast(uint32_t field_idx,
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index 5b7fe0ccf4..b87d81501b 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -19,7 +19,7 @@
#include "entrypoints/entrypoint_utils.h"
#include "mirror/array.h"
-namespace art {
+namespace art HIDDEN {
/*
* Handle fill array data by copying appropriate part of dex file into array.
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 06c27b37c8..c9ec7a7dec 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -36,7 +36,7 @@
} \
}
-namespace art {
+namespace art HIDDEN {
extern "C" int artMethodExitHook(Thread* self,
ArtMethod* method,
diff --git a/runtime/entrypoints/quick/quick_lock_entrypoints.cc b/runtime/entrypoints/quick/quick_lock_entrypoints.cc
index 87286cf651..402f8f613c 100644
--- a/runtime/entrypoints/quick/quick_lock_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_lock_entrypoints.cc
@@ -18,7 +18,7 @@
#include "common_throws.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
extern "C" int artLockObjectFromCode(mirror::Object* obj, Thread* self)
NO_THREAD_SAFETY_ANALYSIS
diff --git a/runtime/entrypoints/quick/quick_string_builder_append_entrypoints.cc b/runtime/entrypoints/quick/quick_string_builder_append_entrypoints.cc
index 9afaf439dc..9e5fe1c826 100644
--- a/runtime/entrypoints/quick/quick_string_builder_append_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_string_builder_append_entrypoints.cc
@@ -19,7 +19,7 @@
#include "string_builder_append.h"
#include "obj_ptr-inl.h"
-namespace art {
+namespace art HIDDEN {
extern "C" mirror::String* artStringBuilderAppend(uint32_t format,
const uint32_t* args,
diff --git a/runtime/entrypoints/quick/quick_thread_entrypoints.cc b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
index 5dca58ab04..53e14d0d7a 100644
--- a/runtime/entrypoints/quick/quick_thread_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
@@ -19,7 +19,7 @@
#include "runtime.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
extern "C" void artDeoptimizeIfNeeded(Thread* self, uintptr_t result, bool is_ref)
REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 202b031bca..781f3e549d 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -24,7 +24,7 @@
#include "thread.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
// Deliver an exception that's pending on thread helping set up a callee save frame on the way.
extern "C" NO_RETURN void artDeliverPendingExceptionFromCode(Thread* self)
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 664cf622a8..d87388e86b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -58,7 +58,7 @@
#include "var_handles.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(DeoptimizationKind kind, Thread* self);
extern "C" NO_RETURN void artDeoptimize(Thread* self, bool skip_method_exit_callbacks);
@@ -943,9 +943,8 @@ class GetQuickReferenceArgumentAtVisitor final : public QuickArgumentVisitor {
// Returning reference argument at position `arg_pos` in Quick stack frame at address `sp`.
// NOTE: Only used for testing purposes.
-extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(size_t arg_pos,
- ArtMethod** sp)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+EXPORT extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(
+ size_t arg_pos, ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* proxy_method = *sp;
ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
CHECK(!non_proxy_method->IsStatic())
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
index 0f0fb69f4b..14e5a7cdfd 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
@@ -22,7 +22,7 @@
#include "common_runtime_test.h"
#include "quick/quick_method_frame_info.h"
-namespace art {
+namespace art HIDDEN {
class QuickTrampolineEntrypointsTest : public CommonRuntimeTest {
protected:
diff --git a/runtime/gc/allocation_listener.h b/runtime/gc/allocation_listener.h
index f286c6cf6e..15daab2136 100644
--- a/runtime/gc/allocation_listener.h
+++ b/runtime/gc/allocation_listener.h
@@ -26,7 +26,7 @@
#include "handle.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index f0d379fde6..f98edf4aa8 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -27,7 +27,7 @@
#include <android-base/properties.h>
-namespace art {
+namespace art HIDDEN {
namespace gc {
int32_t AllocRecordStackTraceElement::ComputeLineNumber() const {
diff --git a/runtime/gc/allocation_record.h b/runtime/gc/allocation_record.h
index 8b4cc67b91..8273ea4df8 100644
--- a/runtime/gc/allocation_record.h
+++ b/runtime/gc/allocation_record.h
@@ -20,11 +20,12 @@
#include <list>
#include <memory>
+#include "base/macros.h"
#include "base/mutex.h"
#include "gc_root.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
class IsMarkedVisitor;
@@ -215,11 +216,8 @@ class AllocRecordObjectMap {
// Caller needs to check that it is enabled before calling since we read the stack trace before
// checking the enabled boolean.
- void RecordAllocation(Thread* self,
- ObjPtr<mirror::Object>* obj,
- size_t byte_count)
- REQUIRES(!Locks::alloc_tracker_lock_)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT void RecordAllocation(Thread* self, ObjPtr<mirror::Object>* obj, size_t byte_count)
+ REQUIRES(!Locks::alloc_tracker_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
static void SetAllocTrackingEnabled(bool enabled) REQUIRES(!Locks::alloc_tracker_lock_);
diff --git a/runtime/gc/allocator/art-dlmalloc.cc b/runtime/gc/allocator/art-dlmalloc.cc
index 62a768db39..86732324d9 100644
--- a/runtime/gc/allocator/art-dlmalloc.cc
+++ b/runtime/gc/allocator/art-dlmalloc.cc
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include "base/bit_utils.h"
+#include "gc/space/dlmalloc_space.h"
// ART specific morecore implementation defined in space.cc.
static void* art_heap_morecore(void* m, intptr_t increment);
@@ -57,50 +58,3 @@ static void art_heap_usage_error(const char* function, void* p) {
LOG(FATAL) << "Incorrect use of function '" << function << "' argument " << p
<< " not expected";
}
-
-#include <sys/mman.h>
-
-#include "base/utils.h"
-#include "runtime_globals.h"
-
-extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* arg) {
- // Is this chunk in use?
- if (used_bytes != 0) {
- return;
- }
- // Do we have any whole pages to give back?
- start = reinterpret_cast<void*>(art::RoundUp(reinterpret_cast<uintptr_t>(start), art::gPageSize));
- end = reinterpret_cast<void*>(art::RoundDown(reinterpret_cast<uintptr_t>(end), art::gPageSize));
- if (end > start) {
- size_t length = reinterpret_cast<uint8_t*>(end) - reinterpret_cast<uint8_t*>(start);
- int rc = madvise(start, length, MADV_DONTNEED);
- if (UNLIKELY(rc != 0)) {
- errno = rc;
- PLOG(FATAL) << "madvise failed during heap trimming";
- }
- size_t* reclaimed = reinterpret_cast<size_t*>(arg);
- *reclaimed += length;
- }
-}
-
-extern "C" void DlmallocBytesAllocatedCallback([[maybe_unused]] void* start,
- [[maybe_unused]] void* end,
- size_t used_bytes,
- void* arg) {
- if (used_bytes == 0) {
- return;
- }
- size_t* bytes_allocated = reinterpret_cast<size_t*>(arg);
- *bytes_allocated += used_bytes + sizeof(size_t);
-}
-
-extern "C" void DlmallocObjectsAllocatedCallback([[maybe_unused]] void* start,
- [[maybe_unused]] void* end,
- size_t used_bytes,
- void* arg) {
- if (used_bytes == 0) {
- return;
- }
- size_t* objects_allocated = reinterpret_cast<size_t*>(arg);
- ++(*objects_allocated);
-}
diff --git a/runtime/gc/allocator/art-dlmalloc.h b/runtime/gc/allocator/art-dlmalloc.h
index 296de72c70..cffde4d8a5 100644
--- a/runtime/gc/allocator/art-dlmalloc.h
+++ b/runtime/gc/allocator/art-dlmalloc.h
@@ -36,26 +36,4 @@
#include "dlmalloc.h"
#pragma GCC diagnostic pop
-// Callback for dlmalloc_inspect_all or mspace_inspect_all that will madvise(2) unused
-// pages back to the kernel.
-extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* /*arg*/);
-
-// Callbacks for dlmalloc_inspect_all or mspace_inspect_all that will
-// count the number of bytes allocated and objects allocated,
-// respectively.
-extern "C" void DlmallocBytesAllocatedCallback(void* start, void* end, size_t used_bytes, void* arg);
-extern "C" void DlmallocObjectsAllocatedCallback(void* start, void* end, size_t used_bytes, void* arg);
-
-namespace art {
-namespace gc {
-namespace allocator {
-
-// Callback from dlmalloc when it needs to increase the footprint. Must be implemented somewhere
-// else (currently dlmalloc_space.cc).
-void* ArtDlMallocMoreCore(void* mspace, intptr_t increment);
-
-} // namespace allocator
-} // namespace gc
-} // namespace art
-
#endif // ART_RUNTIME_GC_ALLOCATOR_ART_DLMALLOC_H_
diff --git a/runtime/gc/allocator_type.h b/runtime/gc/allocator_type.h
index fb298379c9..71188868b2 100644
--- a/runtime/gc/allocator_type.h
+++ b/runtime/gc/allocator_type.h
@@ -19,7 +19,9 @@
#include <iosfwd>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
// Different types of allocators.
diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h
index 5a25166f9a..a905e812f3 100644
--- a/runtime/gc/collector/concurrent_copying-inl.h
+++ b/runtime/gc/collector/concurrent_copying-inl.h
@@ -28,7 +28,7 @@
#include "mirror/class.h"
#include "mirror/object-readbarrier-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index af4848a17b..4987ed07d5 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -47,7 +47,7 @@
#include "thread_list.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index 47d297bdbb..469d54abdf 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_GC_COLLECTOR_CONCURRENT_COPYING_H_
#define ART_RUNTIME_GC_COLLECTOR_CONCURRENT_COPYING_H_
+#include "base/macros.h"
#include "garbage_collector.h"
#include "gc/accounting/space_bitmap.h"
#include "immune_spaces.h"
@@ -27,7 +28,7 @@
#include <unordered_map>
#include <vector>
-namespace art {
+namespace art HIDDEN {
class Barrier;
class Closure;
class RootInfo;
@@ -167,17 +168,15 @@ class ConcurrentCopying : public GarbageCollector {
REQUIRES_SHARED(Locks::mutator_lock_);
private:
- void PushOntoMarkStack(Thread* const self, mirror::Object* obj)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!mark_stack_lock_);
+ EXPORT void PushOntoMarkStack(Thread* const self, mirror::Object* obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
// Returns a to-space copy of the from-space object from_ref, and atomically installs a
// forwarding pointer. Ensures that the forwarding reference is visible to other threads before
// the returned to-space pointer becomes visible to them.
- mirror::Object* Copy(Thread* const self,
- mirror::Object* from_ref,
- mirror::Object* holder,
- MemberOffset offset)
- REQUIRES_SHARED(Locks::mutator_lock_)
+ EXPORT mirror::Object* Copy(Thread* const self,
+ mirror::Object* from_ref,
+ mirror::Object* holder,
+ 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`.
template <bool kNoUnEvac>
@@ -288,8 +287,9 @@ class ConcurrentCopying : public GarbageCollector {
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_);
+ EXPORT 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)
@@ -298,12 +298,11 @@ class ConcurrentCopying : public GarbageCollector {
void DisableMarking() REQUIRES_SHARED(Locks::mutator_lock_);
void IssueDisableMarkingCheckpoint() REQUIRES_SHARED(Locks::mutator_lock_);
void ExpandGcMarkStack() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* MarkNonMoving(Thread* const self,
- mirror::Object* from_ref,
- mirror::Object* holder = nullptr,
- MemberOffset offset = MemberOffset(0))
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_);
+ EXPORT mirror::Object* MarkNonMoving(Thread* const self,
+ mirror::Object* from_ref,
+ mirror::Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_);
ALWAYS_INLINE mirror::Object* MarkUnevacFromSpaceRegion(Thread* const self,
mirror::Object* from_ref,
accounting::SpaceBitmap<kObjectAlignment>* bitmap)
@@ -315,8 +314,8 @@ class ConcurrentCopying : public GarbageCollector {
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!immune_gray_stack_lock_);
void ScanImmuneObject(mirror::Object* obj)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
- mirror::Object* MarkFromReadBarrierWithMeasurements(Thread* const self,
- mirror::Object* from_ref)
+ EXPORT mirror::Object* MarkFromReadBarrierWithMeasurements(Thread* const self,
+ mirror::Object* from_ref)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
void DumpPerformanceInfo(std::ostream& os) override REQUIRES(!rb_slow_path_histogram_lock_);
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 6c9c005238..0274d987c8 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -38,7 +38,7 @@
#include "thread-current-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/garbage_collector.h b/runtime/gc/collector/garbage_collector.h
index 40348d614d..ea5acdf202 100644
--- a/runtime/gc/collector/garbage_collector.h
+++ b/runtime/gc/collector/garbage_collector.h
@@ -21,6 +21,7 @@
#include <list>
#include "base/histogram.h"
+#include "base/macros.h"
#include "base/metrics/metrics.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
@@ -32,7 +33,7 @@
#include "object_byte_pair.h"
#include "object_callbacks.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
diff --git a/runtime/gc/collector/gc_type.h b/runtime/gc/collector/gc_type.h
index f03ba1f0c6..e666c04826 100644
--- a/runtime/gc/collector/gc_type.h
+++ b/runtime/gc/collector/gc_type.h
@@ -19,7 +19,9 @@
#include <iosfwd>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/immune_region.cc b/runtime/gc/collector/immune_region.cc
index 8a04c178b5..a6b90b87be 100644
--- a/runtime/gc/collector/immune_region.cc
+++ b/runtime/gc/collector/immune_region.cc
@@ -19,7 +19,7 @@
#include "gc/space/space-inl.h"
#include "mirror/object.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/immune_region.h b/runtime/gc/collector/immune_region.h
index 80ee44cf68..ee0ce847c9 100644
--- a/runtime/gc/collector/immune_region.h
+++ b/runtime/gc/collector/immune_region.h
@@ -19,7 +19,7 @@
#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
} // namespace mirror
diff --git a/runtime/gc/collector/immune_spaces.cc b/runtime/gc/collector/immune_spaces.cc
index 683ca8de0b..28704af919 100644
--- a/runtime/gc/collector/immune_spaces.cc
+++ b/runtime/gc/collector/immune_spaces.cc
@@ -24,7 +24,7 @@
#include "mirror/object.h"
#include "oat_file.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/immune_spaces.h b/runtime/gc/collector/immune_spaces.h
index 950c35b27a..5ee4ffc32d 100644
--- a/runtime/gc/collector/immune_spaces.h
+++ b/runtime/gc/collector/immune_spaces.h
@@ -24,7 +24,7 @@
#include <set>
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
class ContinuousSpace;
diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc
index 2337eadf7a..cee3d242e6 100644
--- a/runtime/gc/collector/immune_spaces_test.cc
+++ b/runtime/gc/collector/immune_spaces_test.cc
@@ -24,7 +24,7 @@
#include "oat_file.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
} // namespace mirror
diff --git a/runtime/gc/collector/iteration.h b/runtime/gc/collector/iteration.h
index 348f49df00..d70a30b829 100644
--- a/runtime/gc/collector/iteration.h
+++ b/runtime/gc/collector/iteration.h
@@ -21,11 +21,12 @@
#include <vector>
#include "android-base/macros.h"
+#include "base/macros.h"
#include "base/timing_logger.h"
#include "gc/gc_cause.h"
#include "object_byte_pair.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/mark_compact-inl.h b/runtime/gc/collector/mark_compact-inl.h
index fe67906d4b..454d79ae88 100644
--- a/runtime/gc/collector/mark_compact-inl.h
+++ b/runtime/gc/collector/mark_compact-inl.h
@@ -21,7 +21,7 @@
#include "mark_compact.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index ce7c739c8d..e5bac5a9ba 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -93,7 +93,7 @@ using ::android::base::ParseBoolResult;
} // namespace
#endif
-namespace art {
+namespace art HIDDEN {
static bool HaveMremapDontunmap() {
const size_t page_size = GetPageSizeSlow();
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 4f0e6e04fa..076249bf11 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -37,9 +37,9 @@
#include "immune_spaces.h"
#include "offsets.h"
-namespace art {
+namespace art HIDDEN {
-bool KernelSupportsUffd();
+EXPORT bool KernelSupportsUffd();
namespace mirror {
class DexCache;
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 2257b0db8f..2eac037940 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -25,7 +25,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/reference.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index fdaf5a2f57..984d71ca25 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -46,7 +46,7 @@
#include "thread-current-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 12fd7f9995..2a628a40fe 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -29,7 +29,7 @@
#include "immune_spaces.h"
#include "offsets.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
diff --git a/runtime/gc/collector/object_byte_pair.h b/runtime/gc/collector/object_byte_pair.h
index 16ef06b6dd..06268b94ee 100644
--- a/runtime/gc/collector/object_byte_pair.h
+++ b/runtime/gc/collector/object_byte_pair.h
@@ -19,7 +19,9 @@
#include <inttypes.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/partial_mark_sweep.cc b/runtime/gc/collector/partial_mark_sweep.cc
index e283a9583a..dc6d99e1dc 100644
--- a/runtime/gc/collector/partial_mark_sweep.cc
+++ b/runtime/gc/collector/partial_mark_sweep.cc
@@ -20,7 +20,7 @@
#include "gc/space/space.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/partial_mark_sweep.h b/runtime/gc/collector/partial_mark_sweep.h
index 76c44a35bb..8b2c3a8d4c 100644
--- a/runtime/gc/collector/partial_mark_sweep.h
+++ b/runtime/gc/collector/partial_mark_sweep.h
@@ -19,7 +19,9 @@
#include "mark_sweep.h"
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/semi_space-inl.h b/runtime/gc/collector/semi_space-inl.h
index ef6df08b45..8ef6512b58 100644
--- a/runtime/gc/collector/semi_space-inl.h
+++ b/runtime/gc/collector/semi_space-inl.h
@@ -22,7 +22,7 @@
#include "gc/accounting/heap_bitmap.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 397271b03d..77800c32e0 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -52,7 +52,7 @@
using ::art::mirror::Object;
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index 6d3ac0846e..b6d98ce84d 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -29,7 +29,7 @@
#include "mirror/object_reference.h"
#include "offsets.h"
-namespace art {
+namespace art HIDDEN {
class Thread;
diff --git a/runtime/gc/collector/sticky_mark_sweep.cc b/runtime/gc/collector/sticky_mark_sweep.cc
index e1bd16c1fb..96c13229c0 100644
--- a/runtime/gc/collector/sticky_mark_sweep.cc
+++ b/runtime/gc/collector/sticky_mark_sweep.cc
@@ -24,7 +24,7 @@
#include "runtime.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector/sticky_mark_sweep.h b/runtime/gc/collector/sticky_mark_sweep.h
index f65413d153..0c1cd2d114 100644
--- a/runtime/gc/collector/sticky_mark_sweep.h
+++ b/runtime/gc/collector/sticky_mark_sweep.h
@@ -20,7 +20,7 @@
#include "base/macros.h"
#include "partial_mark_sweep.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
index 290860136b..3c19079c08 100644
--- a/runtime/gc/collector_type.h
+++ b/runtime/gc/collector_type.h
@@ -19,7 +19,9 @@
#include <iosfwd>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
// Which types of collections are able to be performed.
diff --git a/runtime/gc/gc_cause.cc b/runtime/gc/gc_cause.cc
index 02fe2f975c..ec213e50e8 100644
--- a/runtime/gc/gc_cause.cc
+++ b/runtime/gc/gc_cause.cc
@@ -23,7 +23,7 @@
#include <ostream>
-namespace art {
+namespace art HIDDEN {
namespace gc {
const char* PrettyCause(GcCause cause) {
diff --git a/runtime/gc/gc_cause.h b/runtime/gc/gc_cause.h
index 5c039b31ee..e035510969 100644
--- a/runtime/gc/gc_cause.h
+++ b/runtime/gc/gc_cause.h
@@ -19,7 +19,9 @@
#include <iosfwd>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
// What caused the GC?
diff --git a/runtime/gc/gc_pause_listener.h b/runtime/gc/gc_pause_listener.h
index da35d2a0de..a626a3ca29 100644
--- a/runtime/gc/gc_pause_listener.h
+++ b/runtime/gc/gc_pause_listener.h
@@ -17,7 +17,9 @@
#ifndef ART_RUNTIME_GC_GC_PAUSE_LISTENER_H_
#define ART_RUNTIME_GC_GC_PAUSE_LISTENER_H_
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
class GcPauseListener {
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 9d4b4a0986..5d6e149b98 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -38,7 +38,7 @@
#include "verify_object.h"
#include "write_barrier-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
template <bool kInstrumented, bool kCheckLargeObject, typename PreFenceVisitor>
diff --git a/runtime/gc/heap-visit-objects-inl.h b/runtime/gc/heap-visit-objects-inl.h
index a235c44033..2b719ee241 100644
--- a/runtime/gc/heap-visit-objects-inl.h
+++ b/runtime/gc/heap-visit-objects-inl.h
@@ -29,7 +29,7 @@
#include "thread-current-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
// Visit objects when threads aren't suspended. If concurrent moving
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index c10f41719a..b7821a3e98 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -108,7 +108,7 @@
#include "verify_object-inl.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
#ifdef ART_TARGET_ANDROID
namespace {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index ab7a95f55a..d0944e0f55 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -49,7 +49,7 @@
#include "scoped_thread_state_change.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
class ConditionVariable;
enum class InstructionSet;
@@ -387,8 +387,8 @@ class Heap {
bool IsMovableObject(ObjPtr<mirror::Object> obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Enables us to compacting GC until objects are released.
- void IncrementDisableMovingGC(Thread* self) REQUIRES(!*gc_complete_lock_);
- void DecrementDisableMovingGC(Thread* self) REQUIRES(!*gc_complete_lock_);
+ EXPORT void IncrementDisableMovingGC(Thread* self) REQUIRES(!*gc_complete_lock_);
+ EXPORT void DecrementDisableMovingGC(Thread* self) REQUIRES(!*gc_complete_lock_);
// Temporarily disable thread flip for JNI critical calls.
void IncrementDisableThreadFlip(Thread* self) REQUIRES(!*thread_flip_lock_);
@@ -407,7 +407,7 @@ class Heap {
// Initiates an explicit garbage collection. Guarantees that a GC started after this call has
// completed.
- void CollectGarbage(bool clear_soft_references, GcCause cause = kGcCauseExplicit)
+ EXPORT void CollectGarbage(bool clear_soft_references, GcCause cause = kGcCauseExplicit)
REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
// Does a concurrent GC, provided the GC numbered requested_gc_num has not already been
@@ -485,7 +485,8 @@ class Heap {
// Blocks the caller until the garbage collector becomes idle and returns the type of GC we
// waited for. Only waits for running collections, ignoring a requested but unstarted GC. Only
// heuristic, since a new GC may have started by the time we return.
- collector::GcType WaitForGcToComplete(GcCause cause, Thread* self) REQUIRES(!*gc_complete_lock_);
+ EXPORT collector::GcType WaitForGcToComplete(GcCause cause, Thread* self)
+ REQUIRES(!*gc_complete_lock_);
// Update the heap's process state to a new value, may cause compaction to occur.
void UpdateProcessState(ProcessState old_process_state, ProcessState new_process_state)
@@ -554,7 +555,7 @@ class Heap {
return rb_table_.get();
}
- void AddFinalizerReference(Thread* self, ObjPtr<mirror::Object>* object);
+ EXPORT void AddFinalizerReference(Thread* self, ObjPtr<mirror::Object>* object);
// Returns the number of bytes currently allocated.
// The result should be treated as an approximation, if it is being concurrently updated.
@@ -605,7 +606,7 @@ class Heap {
// Implements java.lang.Runtime.totalMemory, returning approximate amount of memory currently
// consumed by an application.
- size_t GetTotalMemory() const;
+ EXPORT size_t GetTotalMemory() const;
// Returns approximately how much free memory we have until the next GC happens.
size_t GetFreeMemoryUntilGC() const {
@@ -628,7 +629,8 @@ class Heap {
// 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
+ EXPORT space::ContinuousSpace* FindContinuousSpaceFromObject(ObjPtr<mirror::Object>,
+ bool fail_ok) const
REQUIRES_SHARED(Locks::mutator_lock_);
space::ContinuousSpace* FindContinuousSpaceFromAddress(const mirror::Object* addr) const
@@ -638,7 +640,7 @@ class Heap {
bool fail_ok) const
REQUIRES_SHARED(Locks::mutator_lock_);
- space::Space* FindSpaceFromObject(ObjPtr<mirror::Object> obj, bool fail_ok) const
+ EXPORT space::Space* FindSpaceFromObject(ObjPtr<mirror::Object> obj, bool fail_ok) const
REQUIRES_SHARED(Locks::mutator_lock_);
space::Space* FindSpaceFromAddress(const void* ptr) const
@@ -654,7 +656,7 @@ class Heap {
REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
// Deflate monitors, ... and trim the spaces.
- void Trim(Thread* self) REQUIRES(!*gc_complete_lock_);
+ EXPORT void Trim(Thread* self) REQUIRES(!*gc_complete_lock_);
void RevokeThreadLocalBuffers(Thread* thread);
void RevokeRosAllocThreadLocalBuffers(Thread* thread);
@@ -683,12 +685,11 @@ class Heap {
void PreZygoteFork() NO_THREAD_SAFETY_ANALYSIS;
// Mark and empty stack.
- void FlushAllocStack()
- REQUIRES_SHARED(Locks::mutator_lock_)
+ EXPORT void FlushAllocStack() REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(Locks::heap_bitmap_lock_);
// Revoke all the thread-local allocation stacks.
- void RevokeAllThreadLocalAllocationStacks(Thread* self)
+ EXPORT void RevokeAllThreadLocalAllocationStacks(Thread* self)
REQUIRES(Locks::mutator_lock_, !Locks::runtime_shutdown_lock_, !Locks::thread_list_lock_);
// Mark all the objects in the allocation stack in the specified bitmap.
@@ -715,7 +716,9 @@ class Heap {
return boot_image_spaces_;
}
- bool ObjectIsInBootImageSpace(ObjPtr<mirror::Object> obj) const
+ // TODO(b/260881207): refactor to only use this function in debug builds and
+ // remove EXPORT.
+ EXPORT bool ObjectIsInBootImageSpace(ObjPtr<mirror::Object> obj) const
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsInBootImageOatFile(const void* p) const
@@ -772,7 +775,7 @@ class Heap {
}
void DumpSpaces(std::ostream& stream) const REQUIRES_SHARED(Locks::mutator_lock_);
- std::string DumpSpaces() const REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT std::string DumpSpaces() const REQUIRES_SHARED(Locks::mutator_lock_);
// GC performance measuring
void DumpGcPerformanceInfo(std::ostream& os)
@@ -921,9 +924,7 @@ class Heap {
// Also update state (bytes_until_sample).
// By calling JHPCheckNonTlabSampleAllocation from different functions for Large allocations and
// non-moving allocations we are able to use the stack to identify these allocations separately.
- void JHPCheckNonTlabSampleAllocation(Thread* self,
- mirror::Object* ret,
- size_t alloc_size);
+ EXPORT void JHPCheckNonTlabSampleAllocation(Thread* self, mirror::Object* ret, size_t alloc_size);
// In Tlab case: Calculate the next tlab size (location of next sample point) and whether
// a sample should be taken.
size_t JHPCalculateNextTlabSize(Thread* self,
@@ -984,31 +985,31 @@ class Heap {
bool IsGCDisabledForShutdown() const REQUIRES(!*gc_complete_lock_);
// Create a new alloc space and compact default alloc space to it.
- HomogeneousSpaceCompactResult PerformHomogeneousSpaceCompact()
+ EXPORT HomogeneousSpaceCompactResult PerformHomogeneousSpaceCompact()
REQUIRES(!*gc_complete_lock_, !process_state_update_lock_);
- bool SupportHomogeneousSpaceCompactAndCollectorTransitions() const;
+ EXPORT bool SupportHomogeneousSpaceCompactAndCollectorTransitions() const;
// Install an allocation listener.
- void SetAllocationListener(AllocationListener* l);
+ EXPORT void SetAllocationListener(AllocationListener* l);
// Remove an allocation listener. Note: the listener must not be deleted, as for performance
// reasons, we assume it stays valid when we read it (so that we don't require a lock).
- void RemoveAllocationListener();
+ EXPORT void RemoveAllocationListener();
// Install a gc pause listener.
- void SetGcPauseListener(GcPauseListener* l);
+ EXPORT void SetGcPauseListener(GcPauseListener* l);
// Get the currently installed gc pause listener, or null.
GcPauseListener* GetGcPauseListener() {
return gc_pause_listener_.load(std::memory_order_acquire);
}
// Remove a gc pause listener. Note: the listener must not be deleted, as for performance
// reasons, we assume it stays valid when we read it (so that we don't require a lock).
- void RemoveGcPauseListener();
+ EXPORT void RemoveGcPauseListener();
- const Verification* GetVerification() const;
+ EXPORT const Verification* GetVerification() const;
void PostForkChildAction(Thread* self) REQUIRES(!*gc_complete_lock_);
- void TraceHeapSize(size_t heap_size);
+ EXPORT void TraceHeapSize(size_t heap_size);
bool AddHeapTask(gc::HeapTask* task);
@@ -1114,17 +1115,16 @@ class Heap {
// attempt failed.
// Called with thread suspension disallowed, but re-enables it, and may suspend, internally.
// Returns null if instrumentation or the allocator changed.
- mirror::Object* AllocateInternalWithGc(Thread* self,
- AllocatorType allocator,
- bool instrumented,
- size_t num_bytes,
- size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated,
- ObjPtr<mirror::Class>* klass)
+ EXPORT mirror::Object* AllocateInternalWithGc(Thread* self,
+ AllocatorType allocator,
+ bool instrumented,
+ size_t num_bytes,
+ size_t* bytes_allocated,
+ size_t* usable_size,
+ size_t* bytes_tl_bulk_allocated,
+ ObjPtr<mirror::Class>* klass)
REQUIRES(!Locks::thread_suspend_count_lock_, !*gc_complete_lock_, !*pending_task_lock_)
- REQUIRES(Roles::uninterruptible_)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES(Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_);
// Allocate into a specific space.
mirror::Object* AllocateInto(Thread* self,
@@ -1148,13 +1148,13 @@ class Heap {
size_t* bytes_tl_bulk_allocated)
REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* AllocWithNewTLAB(Thread* self,
- AllocatorType allocator_type,
- size_t alloc_size,
- bool grow,
- size_t* bytes_allocated,
- size_t* usable_size,
- size_t* bytes_tl_bulk_allocated)
+ EXPORT mirror::Object* AllocWithNewTLAB(Thread* self,
+ AllocatorType allocator_type,
+ size_t alloc_size,
+ bool grow,
+ size_t* bytes_allocated,
+ size_t* usable_size,
+ size_t* bytes_tl_bulk_allocated)
REQUIRES_SHARED(Locks::mutator_lock_);
void ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType allocator_type)
@@ -1177,12 +1177,11 @@ class Heap {
void RequestCollectorTransition(CollectorType desired_collector_type, uint64_t delta_time)
REQUIRES(!*pending_task_lock_);
- void RequestConcurrentGCAndSaveObject(Thread* self,
- bool force_full,
- uint32_t observed_gc_num,
- ObjPtr<mirror::Object>* obj)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!*pending_task_lock_);
+ EXPORT void RequestConcurrentGCAndSaveObject(Thread* self,
+ bool force_full,
+ uint32_t observed_gc_num,
+ ObjPtr<mirror::Object>* obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!*pending_task_lock_);
static constexpr uint32_t GC_NUM_ANY = std::numeric_limits<uint32_t>::max();
@@ -1261,9 +1260,10 @@ class Heap {
void PushOnAllocationStackWithInternalGC(Thread* self, ObjPtr<mirror::Object>* obj)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
- void PushOnThreadLocalAllocationStackWithInternalGC(Thread* thread, ObjPtr<mirror::Object>* obj)
+ EXPORT void PushOnThreadLocalAllocationStackWithInternalGC(Thread* thread,
+ ObjPtr<mirror::Object>* obj)
REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
+ REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
void ClearPendingTrim(Thread* self) REQUIRES(!*pending_task_lock_);
void ClearPendingCollectorTransition(Thread* self) REQUIRES(!*pending_task_lock_);
@@ -1294,10 +1294,11 @@ class Heap {
void UpdateGcCountRateHistograms() REQUIRES(gc_complete_lock_);
// GC stress mode attempts to do one GC per unique backtrace.
- void CheckGcStressMode(Thread* self, ObjPtr<mirror::Object>* obj)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!*gc_complete_lock_, !*pending_task_lock_,
- !*backtrace_lock_, !process_state_update_lock_);
+ EXPORT void CheckGcStressMode(Thread* self, ObjPtr<mirror::Object>* obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!*gc_complete_lock_,
+ !*pending_task_lock_,
+ !*backtrace_lock_,
+ !process_state_update_lock_);
collector::GcType NonStickyGcType() const {
return HasZygoteSpace() ? collector::kGcTypePartial : collector::kGcTypeFull;
@@ -1322,7 +1323,9 @@ class Heap {
void IncrementFreedEver();
// Remove a vlog code from heap-inl.h which is transitively included in half the world.
- static void VlogHeapGrowth(size_t max_allowed_footprint, size_t new_footprint, size_t alloc_size);
+ EXPORT static void VlogHeapGrowth(size_t max_allowed_footprint,
+ size_t new_footprint,
+ size_t alloc_size);
// Return our best approximation of the number of bytes of native memory that
// are currently in use, and could possibly be reclaimed as an indirect result
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 42ba911062..bd8fdc6b46 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -28,7 +28,7 @@
#include "mirror/object_array-inl.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class HeapTest : public CommonRuntimeTest {
diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
index a7583fe7f1..168feefea0 100644
--- a/runtime/gc/heap_verification_test.cc
+++ b/runtime/gc/heap_verification_test.cc
@@ -28,7 +28,7 @@
#include "scoped_thread_state_change-inl.h"
#include "verification-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class VerificationTest : public CommonRuntimeTest {
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index f24c94279c..cb777c895c 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -36,7 +36,7 @@
#include "thread_pool.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
static constexpr bool kAsyncReferenceQueueAdd = false;
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 0f84211a87..48aff6c2a2 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -17,12 +17,13 @@
#ifndef ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
+#include "base/macros.h"
#include "base/locks.h"
#include "jni.h"
#include "reference_queue.h"
#include "runtime_globals.h"
-namespace art {
+namespace art HIDDEN {
class IsMarkedVisitor;
class TimingLogger;
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index 53eef9c027..82fd89ecb1 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -25,7 +25,7 @@
#include "mirror/reference-inl.h"
#include "object_callbacks.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
ReferenceQueue::ReferenceQueue(Mutex* lock) : lock_(lock), list_(nullptr) {
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index 69f04d783a..d43eb347a9 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -23,6 +23,7 @@
#include "base/atomic.h"
#include "base/locks.h"
+#include "base/macros.h"
#include "base/timing_logger.h"
#include "jni.h"
#include "obj_ptr.h"
@@ -30,7 +31,7 @@
#include "runtime_globals.h"
#include "thread_pool.h"
-namespace art {
+namespace art HIDDEN {
class Mutex;
diff --git a/runtime/gc/reference_queue_test.cc b/runtime/gc/reference_queue_test.cc
index c8e71b02ac..2b5c3fdea7 100644
--- a/runtime/gc/reference_queue_test.cc
+++ b/runtime/gc/reference_queue_test.cc
@@ -23,7 +23,7 @@
#include "reference_queue.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class ReferenceQueueTest : public CommonRuntimeTest {
diff --git a/runtime/gc/scoped_gc_critical_section.cc b/runtime/gc/scoped_gc_critical_section.cc
index 7a0a6e8736..368649a563 100644
--- a/runtime/gc/scoped_gc_critical_section.cc
+++ b/runtime/gc/scoped_gc_critical_section.cc
@@ -21,7 +21,7 @@
#include "runtime.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
const char* GCCriticalSection::Enter(GcCause cause, CollectorType type) {
diff --git a/runtime/gc/scoped_gc_critical_section.h b/runtime/gc/scoped_gc_critical_section.h
index 8ad01580c2..8481767667 100644
--- a/runtime/gc/scoped_gc_critical_section.h
+++ b/runtime/gc/scoped_gc_critical_section.h
@@ -18,10 +18,11 @@
#define ART_RUNTIME_GC_SCOPED_GC_CRITICAL_SECTION_H_
#include "base/locks.h"
+#include "base/macros.h"
#include "collector_type.h"
#include "gc_cause.h"
-namespace art {
+namespace art HIDDEN {
class Thread;
@@ -35,10 +36,10 @@ class GCCriticalSection {
~GCCriticalSection() {}
// Starts a GCCriticalSection. Returns the previous no-suspension reason.
- const char* Enter(GcCause cause, CollectorType type) ACQUIRE(Roles::uninterruptible_);
+ EXPORT const char* Enter(GcCause cause, CollectorType type) ACQUIRE(Roles::uninterruptible_);
// Ends a GCCriticalSection. Takes the old no-suspension reason.
- void Exit(const char* old_reason) RELEASE(Roles::uninterruptible_);
+ EXPORT void Exit(const char* old_reason) RELEASE(Roles::uninterruptible_);
private:
Thread* const self_;
@@ -50,9 +51,9 @@ class GCCriticalSection {
// suspended.
class ScopedGCCriticalSection {
public:
- ScopedGCCriticalSection(Thread* self, GcCause cause, CollectorType collector_type)
+ EXPORT ScopedGCCriticalSection(Thread* self, GcCause cause, CollectorType collector_type)
ACQUIRE(Roles::uninterruptible_);
- ~ScopedGCCriticalSection() RELEASE(Roles::uninterruptible_);
+ EXPORT ~ScopedGCCriticalSection() RELEASE(Roles::uninterruptible_);
private:
GCCriticalSection critical_section_;
diff --git a/runtime/gc/space/bump_pointer_space-inl.h b/runtime/gc/space/bump_pointer_space-inl.h
index 2774b9e71c..6751344bc4 100644
--- a/runtime/gc/space/bump_pointer_space-inl.h
+++ b/runtime/gc/space/bump_pointer_space-inl.h
@@ -22,7 +22,7 @@
#include "base/bit_utils.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/bump_pointer_space-walk-inl.h b/runtime/gc/space/bump_pointer_space-walk-inl.h
index 89e42bcf27..86af0451de 100644
--- a/runtime/gc/space/bump_pointer_space-walk-inl.h
+++ b/runtime/gc/space/bump_pointer_space-walk-inl.h
@@ -25,7 +25,7 @@
#include <memory>
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/bump_pointer_space.cc b/runtime/gc/space/bump_pointer_space.cc
index aa85ba1247..17e08357e8 100644
--- a/runtime/gc/space/bump_pointer_space.cc
+++ b/runtime/gc/space/bump_pointer_space.cc
@@ -20,7 +20,7 @@
#include "mirror/object-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/bump_pointer_space.h b/runtime/gc/space/bump_pointer_space.h
index d5ab5069ec..77beb476e6 100644
--- a/runtime/gc/space/bump_pointer_space.h
+++ b/runtime/gc/space/bump_pointer_space.h
@@ -22,7 +22,7 @@
#include <deque>
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
@@ -39,7 +39,7 @@ namespace space {
// A bump pointer space allocates by incrementing a pointer, it doesn't provide a free
// implementation as its intended to be evacuated.
-class BumpPointerSpace final : public ContinuousMemMapAllocSpace {
+class EXPORT BumpPointerSpace final : public ContinuousMemMapAllocSpace {
public:
using WalkCallback = void (*)(void *, void *, int, void *);
diff --git a/runtime/gc/space/dlmalloc_space-inl.h b/runtime/gc/space/dlmalloc_space-inl.h
index 6041fd02af..0d9467314b 100644
--- a/runtime/gc/space/dlmalloc_space-inl.h
+++ b/runtime/gc/space/dlmalloc_space-inl.h
@@ -21,7 +21,7 @@
#include "gc/allocator/art-dlmalloc.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index e5253cd697..b45e4824ed 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -16,6 +16,8 @@
#include "dlmalloc_space-inl.h"
+#include <sys/mman.h>
+
#include "base/logging.h" // For VLOG.
#include "base/time_utils.h"
#include "base/utils.h"
@@ -32,12 +34,60 @@
#include "thread.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
static constexpr bool kPrefetchDuringDlMallocFreeList = true;
+// Callback for mspace_inspect_all that will madvise(2) unused pages back to
+// the kernel.
+void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* arg) {
+ // Is this chunk in use?
+ if (used_bytes != 0) {
+ return;
+ }
+ // Do we have any whole pages to give back?
+ start = reinterpret_cast<void*>(art::RoundUp(reinterpret_cast<uintptr_t>(start), art::gPageSize));
+ end = reinterpret_cast<void*>(art::RoundDown(reinterpret_cast<uintptr_t>(end), art::gPageSize));
+ if (end > start) {
+ size_t length = reinterpret_cast<uint8_t*>(end) - reinterpret_cast<uint8_t*>(start);
+ int rc = madvise(start, length, MADV_DONTNEED);
+ if (UNLIKELY(rc != 0)) {
+ errno = rc;
+ PLOG(FATAL) << "madvise failed during heap trimming";
+ }
+ size_t* reclaimed = reinterpret_cast<size_t*>(arg);
+ *reclaimed += length;
+ }
+}
+
+// Callback for mspace_inspect_all that will count the number of bytes
+// allocated.
+void DlmallocBytesAllocatedCallback([[maybe_unused]] void* start,
+ [[maybe_unused]] void* end,
+ size_t used_bytes,
+ void* arg) {
+ if (used_bytes == 0) {
+ return;
+ }
+ size_t* bytes_allocated = reinterpret_cast<size_t*>(arg);
+ *bytes_allocated += used_bytes + sizeof(size_t);
+}
+
+// Callback for mspace_inspect_all that will count the number of objects
+// allocated.
+void DlmallocObjectsAllocatedCallback([[maybe_unused]] void* start,
+ [[maybe_unused]] void* end,
+ size_t used_bytes,
+ void* arg) {
+ if (used_bytes == 0) {
+ return;
+ }
+ size_t* objects_allocated = reinterpret_cast<size_t*>(arg);
+ ++(*objects_allocated);
+}
+
DlMallocSpace::DlMallocSpace(MemMap&& mem_map,
size_t initial_size,
const std::string& name,
diff --git a/runtime/gc/space/dlmalloc_space.h b/runtime/gc/space/dlmalloc_space.h
index 429b4d035a..774d2e3c80 100644
--- a/runtime/gc/space/dlmalloc_space.h
+++ b/runtime/gc/space/dlmalloc_space.h
@@ -20,7 +20,7 @@
#include "malloc_space.h"
#include "space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
@@ -188,6 +188,14 @@ class DlMallocSpace : public MallocSpace {
};
} // namespace space
+
+namespace allocator {
+
+// Callback from dlmalloc when it needs to increase the footprint.
+// Must be implemented outside of art-dlmalloc.cc.
+void* ArtDlMallocMoreCore(void* mspace, intptr_t increment);
+
+} // namespace allocator
} // namespace gc
} // namespace art
diff --git a/runtime/gc/space/dlmalloc_space_random_test.cc b/runtime/gc/space/dlmalloc_space_random_test.cc
index b653bcf03a..bcca442fb8 100644
--- a/runtime/gc/space/dlmalloc_space_random_test.cc
+++ b/runtime/gc/space/dlmalloc_space_random_test.cc
@@ -18,7 +18,7 @@
#include "dlmalloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
namespace {
diff --git a/runtime/gc/space/dlmalloc_space_static_test.cc b/runtime/gc/space/dlmalloc_space_static_test.cc
index 74dd765dfd..c07a8eaa8b 100644
--- a/runtime/gc/space/dlmalloc_space_static_test.cc
+++ b/runtime/gc/space/dlmalloc_space_static_test.cc
@@ -18,7 +18,7 @@
#include "dlmalloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
namespace {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 7d0bb1b674..3314c14fca 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -69,7 +69,7 @@
#include "runtime.h"
#include "space-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 5271489fc6..63a47c86c1 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -24,7 +24,7 @@
#include "runtime.h"
#include "space.h"
-namespace art {
+namespace art HIDDEN {
class DexFile;
enum class InstructionSet;
@@ -152,9 +152,9 @@ class ImageSpace : public MemMapSpace {
// Try to open an existing app image space for an oat file,
// using the boot image spaces from the current Runtime.
- static std::unique_ptr<ImageSpace> CreateFromAppImage(const char* image,
- const OatFile* oat_file,
- std::string* error_msg)
+ EXPORT static std::unique_ptr<ImageSpace> CreateFromAppImage(const char* image,
+ const OatFile* oat_file,
+ std::string* error_msg)
REQUIRES_SHARED(Locks::mutator_lock_);
// Try to open an existing app image space for an the oat file and given boot image spaces.
static std::unique_ptr<ImageSpace> CreateFromAppImage(
@@ -167,7 +167,7 @@ class ImageSpace : public MemMapSpace {
static bool IsBootClassPathOnDisk(InstructionSet image_isa);
// Give access to the OatFile.
- const OatFile* GetOatFile() const;
+ EXPORT const OatFile* GetOatFile() const;
// Releases the OatFile from the ImageSpace so it can be transfer to
// the caller, presumably the OatFileManager.
@@ -238,8 +238,8 @@ class ImageSpace : public MemMapSpace {
// Returns the checksums for the boot image, extensions and extra boot class path dex files,
// based on the image spaces and boot class path dex files loaded in memory.
// The `image_spaces` must correspond to the head of the `boot_class_path`.
- static std::string GetBootClassPathChecksums(ArrayRef<ImageSpace* const> image_spaces,
- ArrayRef<const DexFile* const> boot_class_path);
+ EXPORT static std::string GetBootClassPathChecksums(
+ ArrayRef<ImageSpace* const> image_spaces, ArrayRef<const DexFile* const> boot_class_path);
// Returns the total number of components (jar files) associated with the image spaces.
static size_t GetNumberOfComponents(ArrayRef<gc::space::ImageSpace* const> image_spaces);
@@ -255,7 +255,7 @@ class ImageSpace : public MemMapSpace {
/*out*/std::string* error_msg);
// Expand a single image location to multi-image locations based on the dex locations.
- static std::vector<std::string> ExpandMultiImageLocations(
+ EXPORT static std::vector<std::string> ExpandMultiImageLocations(
ArrayRef<const std::string> dex_locations,
const std::string& image_location,
bool boot_image_extension = false);
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index 8fb39e849b..e6b758fe55 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -28,7 +28,7 @@
#include "noop_compiler_callbacks.h"
#include "oat_file.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index b0db30b176..3d9fd5a620 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -36,7 +36,7 @@
#include "space-inl.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index 5588f5f7c6..ae1526d818 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -27,7 +27,7 @@
#include <set>
#include <vector>
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index 99a67c5812..1d1bc6e683 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -19,7 +19,7 @@
#include "base/time_utils.h"
#include "space_test.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index b25c4fab38..ca2991a8b8 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -35,7 +35,7 @@
#include "thread.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 59ab3f3214..73ce4e7436 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -24,7 +24,7 @@
#include "base/memory_tool.h"
#include "base/mutex.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/space/memory_tool_malloc_space-inl.h b/runtime/gc/space/memory_tool_malloc_space-inl.h
index ba088893f7..3fc2b7ab40 100644
--- a/runtime/gc/space/memory_tool_malloc_space-inl.h
+++ b/runtime/gc/space/memory_tool_malloc_space-inl.h
@@ -23,7 +23,7 @@
#include "memory_tool_settings.h"
#include "mirror/object-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/memory_tool_malloc_space.h b/runtime/gc/space/memory_tool_malloc_space.h
index ce72b5b435..c76bb9c4ad 100644
--- a/runtime/gc/space/memory_tool_malloc_space.h
+++ b/runtime/gc/space/memory_tool_malloc_space.h
@@ -19,7 +19,7 @@
#include "malloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/memory_tool_settings.h b/runtime/gc/space/memory_tool_settings.h
index e9333c8c97..6fe4f59c34 100644
--- a/runtime/gc/space/memory_tool_settings.h
+++ b/runtime/gc/space/memory_tool_settings.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_SPACE_MEMORY_TOOL_SETTINGS_H_
#define ART_RUNTIME_GC_SPACE_MEMORY_TOOL_SETTINGS_H_
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h
index 4376137cb4..d67fc0ef47 100644
--- a/runtime/gc/space/region_space-inl.h
+++ b/runtime/gc/space/region_space-inl.h
@@ -22,7 +22,7 @@
#include "region_space.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 49ea2d64e6..e891739ec7 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -24,7 +24,7 @@
#include "mirror/object-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index 98f2060df1..c6b68250fc 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -25,7 +25,7 @@
#include <functional>
#include <map>
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace accounting {
@@ -99,7 +99,7 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_) {
return AllocationSizeNonvirtual(obj, usable_size);
}
- size_t AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size)
+ EXPORT size_t AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_);
size_t Free(Thread*, mirror::Object*) override {
@@ -117,7 +117,7 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
return &mark_bitmap_;
}
- void Clear() override REQUIRES(!region_lock_);
+ EXPORT void Clear() override REQUIRES(!region_lock_);
// Remove read and write memory protection from the whole region space,
// i.e. make memory pages backing the region area not readable and not
@@ -128,7 +128,7 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
// pages backing the region area readable and writable. This method is useful
// to avoid page protection faults when dumping information about an invalid
// reference.
- void Unprotect();
+ EXPORT void Unprotect();
// Change the non growth limit capacity to new capacity by shrinking or expanding the map.
// Currently, only shrinking is supported.
@@ -137,15 +137,15 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
// growth limit.
void ClampGrowthLimit(size_t new_capacity) REQUIRES(!region_lock_);
- void Dump(std::ostream& os) const override;
+ EXPORT void Dump(std::ostream& os) const override;
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_);
+ EXPORT void DumpNonFreeRegions(std::ostream& os) REQUIRES(!region_lock_);
- size_t RevokeThreadLocalBuffers(Thread* thread) override REQUIRES(!region_lock_);
+ EXPORT size_t RevokeThreadLocalBuffers(Thread* thread) override REQUIRES(!region_lock_);
size_t RevokeThreadLocalBuffers(Thread* thread, const bool reuse) REQUIRES(!region_lock_);
- size_t RevokeAllThreadLocalBuffers() override
+ EXPORT size_t RevokeAllThreadLocalBuffers() override
REQUIRES(!Locks::runtime_shutdown_lock_, !Locks::thread_list_lock_, !region_lock_);
void AssertThreadLocalBuffersAreRevoked(Thread* thread) REQUIRES(!region_lock_);
void AssertAllThreadLocalBuffersAreRevoked()
@@ -227,7 +227,7 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
accounting::ContinuousSpaceBitmap::SweepCallback* GetSweepCallback() override {
return nullptr;
}
- bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+ EXPORT bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_);
// Object alignment within the space.
@@ -453,11 +453,11 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
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)
+ EXPORT 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)
+ EXPORT void UnfreeLargeTail(RegionSpace* region_space, uint32_t alloc_time)
REQUIRES(region_space->region_lock_);
void MarkAsAllocated(RegionSpace* region_space, uint32_t alloc_time)
@@ -715,7 +715,7 @@ class RegionSpace final : public ContinuousMemMapAllocSpace {
}
}
- Region* AllocateRegion(bool for_evac) REQUIRES(region_lock_);
+ EXPORT Region* AllocateRegion(bool for_evac) REQUIRES(region_lock_);
void RevokeThreadLocalBuffersLocked(Thread* thread, bool reuse) REQUIRES(region_lock_);
// Scan region range [`begin`, `end`) in increasing order to try to
diff --git a/runtime/gc/space/rosalloc_space-inl.h b/runtime/gc/space/rosalloc_space-inl.h
index 09aa7cf8a3..f37376377e 100644
--- a/runtime/gc/space/rosalloc_space-inl.h
+++ b/runtime/gc/space/rosalloc_space-inl.h
@@ -24,7 +24,7 @@
#include "gc/space/memory_tool_settings.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 86a5d3a794..2639755015 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -31,7 +31,7 @@
#include "thread.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h
index 7becea0828..712b344a4f 100644
--- a/runtime/gc/space/rosalloc_space.h
+++ b/runtime/gc/space/rosalloc_space.h
@@ -21,7 +21,7 @@
#include "malloc_space.h"
#include "space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace collector {
diff --git a/runtime/gc/space/rosalloc_space_random_test.cc b/runtime/gc/space/rosalloc_space_random_test.cc
index 3010b775f3..211c6be515 100644
--- a/runtime/gc/space/rosalloc_space_random_test.cc
+++ b/runtime/gc/space/rosalloc_space_random_test.cc
@@ -18,7 +18,7 @@
#include "rosalloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
namespace {
diff --git a/runtime/gc/space/rosalloc_space_static_test.cc b/runtime/gc/space/rosalloc_space_static_test.cc
index 860a4615e4..fcb03cec65 100644
--- a/runtime/gc/space/rosalloc_space_static_test.cc
+++ b/runtime/gc/space/rosalloc_space_static_test.cc
@@ -18,7 +18,7 @@
#include "rosalloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
namespace {
diff --git a/runtime/gc/space/space-inl.h b/runtime/gc/space/space-inl.h
index 3ea68cf9ca..d5fb081a78 100644
--- a/runtime/gc/space/space-inl.h
+++ b/runtime/gc/space/space-inl.h
@@ -24,7 +24,7 @@
#include "image_space.h"
#include "large_object_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/space.cc b/runtime/gc/space/space.cc
index cae9ce8f06..5fc09b83df 100644
--- a/runtime/gc/space/space.cc
+++ b/runtime/gc/space/space.cc
@@ -25,7 +25,7 @@
#include "runtime.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 160c73097c..abe26b4e26 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -28,7 +28,7 @@
#include "gc/collector/object_byte_pair.h"
#include "runtime_globals.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
} // namespace mirror
@@ -77,7 +77,7 @@ enum SpaceType {
std::ostream& operator<<(std::ostream& os, SpaceType space_type);
// A space contains memory allocated for managed objects.
-class Space {
+class EXPORT Space {
public:
// Dump space. Also key method for C++ vtables.
virtual void Dump(std::ostream& os) const;
diff --git a/runtime/gc/space/space_create_test.cc b/runtime/gc/space/space_create_test.cc
index 25bc12e85b..83568351b3 100644
--- a/runtime/gc/space/space_create_test.cc
+++ b/runtime/gc/space/space_create_test.cc
@@ -20,7 +20,7 @@
#include "rosalloc_space.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 4b01e83b38..2be1b9445a 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -31,7 +31,7 @@
#include "thread_list.h"
#include "zygote_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/zygote_space.cc b/runtime/gc/space/zygote_space.cc
index f40061ff88..cab183ef94 100644
--- a/runtime/gc/space/zygote_space.cc
+++ b/runtime/gc/space/zygote_space.cc
@@ -25,7 +25,7 @@
#include "runtime.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/space/zygote_space.h b/runtime/gc/space/zygote_space.h
index 3ebc943d96..12cc5c7e8b 100644
--- a/runtime/gc/space/zygote_space.h
+++ b/runtime/gc/space/zygote_space.h
@@ -21,7 +21,7 @@
#include "gc/accounting/space_bitmap.h"
#include "malloc_space.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
namespace space {
diff --git a/runtime/gc/system_weak.h b/runtime/gc/system_weak.h
index 57d593c756..721977d596 100644
--- a/runtime/gc/system_weak.h
+++ b/runtime/gc/system_weak.h
@@ -17,11 +17,12 @@
#ifndef ART_RUNTIME_GC_SYSTEM_WEAK_H_
#define ART_RUNTIME_GC_SYSTEM_WEAK_H_
+#include "base/macros.h"
#include "base/mutex.h"
#include "object_callbacks.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class AbstractSystemWeakHolder {
diff --git a/runtime/gc/system_weak_test.cc b/runtime/gc/system_weak_test.cc
index dd936538e5..b2a8c4d179 100644
--- a/runtime/gc/system_weak_test.cc
+++ b/runtime/gc/system_weak_test.cc
@@ -31,7 +31,7 @@
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class SystemWeakTest : public CommonRuntimeTest {
diff --git a/runtime/gc/task_processor.cc b/runtime/gc/task_processor.cc
index e56dbd17c3..50be93e844 100644
--- a/runtime/gc/task_processor.cc
+++ b/runtime/gc/task_processor.cc
@@ -19,7 +19,7 @@
#include "base/time_utils.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
TaskProcessor::TaskProcessor()
diff --git a/runtime/gc/task_processor.h b/runtime/gc/task_processor.h
index b9e6938b09..65d703d082 100644
--- a/runtime/gc/task_processor.h
+++ b/runtime/gc/task_processor.h
@@ -20,11 +20,12 @@
#include <memory>
#include <set>
+#include "base/macros.h"
#include "base/mutex.h"
#include "runtime_globals.h"
#include "thread_pool.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class HeapTask : public SelfDeletingTask {
diff --git a/runtime/gc/task_processor_test.cc b/runtime/gc/task_processor_test.cc
index 3614a51d90..5ee49415a5 100644
--- a/runtime/gc/task_processor_test.cc
+++ b/runtime/gc/task_processor_test.cc
@@ -20,7 +20,7 @@
#include "thread-current-inl.h"
#include "thread_pool.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
class TaskProcessorTest : public CommonRuntimeTest {
diff --git a/runtime/gc/verification-inl.h b/runtime/gc/verification-inl.h
index 1ef96e2954..6becd26f4e 100644
--- a/runtime/gc/verification-inl.h
+++ b/runtime/gc/verification-inl.h
@@ -21,7 +21,7 @@
#include "mirror/class-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
template <ReadBarrierOption kReadBarrierOption>
diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc
index 8ef61cbea0..926156fd8f 100644
--- a/runtime/gc/verification.cc
+++ b/runtime/gc/verification.cc
@@ -25,7 +25,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-refvisitor-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace gc {
std::string Verification::DumpRAMAroundAddress(uintptr_t addr, uintptr_t bytes) const {
diff --git a/runtime/gc/verification.h b/runtime/gc/verification.h
index 7a5d01a40a..0a9f78a26f 100644
--- a/runtime/gc/verification.h
+++ b/runtime/gc/verification.h
@@ -17,11 +17,12 @@
#ifndef ART_RUNTIME_GC_VERIFICATION_H_
#define ART_RUNTIME_GC_VERIFICATION_H_
+#include "base/macros.h"
#include "obj_ptr.h"
#include "offsets.h"
#include "read_barrier_option.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
@@ -45,10 +46,10 @@ class Verification {
REQUIRES_SHARED(Locks::mutator_lock_);
// Don't use ObjPtr for things that might not be aligned like the invalid reference.
- void LogHeapCorruption(ObjPtr<mirror::Object> holder,
- MemberOffset offset,
- mirror::Object* ref,
- bool fatal) const REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT void LogHeapCorruption(ObjPtr<mirror::Object> holder,
+ MemberOffset offset,
+ mirror::Object* ref,
+ bool fatal) const REQUIRES_SHARED(Locks::mutator_lock_);
// Return true if the klass is likely to be a valid mirror::Class.
// Returns true if the class is a valid mirror::Class or possibly spuriously.
@@ -68,7 +69,7 @@ class Verification {
// Find the first path to the target from the root set. Should be called while paused since
// visiting roots is not safe otherwise.
- std::string FirstPathFromRootSet(ObjPtr<mirror::Object> target) const
+ EXPORT std::string FirstPathFromRootSet(ObjPtr<mirror::Object> target) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Does not check alignment, used by DumpRAMAroundAddress.
diff --git a/runtime/gc/weak_root_state.h b/runtime/gc/weak_root_state.h
index 0784d3c738..316527fce5 100644
--- a/runtime/gc/weak_root_state.h
+++ b/runtime/gc/weak_root_state.h
@@ -19,7 +19,9 @@
#include <iosfwd>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace gc {
enum WeakRootState {
diff --git a/runtime/gc_root-inl.h b/runtime/gc_root-inl.h
index e561d29f99..736fdd3890 100644
--- a/runtime/gc_root-inl.h
+++ b/runtime/gc_root-inl.h
@@ -24,7 +24,7 @@
#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
-namespace art {
+namespace art HIDDEN {
template<class MirrorType>
template<ReadBarrierOption kReadBarrierOption>
diff --git a/runtime/gc_root.h b/runtime/gc_root.h
index 19e2786ae2..da9d3af6cb 100644
--- a/runtime/gc_root.h
+++ b/runtime/gc_root.h
@@ -22,7 +22,7 @@
#include "mirror/object_reference.h"
#include "read_barrier_option.h"
-namespace art {
+namespace art HIDDEN {
class ArtField;
class ArtMethod;
template<class MirrorType> class ObjPtr;
@@ -54,7 +54,7 @@ enum RootType {
kRootVMInternal,
kRootJNIMonitor,
};
-std::ostream& operator<<(std::ostream& os, RootType root_type);
+EXPORT std::ostream& operator<<(std::ostream& os, RootType root_type);
// Only used by hprof. thread_id_ and type_ are only used by hprof.
class RootInfo {
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index dcbf9ebf52..fa0a02f997 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -35,7 +35,7 @@
#include "thread-inl.h"
#include "unstarted_runtime.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
ALWAYS_INLINE static ObjPtr<mirror::Object> ObjArg(uint32_t arg)
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index f7bc1a3d55..c7508f66f9 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -18,10 +18,11 @@
#define ART_RUNTIME_INTERPRETER_INTERPRETER_H_
#include "base/locks.h"
+#include "base/macros.h"
#include "dex/dex_file.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
} // namespace mirror
diff --git a/runtime/interpreter/interpreter_cache-inl.h b/runtime/interpreter/interpreter_cache-inl.h
index 804d382877..a325ea464a 100644
--- a/runtime/interpreter/interpreter_cache-inl.h
+++ b/runtime/interpreter/interpreter_cache-inl.h
@@ -21,7 +21,7 @@
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
inline bool InterpreterCache::Get(Thread* self, const void* key, /* out */ size_t* value) {
DCHECK(self->GetInterpreterCache() == this) << "Must be called from owning thread";
diff --git a/runtime/interpreter/interpreter_cache.cc b/runtime/interpreter/interpreter_cache.cc
index 7e7b294c17..a272d14bba 100644
--- a/runtime/interpreter/interpreter_cache.cc
+++ b/runtime/interpreter/interpreter_cache.cc
@@ -17,7 +17,7 @@
#include "interpreter_cache.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
void InterpreterCache::Clear(Thread* owning_thread) {
DCHECK(owning_thread->GetInterpreterCache() == this);
diff --git a/runtime/interpreter/interpreter_cache.h b/runtime/interpreter/interpreter_cache.h
index 8714bc613c..410fdf58ab 100644
--- a/runtime/interpreter/interpreter_cache.h
+++ b/runtime/interpreter/interpreter_cache.h
@@ -23,7 +23,7 @@
#include "base/bit_utils.h"
#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
class Thread;
@@ -60,7 +60,7 @@ class ALIGNED(16) InterpreterCache {
}
// Clear the whole cache. It requires the owning thread for DCHECKs.
- void Clear(Thread* owning_thread);
+ EXPORT void Clear(Thread* owning_thread);
ALWAYS_INLINE bool Get(Thread* self, const void* key, /* out */ size_t* value);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 814f28da75..85ed318390 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -50,7 +50,7 @@
#include "var_handles.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
void ThrowNullPointerExceptionFromInterpreter() {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 94cf8f8795..0745a000e7 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -64,7 +64,7 @@
#include "unstarted_runtime.h"
#include "verifier/method_verifier.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
void ThrowNullPointerExceptionFromInterpreter()
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index ddde26d0cf..db20f3951b 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -40,7 +40,7 @@
#include "thread.h"
#include "verifier/method_verifier.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
diff --git a/runtime/interpreter/interpreter_switch_impl.h b/runtime/interpreter/interpreter_switch_impl.h
index 3a42c217a9..c390692f10 100644
--- a/runtime/interpreter/interpreter_switch_impl.h
+++ b/runtime/interpreter/interpreter_switch_impl.h
@@ -24,7 +24,7 @@
#include "jvalue.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
class ShadowFrame;
class Thread;
diff --git a/runtime/interpreter/interpreter_switch_impl0.cc b/runtime/interpreter/interpreter_switch_impl0.cc
index b4e5f5061d..65ae2fe333 100644
--- a/runtime/interpreter/interpreter_switch_impl0.cc
+++ b/runtime/interpreter/interpreter_switch_impl0.cc
@@ -19,7 +19,7 @@
#include "interpreter_switch_impl-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
// Explicit definition of ExecuteSwitchImplCpp.
diff --git a/runtime/interpreter/interpreter_switch_impl1.cc b/runtime/interpreter/interpreter_switch_impl1.cc
index f8f9fcc81a..b9033d926e 100644
--- a/runtime/interpreter/interpreter_switch_impl1.cc
+++ b/runtime/interpreter/interpreter_switch_impl1.cc
@@ -19,7 +19,7 @@
#include "interpreter_switch_impl-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
// Explicit definition of ExecuteSwitchImplCpp.
diff --git a/runtime/interpreter/lock_count_data.cc b/runtime/interpreter/lock_count_data.cc
index 64b59cd390..ad53d703b3 100644
--- a/runtime/interpreter/lock_count_data.cc
+++ b/runtime/interpreter/lock_count_data.cc
@@ -23,7 +23,7 @@
#include "mirror/object-inl.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
void LockCountData::AddMonitor(Thread* self, mirror::Object* obj) {
if (obj == nullptr) {
diff --git a/runtime/interpreter/lock_count_data.h b/runtime/interpreter/lock_count_data.h
index efa14c5bbc..ec108fc5c1 100644
--- a/runtime/interpreter/lock_count_data.h
+++ b/runtime/interpreter/lock_count_data.h
@@ -21,8 +21,9 @@
#include <vector>
#include "base/locks.h"
+#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index 668289a37d..bcc59a4032 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -31,7 +31,7 @@
#include "mirror/string-alloc-inl.h"
#include "nterp_helpers.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
bool IsNterpSupported() {
diff --git a/runtime/interpreter/mterp/nterp.h b/runtime/interpreter/mterp/nterp.h
index a7745db716..446fb858ce 100644
--- a/runtime/interpreter/mterp/nterp.h
+++ b/runtime/interpreter/mterp/nterp.h
@@ -19,11 +19,12 @@
#include "base/array_ref.h"
#include "base/globals.h"
+#include "base/macros.h"
extern "C" void* artNterpAsmInstructionStart[];
extern "C" void* artNterpAsmInstructionEnd[];
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
diff --git a/runtime/interpreter/safe_math.h b/runtime/interpreter/safe_math.h
index 25a9353bc0..9b6265f420 100644
--- a/runtime/interpreter/safe_math.h
+++ b/runtime/interpreter/safe_math.h
@@ -20,7 +20,9 @@
#include <functional>
#include <type_traits>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace interpreter {
// Declares a type which is the larger in bit size of the two template parameters.
diff --git a/runtime/interpreter/safe_math_test.cc b/runtime/interpreter/safe_math_test.cc
index 28087a395b..c88ac4e061 100644
--- a/runtime/interpreter/safe_math_test.cc
+++ b/runtime/interpreter/safe_math_test.cc
@@ -20,7 +20,7 @@
#include "gtest/gtest.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
TEST(SafeMath, Add) {
diff --git a/runtime/interpreter/shadow_frame-inl.h b/runtime/interpreter/shadow_frame-inl.h
index 799b2d205d..a05d60f59b 100644
--- a/runtime/interpreter/shadow_frame-inl.h
+++ b/runtime/interpreter/shadow_frame-inl.h
@@ -21,7 +21,7 @@
#include "obj_ptr-inl.h"
-namespace art {
+namespace art HIDDEN {
template<VerifyObjectFlags kVerifyFlags /*= kDefaultVerifyFlags*/>
inline void ShadowFrame::SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
diff --git a/runtime/interpreter/shadow_frame.cc b/runtime/interpreter/shadow_frame.cc
index 264ec6a997..5ed4224900 100644
--- a/runtime/interpreter/shadow_frame.cc
+++ b/runtime/interpreter/shadow_frame.cc
@@ -18,7 +18,7 @@
#include "art_method-inl.h"
-namespace art {
+namespace art HIDDEN {
mirror::Object* ShadowFrame::GetThisObject() const {
ArtMethod* m = GetMethod();
diff --git a/runtime/interpreter/shadow_frame.h b/runtime/interpreter/shadow_frame.h
index 7ca2423856..54c40b2e3c 100644
--- a/runtime/interpreter/shadow_frame.h
+++ b/runtime/interpreter/shadow_frame.h
@@ -28,7 +28,7 @@
#include "stack_reference.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 6cf6746f01..3b5bee80d7 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -66,7 +66,7 @@
#include "unstarted_runtime_list.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
using android::base::StringAppendV;
diff --git a/runtime/interpreter/unstarted_runtime.h b/runtime/interpreter/unstarted_runtime.h
index 8b31f8f441..60092ad958 100644
--- a/runtime/interpreter/unstarted_runtime.h
+++ b/runtime/interpreter/unstarted_runtime.h
@@ -19,11 +19,12 @@
#include "interpreter.h"
+#include "base/macros.h"
#include "dex/dex_file.h"
#include "jvalue.h"
#include "unstarted_runtime_list.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
class CodeItemDataAccessor;
@@ -47,7 +48,7 @@ namespace interpreter {
class UnstartedRuntime {
public:
- static void Initialize();
+ EXPORT static void Initialize();
// For testing. When we destroy the Runtime and create a new one,
// we need to reinitialize maps with new `ArtMethod*` keys.
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index daa1a825de..d21c5ea145 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -45,7 +45,7 @@
#include "transaction.h"
#include "unstarted_runtime_list.h"
-namespace art {
+namespace art HIDDEN {
namespace interpreter {
// Deleter to be used with ShadowFrame::CreateDeoptimizedFrame objects.
diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc
index 112746e2fe..8c9fb4c999 100644
--- a/runtime/jit/debugger_interface.cc
+++ b/runtime/jit/debugger_interface.cc
@@ -93,7 +93,7 @@
// attempting to run TSAN on this code.
//
-namespace art {
+namespace art HIDDEN {
static Mutex g_jit_debug_lock("JIT native debug entries", kNativeDebugInterfaceLock);
static Mutex g_dex_debug_lock("DEX native debug entries", kNativeDebugInterfaceLock);
@@ -108,8 +108,11 @@ constexpr uint32_t kJitRepackGroupSize = 64 * KB;
// Automatically call the repack method every 'n' new entries.
constexpr uint32_t kJitRepackFrequency = 64;
+} // namespace art
+
// Public binary interface between ART and native tools (gdb, libunwind, etc).
// The fields below need to be exported and have special names as per the gdb api.
+namespace art EXPORT {
extern "C" {
enum JITAction {
JIT_NOACTION = 0,
@@ -198,6 +201,9 @@ extern "C" {
void (*__dex_debug_register_code_ptr)() = __dex_debug_register_code;
JITDescriptor __dex_debug_descriptor GUARDED_BY(g_dex_debug_lock) {};
}
+} // namespace art
+
+namespace art HIDDEN {
// The fields below are internal, but we keep them here anyway for consistency.
// Their state is related to the static state above and it must be kept in sync.
diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h
index 62288de8cf..da7e90749e 100644
--- a/runtime/jit/debugger_interface.h
+++ b/runtime/jit/debugger_interface.h
@@ -25,7 +25,7 @@
#include "base/array_ref.h"
#include "base/locks.h"
-namespace art {
+namespace art HIDDEN {
class DexFile;
class Mutex;
@@ -70,7 +70,7 @@ size_t GetJitMiniDebugInfoMemUsage() REQUIRES_SHARED(Locks::jit_lock_);
// Get the lock which protects the native debug info.
// Used only in tests to unwind while the JIT thread is running.
// TODO: Unwinding should be race-free. Remove this.
-Mutex* GetNativeDebugInfoLock();
+EXPORT Mutex* GetNativeDebugInfoLock();
// Call given callback for every non-zygote symbol.
// The callback parameters are (address, size, name).
diff --git a/runtime/jit/jit-inl.h b/runtime/jit/jit-inl.h
index 237f63ce97..52099c2e1d 100644
--- a/runtime/jit/jit-inl.h
+++ b/runtime/jit/jit-inl.h
@@ -24,7 +24,7 @@
#include "thread.h"
#include "runtime-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace jit {
inline void Jit::AddSamples(Thread* self, ArtMethod* method) {
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 0ee138fa06..4d4a1ed79c 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -58,7 +58,7 @@
using android::base::unique_fd;
-namespace art {
+namespace art HIDDEN {
namespace jit {
static constexpr bool kEnableOnStackReplacement = true;
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 1c579167ad..ddf408fb33 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -35,7 +35,7 @@
#include "obj_ptr.h"
#include "thread_pool.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
class ClassLinker;
@@ -200,7 +200,6 @@ class JitCompilerInterface {
virtual void ParseCompilerOptions() = 0;
virtual bool IsBaselineCompiler() const = 0;
virtual void SetDebuggableCompilerOption(bool value) = 0;
- virtual uint32_t GetInlineMaxCodeUnits() const = 0;
virtual std::vector<uint8_t> PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files,
ArrayRef<const void*> removed_symbols,
@@ -309,8 +308,10 @@ class Jit {
// Create JIT itself.
static std::unique_ptr<Jit> Create(JitCodeCache* code_cache, JitOptions* options);
- bool CompileMethod(ArtMethod* method, Thread* self, CompilationKind compilation_kind, bool prejit)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT bool CompileMethod(ArtMethod* method,
+ Thread* self,
+ CompilationKind compilation_kind,
+ bool prejit) REQUIRES_SHARED(Locks::mutator_lock_);
void VisitRoots(RootVisitor* visitor);
@@ -371,7 +372,7 @@ class Jit {
}
// Wait until there is no more pending compilation tasks.
- void WaitForCompilationToFinish(Thread* self);
+ EXPORT void WaitForCompilationToFinish(Thread* self);
// Profiling methods.
void MethodEntered(Thread* thread, ArtMethod* method)
@@ -412,7 +413,7 @@ class Jit {
void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
// Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
- bool JitAtFirstUse();
+ EXPORT bool JitAtFirstUse();
// Return whether we can invoke JIT code for `method`.
bool CanInvokeCompiledCode(ArtMethod* method);
@@ -438,16 +439,16 @@ class Jit {
}
// Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
- void Stop();
+ EXPORT void Stop();
// Start JIT threads.
- void Start();
+ EXPORT void Start();
// Transition to a child state.
- void PostForkChildAction(bool is_system_server, bool is_zygote);
+ EXPORT void PostForkChildAction(bool is_system_server, bool is_zygote);
// Prepare for forking.
- void PreZygoteFork();
+ EXPORT void PreZygoteFork();
// Adjust state after forking.
void PostZygoteFork();
@@ -540,7 +541,7 @@ class Jit {
REQUIRES_SHARED(Locks::mutator_lock_);
// JIT compiler
- static JitCompilerInterface* jit_compiler_;
+ EXPORT static JitCompilerInterface* jit_compiler_;
// JIT resources owned by runtime.
jit::JitCodeCache* const code_cache_;
@@ -588,7 +589,7 @@ class Jit {
};
// Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
-class ScopedJitSuspend {
+class EXPORT ScopedJitSuspend {
public:
ScopedJitSuspend();
~ScopedJitSuspend();
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index e8d8b3b663..f44b822bb1 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -60,7 +60,7 @@
#include "thread-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
namespace jit {
static constexpr size_t kCodeSizeLogThreshold = 50 * KB;
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index e61ae7963d..96fc7e2706 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -37,7 +37,7 @@
#include "jit_memory_region.h"
#include "profiling_info.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
template<class T> class Handle;
@@ -211,7 +211,7 @@ class JitCodeCache {
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::jit_lock_);
- void NotifyMethodRedefined(ArtMethod* method)
+ EXPORT void NotifyMethodRedefined(ArtMethod* method)
REQUIRES(Locks::mutator_lock_)
REQUIRES(!Locks::jit_lock_);
@@ -232,13 +232,13 @@ class JitCodeCache {
REQUIRES(!Locks::jit_lock_);
// Return true if the code cache contains this pc.
- bool ContainsPc(const void* pc) const;
+ EXPORT bool ContainsPc(const void* pc) const;
// Return true if the code cache contains this pc in the private region (i.e. not from zygote).
bool PrivateRegionContainsPc(const void* pc) const;
// Return true if the code cache contains this method.
- bool ContainsMethod(ArtMethod* method)
+ EXPORT bool ContainsMethod(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::jit_lock_);
// Return the code pointer for a JNI-compiled stub if the method is in the cache, null otherwise.
@@ -289,7 +289,7 @@ class JitCodeCache {
REQUIRES(Locks::jit_lock_);
// Perform a collection on the code cache.
- void GarbageCollectCache(Thread* self)
+ EXPORT void GarbageCollectCache(Thread* self)
REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -300,14 +300,14 @@ class JitCodeCache {
REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- OatQuickMethodHeader* LookupOsrMethodHeader(ArtMethod* method)
+ EXPORT OatQuickMethodHeader* LookupOsrMethodHeader(ArtMethod* method)
REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
// Removes method from the cache for testing purposes. The caller
// must ensure that all threads are suspended and the method should
// not be in any thread's stack.
- bool RemoveMethod(ArtMethod* method, bool release_memory)
+ EXPORT bool RemoveMethod(ArtMethod* method, bool release_memory)
REQUIRES(!Locks::jit_lock_)
REQUIRES(Locks::mutator_lock_);
@@ -338,12 +338,12 @@ class JitCodeCache {
// Adds to `methods` all profiled methods which are part of any of the given dex locations.
// Saves inline caches for a method if its hotness meets `inline_cache_threshold` after being
// baseline compiled.
- void GetProfiledMethods(const std::set<std::string>& dex_base_locations,
- std::vector<ProfileMethodInfo>& methods,
- uint16_t inline_cache_threshold) REQUIRES(!Locks::jit_lock_)
+ EXPORT void GetProfiledMethods(const std::set<std::string>& dex_base_locations,
+ std::vector<ProfileMethodInfo>& methods,
+ uint16_t inline_cache_threshold) REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- void InvalidateAllCompiledCode()
+ EXPORT void InvalidateAllCompiledCode()
REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -370,11 +370,11 @@ class JitCodeCache {
// Notify the code cache that the method at the pointer 'old_method' is being moved to the pointer
// 'new_method' since it is being made obsolete.
- void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method)
+ EXPORT void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method)
REQUIRES(!Locks::jit_lock_) REQUIRES(Locks::mutator_lock_);
// Dynamically change whether we want to garbage collect code.
- void SetGarbageCollectCode(bool value) REQUIRES(!Locks::jit_lock_);
+ EXPORT void SetGarbageCollectCode(bool value) REQUIRES(!Locks::jit_lock_);
bool GetGarbageCollectCode() REQUIRES(!Locks::jit_lock_);
@@ -392,13 +392,13 @@ class JitCodeCache {
REQUIRES(!Locks::jit_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- void PostForkChildAction(bool is_system_server, bool is_zygote);
+ EXPORT void PostForkChildAction(bool is_system_server, bool is_zygote);
// Clear the entrypoints of JIT compiled methods that belong in the zygote space.
// This is used for removing non-debuggable JIT code at the point we realize the runtime
// is debuggable. Also clear the Precompiled flag from all methods so the non-debuggable code
// doesn't come back.
- void TransitionToDebuggable() REQUIRES(!Locks::jit_lock_) REQUIRES(Locks::mutator_lock_);
+ EXPORT void TransitionToDebuggable() REQUIRES(!Locks::jit_lock_) REQUIRES(Locks::mutator_lock_);
JitMemoryRegion* GetCurrentRegion();
bool IsSharedRegion(const JitMemoryRegion& region) const { return &region == &shared_region_; }
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 911b7d7aca..3a4ef973eb 100644
--- a/runtime/jit/jit_memory_region.cc
+++ b/runtime/jit/jit_memory_region.cc
@@ -34,7 +34,7 @@
using android::base::unique_fd;
-namespace art {
+namespace art HIDDEN {
namespace jit {
// Data cache will be half of the capacity
diff --git a/runtime/jit/jit_memory_region.h b/runtime/jit/jit_memory_region.h
index 8a3d6c3e55..7391541f07 100644
--- a/runtime/jit/jit_memory_region.h
+++ b/runtime/jit/jit_memory_region.h
@@ -26,7 +26,7 @@
#include "gc_root-inl.h"
#include "handle.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
diff --git a/runtime/jit/jit_memory_region_test.cc b/runtime/jit/jit_memory_region_test.cc
index bf943f9981..449255a7f7 100644
--- a/runtime/jit/jit_memory_region_test.cc
+++ b/runtime/jit/jit_memory_region_test.cc
@@ -29,7 +29,7 @@
#include "base/utils.h"
#include "common_runtime_test.h"
-namespace art {
+namespace art HIDDEN {
namespace jit {
// These tests only run on bionic.
diff --git a/runtime/jit/jit_scoped_code_cache_write.h b/runtime/jit/jit_scoped_code_cache_write.h
index e2adebfb1b..ed21cf9fbd 100644
--- a/runtime/jit/jit_scoped_code_cache_write.h
+++ b/runtime/jit/jit_scoped_code_cache_write.h
@@ -22,7 +22,7 @@
#include "base/systrace.h"
#include "base/utils.h" // For CheckedCall
-namespace art {
+namespace art HIDDEN {
namespace jit {
class JitMemoryRegion;
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index af5f561d8c..91b011bce8 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -43,7 +43,7 @@
#include "profile/profile_compilation_info.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
using Hotness = ProfileCompilationInfo::MethodHotness;
diff --git a/runtime/jit/profile_saver.h b/runtime/jit/profile_saver.h
index b5fb1e6c26..1042db9a89 100644
--- a/runtime/jit/profile_saver.h
+++ b/runtime/jit/profile_saver.h
@@ -24,7 +24,7 @@
#include "profile/profile_compilation_info.h"
#include "profile_saver_options.h"
-namespace art {
+namespace art HIDDEN {
class ProfileSaver {
public:
@@ -53,7 +53,7 @@ class ProfileSaver {
static void NotifyJitActivity() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
// For testing or manual purposes (SIGUSR1).
- static void ForceProcessProfiles() REQUIRES(!Locks::profiler_lock_, !Locks::mutator_lock_);
+ EXPORT static void ForceProcessProfiles() REQUIRES(!Locks::profiler_lock_, !Locks::mutator_lock_);
// Notify that startup has completed.
static void NotifyStartupCompleted() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
diff --git a/runtime/jit/profile_saver_options.h b/runtime/jit/profile_saver_options.h
index f53b5fcfcc..f6d928ff6b 100644
--- a/runtime/jit/profile_saver_options.h
+++ b/runtime/jit/profile_saver_options.h
@@ -17,7 +17,7 @@
#include <ostream>
#include <string>
-namespace art {
+namespace art HIDDEN {
struct ProfileSaverOptions {
public:
diff --git a/runtime/jit/profile_saver_test.cc b/runtime/jit/profile_saver_test.cc
index e737b7c8ee..e522677eca 100644
--- a/runtime/jit/profile_saver_test.cc
+++ b/runtime/jit/profile_saver_test.cc
@@ -22,7 +22,7 @@
#include "profile_saver.h"
#include "profile/profile_compilation_info.h"
-namespace art {
+namespace art HIDDEN {
using Hotness = ProfileCompilationInfo::MethodHotness;
diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc
index 1aaf53e0a1..395e175d7c 100644
--- a/runtime/jit/profiling_info.cc
+++ b/runtime/jit/profiling_info.cc
@@ -23,7 +23,7 @@
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
ProfilingInfo::ProfilingInfo(ArtMethod* method,
const std::vector<uint32_t>& inline_cache_entries,
@@ -114,9 +114,6 @@ BranchCache* ProfilingInfo::GetBranchCache(uint32_t dex_pc) {
void ProfilingInfo::AddInvokeInfo(uint32_t dex_pc, mirror::Class* cls) {
InlineCache* cache = GetInlineCache(dex_pc);
- if (cache == nullptr) {
- return;
- }
for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
mirror::Class* existing = cache->classes_[i].Read<kWithoutReadBarrier>();
mirror::Class* marked = ReadBarrier::IsMarked(existing);
@@ -162,39 +159,4 @@ ScopedProfilingInfoUse::~ScopedProfilingInfoUse() {
}
}
-uint32_t InlineCache::EncodeDexPc(ArtMethod* method,
- const std::vector<uint32_t>& dex_pcs,
- uint32_t inline_max_code_units) {
- if (kIsDebugBuild) {
- // Make sure `inline_max_code_units` is always the same.
- static uint32_t global_max_code_units = inline_max_code_units;
- CHECK_EQ(global_max_code_units, inline_max_code_units);
- }
- if (dex_pcs.size() - 1 > MaxDexPcEncodingDepth(method, inline_max_code_units)) {
- return -1;
- }
- uint32_t size = dex_pcs.size();
- uint32_t insns_size = method->DexInstructions().InsnsSizeInCodeUnits();
-
- uint32_t dex_pc = dex_pcs[size - 1];
- uint32_t shift = MinimumBitsToStore(insns_size - 1);
- for (uint32_t i = size - 1; i > 0; --i) {
- DCHECK_LT(shift, BitSizeOf<uint32_t>());
- dex_pc += ((dex_pcs[i - 1] + 1) << shift);
- shift += MinimumBitsToStore(inline_max_code_units);
- }
- return dex_pc;
-}
-
-uint32_t InlineCache::MaxDexPcEncodingDepth(ArtMethod* method, uint32_t inline_max_code_units) {
- uint32_t insns_size = method->DexInstructions().InsnsSizeInCodeUnits();
- uint32_t num_bits = MinimumBitsToStore(insns_size - 1);
- uint32_t depth = 0;
- do {
- depth++;
- num_bits += MinimumBitsToStore(inline_max_code_units);
- } while (num_bits <= BitSizeOf<uint32_t>());
- return depth - 1;
-}
-
} // namespace art
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index 4ce20ff66a..05420fd904 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -25,10 +25,9 @@
#include "interpreter/mterp/nterp.h"
#include "offsets.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
-class CompilerOptions;
class ProfilingInfo;
namespace jit {
@@ -51,18 +50,6 @@ class InlineCache {
return MemberOffset(OFFSETOF_MEMBER(InlineCache, classes_));
}
- // Encode the list of `dex_pcs` to fit into an uint32_t.
- static uint32_t EncodeDexPc(ArtMethod* method,
- const std::vector<uint32_t>& dex_pcs,
- uint32_t inline_max_code_units)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Return the maximum inlining depth that we support to encode a list of dex
- // pcs.
- static uint32_t MaxDexPcEncodingDepth(ArtMethod* method,
- uint32_t inline_max_code_units)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
uint32_t dex_pc_;
GcRoot<mirror::Class> classes_[kIndividualCacheSize];
@@ -112,9 +99,9 @@ class BranchCache {
class ProfilingInfo {
public:
// Create a ProfilingInfo for 'method'.
- static ProfilingInfo* Create(Thread* self,
- ArtMethod* method,
- const std::vector<uint32_t>& inline_cache_entries)
+ EXPORT static ProfilingInfo* Create(Thread* self,
+ ArtMethod* method,
+ const std::vector<uint32_t>& inline_cache_entries)
REQUIRES_SHARED(Locks::mutator_lock_);
// Add information from an executed INVOKE instruction to the profile.
diff --git a/runtime/jit/profiling_info_test.cc b/runtime/jit/profiling_info_test.cc
index 021bebfe4e..a8a95774d8 100644
--- a/runtime/jit/profiling_info_test.cc
+++ b/runtime/jit/profiling_info_test.cc
@@ -33,7 +33,7 @@
#include "profile/profile_test_helper.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
using Hotness = ProfileCompilationInfo::MethodHotness;
diff --git a/runtime/jni/check_jni.cc b/runtime/jni/check_jni.cc
index 3dc9b9f475..db4205cdf8 100644
--- a/runtime/jni/check_jni.cc
+++ b/runtime/jni/check_jni.cc
@@ -51,7 +51,7 @@
#include "thread.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
// This helper cannot be in the anonymous namespace because it needs to be
// declared as a friend by JniVmExt and JniEnvExt.
diff --git a/runtime/jni/check_jni.h b/runtime/jni/check_jni.h
index 10fdfe859d..854aa20617 100644
--- a/runtime/jni/check_jni.h
+++ b/runtime/jni/check_jni.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
const JNINativeInterface* GetCheckJniNativeInterface();
const JNIInvokeInterface* GetCheckJniInvokeInterface();
diff --git a/runtime/jni/java_vm_ext-inl.h b/runtime/jni/java_vm_ext-inl.h
index c98a5532f6..75cfabb588 100644
--- a/runtime/jni/java_vm_ext-inl.h
+++ b/runtime/jni/java_vm_ext-inl.h
@@ -22,7 +22,7 @@
#include "read_barrier_config.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
inline bool JavaVMExt::MayAccessWeakGlobals(Thread* self) const {
DCHECK(self != nullptr);
diff --git a/runtime/jni/java_vm_ext.cc b/runtime/jni/java_vm_ext.cc
index 18abd8b3ee..2a364f37b1 100644
--- a/runtime/jni/java_vm_ext.cc
+++ b/runtime/jni/java_vm_ext.cc
@@ -54,7 +54,7 @@
#include "ti/agent.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringAppendF;
using android::base::StringAppendV;
@@ -1210,7 +1210,7 @@ jstring JavaVMExt::GetLibrarySearchPath(JNIEnv* env, jobject class_loader) {
// JNI Invocation interface.
-extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
+extern "C" EXPORT jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
ScopedTrace trace(__FUNCTION__);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
if (JavaVMExt::IsBadJniVersion(args->version)) {
@@ -1252,7 +1252,7 @@ extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
return JNI_OK;
}
-extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms_buf, jsize buf_len, jsize* vm_count) {
+extern "C" EXPORT jint JNI_GetCreatedJavaVMs(JavaVM** vms_buf, jsize buf_len, jsize* vm_count) {
Runtime* runtime = Runtime::Current();
if (runtime == nullptr || buf_len == 0) {
*vm_count = 0;
@@ -1264,7 +1264,7 @@ extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms_buf, jsize buf_len, jsize* vm
}
// Historically unsupported.
-extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
+extern "C" EXPORT jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
return JNI_ERR;
}
diff --git a/runtime/jni/java_vm_ext.h b/runtime/jni/java_vm_ext.h
index 7f4f5485b6..c04bee7db1 100644
--- a/runtime/jni/java_vm_ext.h
+++ b/runtime/jni/java_vm_ext.h
@@ -25,7 +25,7 @@
#include "obj_ptr.h"
#include "reference_table.h"
-namespace art {
+namespace art HIDDEN {
namespace linker {
class ImageWriter;
@@ -103,11 +103,11 @@ class JavaVMExt : public JavaVM {
* Returns 'true' on success. On failure, sets 'error_msg' to a
* human-readable description of the error.
*/
- bool LoadNativeLibrary(JNIEnv* env,
- const std::string& path,
- jobject class_loader,
- jclass caller_class,
- std::string* error_msg);
+ EXPORT bool LoadNativeLibrary(JNIEnv* env,
+ const std::string& path,
+ jobject class_loader,
+ jclass caller_class,
+ std::string* error_msg);
// Unload native libraries with cleared class loaders.
void UnloadNativeLibraries()
@@ -139,7 +139,7 @@ class JavaVMExt : public JavaVM {
bool SetCheckJniEnabled(bool enabled);
- void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_)
+ EXPORT void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::jni_globals_lock_);
void DisallowNewWeakGlobals()
@@ -151,17 +151,15 @@ class JavaVMExt : public JavaVM {
void BroadcastForNewWeakGlobals()
REQUIRES(!Locks::jni_weak_globals_lock_);
- jobject AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Locks::jni_globals_lock_);
+ EXPORT jobject AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::jni_globals_lock_);
- jweak AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Locks::jni_weak_globals_lock_);
+ EXPORT jweak AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::jni_weak_globals_lock_);
- void DeleteGlobalRef(Thread* self, jobject obj) REQUIRES(!Locks::jni_globals_lock_);
+ EXPORT void DeleteGlobalRef(Thread* self, jobject obj) REQUIRES(!Locks::jni_globals_lock_);
- void DeleteWeakGlobalRef(Thread* self, jweak obj) REQUIRES(!Locks::jni_weak_globals_lock_);
+ EXPORT void DeleteWeakGlobalRef(Thread* self, jweak obj) REQUIRES(!Locks::jni_weak_globals_lock_);
void SweepJniWeakGlobals(IsMarkedVisitor* visitor)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -214,8 +212,7 @@ class JavaVMExt : public JavaVM {
jint HandleGetEnv(/*out*/void** env, jint version)
REQUIRES(!env_hooks_lock_);
- void AddEnvironmentHook(GetEnvHook hook)
- REQUIRES(!env_hooks_lock_);
+ EXPORT void AddEnvironmentHook(GetEnvHook hook) REQUIRES(!env_hooks_lock_);
static bool IsBadJniVersion(int version);
diff --git a/runtime/jni/java_vm_ext_test.cc b/runtime/jni/java_vm_ext_test.cc
index e7295aaa62..f9176fc5c4 100644
--- a/runtime/jni/java_vm_ext_test.cc
+++ b/runtime/jni/java_vm_ext_test.cc
@@ -23,7 +23,7 @@
#include "java_vm_ext.h"
#include "runtime.h"
-namespace art {
+namespace art HIDDEN {
class JavaVmExtTest : public CommonRuntimeTest {
protected:
diff --git a/runtime/jni/jni_env_ext-inl.h b/runtime/jni/jni_env_ext-inl.h
index 0c04192958..9adb173e60 100644
--- a/runtime/jni/jni_env_ext-inl.h
+++ b/runtime/jni/jni_env_ext-inl.h
@@ -22,17 +22,12 @@
#include "local_reference_table-inl.h"
#include "mirror/object.h"
-namespace art {
+namespace art HIDDEN {
template<typename T>
inline T JNIEnvExt::AddLocalReference(ObjPtr<mirror::Object> obj) {
- std::string error_msg;
- IndirectRef ref = locals_.Add(local_ref_cookie_, obj, &error_msg);
- if (UNLIKELY(ref == nullptr)) {
- // This is really unexpected if we allow resizing local IRTs...
- LOG(FATAL) << error_msg;
- UNREACHABLE();
- }
+ DCHECK(obj != nullptr);
+ jobject ref = NewLocalRef(obj.Ptr());
// TODO: fix this to understand PushLocalFrame, so we can turn it on.
if (false) {
diff --git a/runtime/jni/jni_env_ext.cc b/runtime/jni/jni_env_ext.cc
index fcf38bafb0..a68df6f658 100644
--- a/runtime/jni/jni_env_ext.cc
+++ b/runtime/jni/jni_env_ext.cc
@@ -36,7 +36,7 @@
#include "thread-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/jni/jni_env_ext.h b/runtime/jni/jni_env_ext.h
index 1f57658c87..177c70d171 100644
--- a/runtime/jni/jni_env_ext.h
+++ b/runtime/jni/jni_env_ext.h
@@ -25,7 +25,7 @@
#include "obj_ptr.h"
#include "reference_table.h"
-namespace art {
+namespace art HIDDEN {
class ArtMethod;
class ArtField;
@@ -66,8 +66,8 @@ class JNIEnvExt : public JNIEnv {
void UpdateLocal(IndirectRef iref, ObjPtr<mirror::Object> obj)
REQUIRES_SHARED(Locks::mutator_lock_);
- jobject NewLocalRef(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
- void DeleteLocalRef(jobject obj) REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT jobject NewLocalRef(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT void DeleteLocalRef(jobject obj) REQUIRES_SHARED(Locks::mutator_lock_);
void TrimLocals() REQUIRES_SHARED(Locks::mutator_lock_) {
locals_.Trim();
@@ -138,12 +138,12 @@ class JNIEnvExt : public JNIEnv {
// to all threads.
// Note: JNI function table overrides are sensitive to the order of operations wrt/ CheckJNI.
// After overriding the JNI function table, CheckJNI toggling is ignored.
- static void SetTableOverride(const JNINativeInterface* table_override)
+ EXPORT static void SetTableOverride(const JNINativeInterface* table_override)
REQUIRES(!Locks::thread_list_lock_, !Locks::jni_function_table_lock_);
// Return either the regular, or the CheckJNI function table. Will return table_override_ instead
// if it is not null.
- static const JNINativeInterface* GetFunctionTable(bool check_jni)
+ EXPORT static const JNINativeInterface* GetFunctionTable(bool check_jni)
REQUIRES(Locks::jni_function_table_lock_);
static void ResetFunctionTable()
diff --git a/runtime/jni/jni_id_manager.cc b/runtime/jni/jni_id_manager.cc
index 5af1a78013..c7c2733951 100644
--- a/runtime/jni/jni_id_manager.cc
+++ b/runtime/jni/jni_id_manager.cc
@@ -46,7 +46,7 @@
#include "thread-inl.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
namespace jni {
constexpr bool kTraceIds = false;
diff --git a/runtime/jni/jni_id_manager.h b/runtime/jni/jni_id_manager.h
index c8ebfc331a..c7ebeb8abb 100644
--- a/runtime/jni/jni_id_manager.h
+++ b/runtime/jni/jni_id_manager.h
@@ -29,7 +29,7 @@
#include "jni_id_type.h"
#include "reflective_value_visitor.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Object;
class ClassExt;
@@ -50,15 +50,15 @@ class JniIdManager {
void Init(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
- ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_);
- ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_);
- jmethodID EncodeMethodId(ReflectiveHandle<ArtMethod> method) REQUIRES(!Locks::jni_id_lock_)
+ EXPORT ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_);
+ EXPORT ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_);
+ EXPORT jmethodID EncodeMethodId(ReflectiveHandle<ArtMethod> method) REQUIRES(!Locks::jni_id_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_)
+ EXPORT jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- jfieldID EncodeFieldId(ReflectiveHandle<ArtField> field) REQUIRES(!Locks::jni_id_lock_)
+ EXPORT jfieldID EncodeFieldId(ReflectiveHandle<ArtField> field) REQUIRES(!Locks::jni_id_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_)
+ EXPORT jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
void VisitReflectiveTargets(ReflectiveValueVisitor* rvv)
@@ -66,7 +66,7 @@ class JniIdManager {
void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<mirror::Object> GetPointerMarker() REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT ObjPtr<mirror::Object> GetPointerMarker() REQUIRES_SHARED(Locks::mutator_lock_);
private:
template <typename ArtType>
@@ -113,7 +113,7 @@ class JniIdManager {
// This is required since normally we need to be able to allocate to encode new ids. This should
// only be used when absolutely required, for example to invoke user-callbacks during heap walking
// or similar.
-class ScopedEnableSuspendAllJniIdQueries {
+class EXPORT ScopedEnableSuspendAllJniIdQueries {
public:
ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_);
~ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 71bed2e0be..50037ecbfd 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -66,7 +66,7 @@
#include "thread.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace {
diff --git a/runtime/jni/jni_internal.h b/runtime/jni/jni_internal.h
index cfe8208a11..10168b511d 100644
--- a/runtime/jni/jni_internal.h
+++ b/runtime/jni/jni_internal.h
@@ -27,14 +27,14 @@
#include "runtime.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
class ArtField;
class ArtMethod;
class ScopedObjectAccess;
const JNINativeInterface* GetJniNativeInterface();
-const JNINativeInterface* GetRuntimeShutdownNativeInterface();
+EXPORT const JNINativeInterface* GetRuntimeShutdownNativeInterface();
int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause);
diff --git a/runtime/jni/jni_internal_test.cc b/runtime/jni/jni_internal_test.cc
index 7f65925910..676bd59a55 100644
--- a/runtime/jni/jni_internal_test.cc
+++ b/runtime/jni/jni_internal_test.cc
@@ -28,7 +28,7 @@
#include "nativehelper/scoped_local_ref.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/jni/local_reference_table-inl.h b/runtime/jni/local_reference_table-inl.h
index 8b4604976f..cc94e9c538 100644
--- a/runtime/jni/local_reference_table-inl.h
+++ b/runtime/jni/local_reference_table-inl.h
@@ -27,7 +27,7 @@
#include "mirror/object_reference.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
namespace jni {
inline void LrtEntry::SetReference(ObjPtr<mirror::Object> ref) {
diff --git a/runtime/jni/local_reference_table.cc b/runtime/jni/local_reference_table.cc
index bf55f0ec3e..b8c2efcd45 100644
--- a/runtime/jni/local_reference_table.cc
+++ b/runtime/jni/local_reference_table.cc
@@ -34,7 +34,7 @@
#include <cstdlib>
-namespace art {
+namespace art HIDDEN {
namespace jni {
static constexpr bool kDumpStackOnNonLocalReference = false;
diff --git a/runtime/jni/local_reference_table.h b/runtime/jni/local_reference_table.h
index df2b5075a5..85c7964103 100644
--- a/runtime/jni/local_reference_table.h
+++ b/runtime/jni/local_reference_table.h
@@ -39,7 +39,7 @@
#include "obj_ptr.h"
#include "offsets.h"
-namespace art {
+namespace art HIDDEN {
class RootInfo;
@@ -274,8 +274,7 @@ class LocalReferenceTable {
// will return null if an error happened (with an appropriate error message set).
IndirectRef Add(LRTSegmentState previous_state,
ObjPtr<mirror::Object> obj,
- std::string* error_msg)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
// Given an `IndirectRef` in the table, return the `Object` it refers to.
//
@@ -330,7 +329,7 @@ class LocalReferenceTable {
// without recovering holes. Thus this is a conservative estimate.
size_t FreeCapacity() const;
- void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
+ EXPORT void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
REQUIRES_SHARED(Locks::mutator_lock_);
LRTSegmentState GetSegmentState() const {
diff --git a/runtime/jni/local_reference_table_test.cc b/runtime/jni/local_reference_table_test.cc
index 5839c60d0a..5063d728b2 100644
--- a/runtime/jni/local_reference_table_test.cc
+++ b/runtime/jni/local_reference_table_test.cc
@@ -24,7 +24,7 @@
#include "mirror/object-inl.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace jni {
using android::base::StringPrintf;
diff --git a/runtime/metrics/statsd.cc b/runtime/metrics/statsd.cc
index 716989131e..764550e648 100644
--- a/runtime/metrics/statsd.cc
+++ b/runtime/metrics/statsd.cc
@@ -386,12 +386,11 @@ class StatsdBackend : public MetricsBackend {
EncodeCompileFilter(session_data_.compiler_filter),
EncodeCompilationReason(session_data_.compilation_reason),
current_timestamp_,
- 0, // TODO: collect and report thread type (0 means UNKNOWN, but that
- // constant is not present in all branches)
+ 0, // deprecated - was ArtThreadType
datum_id.value(),
static_cast<int64_t>(value),
- statsd::ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN,
- statsd::ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN,
+ 0, // deprecated - was ArtDexMetadataType
+ 0, // deprecated - was ArtApkType
EncodeInstructionSet(kRuntimeISA),
EncodeGcCollectorType(Runtime::Current()->GetHeap()->GetForegroundCollectorType()),
EncodeUffdMinorFaultSupport());
diff --git a/runtime/native/dalvik_system_BaseDexClassLoader.cc b/runtime/native/dalvik_system_BaseDexClassLoader.cc
index a4f702c28d..f9a1aba022 100644
--- a/runtime/native/dalvik_system_BaseDexClassLoader.cc
+++ b/runtime/native/dalvik_system_BaseDexClassLoader.cc
@@ -25,7 +25,7 @@
#include "nativehelper/jni_macros.h"
#include "thread-inl.h"
-namespace art {
+namespace art HIDDEN {
static bool append_string(Thread* self,
Handle<mirror::ObjectArray<mirror::String>> array,
diff --git a/runtime/native/dalvik_system_BaseDexClassLoader.h b/runtime/native/dalvik_system_BaseDexClassLoader.h
index 4ec03ef7a6..5a18b18b50 100644
--- a/runtime/native/dalvik_system_BaseDexClassLoader.h
+++ b/runtime/native/dalvik_system_BaseDexClassLoader.h
@@ -20,7 +20,9 @@
#include <jni.h>
#include <unistd.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_dalvik_system_BaseDexClassLoader(JNIEnv* env);
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index f602f73630..f1c5d541a9 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -62,7 +62,7 @@
#include <sys/system_properties.h>
#endif // ART_TARGET_ANDROID
-namespace art {
+namespace art HIDDEN {
// Should be the same as dalvik.system.DexFile.ENFORCE_READ_ONLY_JAVA_DCL
static constexpr uint64_t kEnforceReadOnlyJavaDcl = 218865702;
diff --git a/runtime/native/dalvik_system_DexFile.h b/runtime/native/dalvik_system_DexFile.h
index 77d219dfad..c22b83d6e8 100644
--- a/runtime/native/dalvik_system_DexFile.h
+++ b/runtime/native/dalvik_system_DexFile.h
@@ -20,7 +20,9 @@
#include <jni.h>
#include <unistd.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
constexpr size_t kOatFileIndex = 0;
constexpr size_t kDexFileIndexStart = 1;
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index cf2b25d6a2..137b04fede 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -51,7 +51,7 @@
#include "thread-inl.h"
#include "trace.h"
-namespace art {
+namespace art HIDDEN {
static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
ScopedObjectAccess soa(Thread::ForEnv(env));
diff --git a/runtime/native/dalvik_system_VMDebug.h b/runtime/native/dalvik_system_VMDebug.h
index b7eb8a8379..6d53fbea9d 100644
--- a/runtime/native/dalvik_system_VMDebug.h
+++ b/runtime/native/dalvik_system_VMDebug.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_dalvik_system_VMDebug(JNIEnv* env);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index f1561a2530..e774f07dc9 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -66,6 +66,8 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version);
#include "thread-inl.h"
#include "thread_list.h"
+// TODO(260881207): should be HIDDEN, but some apps fail to launch
+// (e.g. b/319255249)
namespace art {
using android::base::StringPrintf;
diff --git a/runtime/native/dalvik_system_VMRuntime.h b/runtime/native/dalvik_system_VMRuntime.h
index 795caa5ec6..d66c107a30 100644
--- a/runtime/native/dalvik_system_VMRuntime.h
+++ b/runtime/native/dalvik_system_VMRuntime.h
@@ -19,6 +19,10 @@
#include <jni.h>
+#include "base/macros.h"
+
+// TODO(260881207): should be HIDDEN, but some apps fail to launch
+// (e.g. b/319255249)
namespace art {
void register_dalvik_system_VMRuntime(JNIEnv* env);
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 596b2eb435..599bdb9e4b 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -32,7 +32,7 @@
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
template <typename T,
typename ResultT =
diff --git a/runtime/native/dalvik_system_VMStack.h b/runtime/native/dalvik_system_VMStack.h
index 5638f99ec1..c7a62ad46a 100644
--- a/runtime/native/dalvik_system_VMStack.h
+++ b/runtime/native/dalvik_system_VMStack.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_dalvik_system_VMStack(JNIEnv* env);
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index dd44e2ec4b..cc47032bd4 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -47,7 +47,7 @@
#include <sys/resource.h>
-namespace art {
+namespace art HIDDEN {
// Set to true to always determine the non-debuggable classes even if we would not allow a debugger
// to actually attach.
diff --git a/runtime/native/dalvik_system_ZygoteHooks.h b/runtime/native/dalvik_system_ZygoteHooks.h
index ca0658d318..fbd14c0fcc 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.h
+++ b/runtime/native/dalvik_system_ZygoteHooks.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_dalvik_system_ZygoteHooks(JNIEnv* env);
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 2abc4935e0..1dc74e0db2 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -56,7 +56,7 @@
#include "scoped_thread_state_change-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread* self) {
return [=]() REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/native/java_lang_Class.h b/runtime/native/java_lang_Class.h
index 8f769c39e9..aaa9b669d0 100644
--- a/runtime/native/java_lang_Class.h
+++ b/runtime/native/java_lang_Class.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_Class(JNIEnv* env);
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 8fc10d1114..5649b2cc5b 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -24,7 +24,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobject Object_internalClone(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_Object.h b/runtime/native/java_lang_Object.h
index c860571904..1ea2c05d19 100644
--- a/runtime/native/java_lang_Object.h
+++ b/runtime/native/java_lang_Object.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_Object(JNIEnv* env);
diff --git a/runtime/native/java_lang_StackStreamFactory.cc b/runtime/native/java_lang_StackStreamFactory.cc
index f876c1014b..24d903047d 100644
--- a/runtime/native/java_lang_StackStreamFactory.cc
+++ b/runtime/native/java_lang_StackStreamFactory.cc
@@ -23,7 +23,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
static jobject StackStreamFactory_nativeGetStackAnchor(JNIEnv* env, jclass) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_StackStreamFactory.h b/runtime/native/java_lang_StackStreamFactory.h
index 2216871ebf..31b3c9528d 100644
--- a/runtime/native/java_lang_StackStreamFactory.h
+++ b/runtime/native/java_lang_StackStreamFactory.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_StackStreamFactory(JNIEnv* env);
diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc
index f70a188e79..1ba0028fd3 100644
--- a/runtime/native/java_lang_String.cc
+++ b/runtime/native/java_lang_String.cc
@@ -31,7 +31,7 @@
#include "scoped_thread_state_change-inl.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
static jchar String_charAt(JNIEnv* env, jobject java_this, jint index) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_String.h b/runtime/native/java_lang_String.h
index 357eb3daf9..a78fdcec72 100644
--- a/runtime/native/java_lang_String.h
+++ b/runtime/native/java_lang_String.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_String(JNIEnv* env);
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 2fbebc0941..e6c03dbcf2 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -28,7 +28,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
static jstring StringFactory_newStringFromBytes(JNIEnv* env, jclass, jbyteArray java_data,
jint high, jint offset, jint byte_count) {
diff --git a/runtime/native/java_lang_StringFactory.h b/runtime/native/java_lang_StringFactory.h
index c476ad3db9..cdc19df87d 100644
--- a/runtime/native/java_lang_StringFactory.h
+++ b/runtime/native/java_lang_StringFactory.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_StringFactory(JNIEnv* env);
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index 63cbd2c815..203d98dc4c 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -29,7 +29,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
/*
* We make guarantees about the atomicity of accesses to primitive variables. These guarantees
diff --git a/runtime/native/java_lang_System.h b/runtime/native/java_lang_System.h
index e371fa5db4..a52972711d 100644
--- a/runtime/native/java_lang_System.h
+++ b/runtime/native/java_lang_System.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_System(JNIEnv* env);
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index fd67a0a7fa..65e3009c0f 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -29,7 +29,7 @@
#include "thread_list.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
static jobject Thread_currentThread(JNIEnv* env, jclass) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_Thread.h b/runtime/native/java_lang_Thread.h
index 7700ce29a8..ef880a9904 100644
--- a/runtime/native/java_lang_Thread.h
+++ b/runtime/native/java_lang_Thread.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_Thread(JNIEnv* env);
diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc
index b89e287481..091ad03bb2 100644
--- a/runtime/native/java_lang_Throwable.cc
+++ b/runtime/native/java_lang_Throwable.cc
@@ -23,7 +23,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "thread.h"
-namespace art {
+namespace art HIDDEN {
static jobject Throwable_nativeFillInStackTrace(JNIEnv* env, jclass) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_Throwable.h b/runtime/native/java_lang_Throwable.h
index f9aea84abe..6758e48951 100644
--- a/runtime/native/java_lang_Throwable.h
+++ b/runtime/native/java_lang_Throwable.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_Throwable(JNIEnv* env);
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 4dad46fb8c..ba1fde00d3 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -38,7 +38,7 @@
#include "thread-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
// A class so we can be friends with ClassLinker and access internal methods.
class VMClassLoader {
diff --git a/runtime/native/java_lang_VMClassLoader.h b/runtime/native/java_lang_VMClassLoader.h
index bf8d94f5a9..adf0c0aeac 100644
--- a/runtime/native/java_lang_VMClassLoader.h
+++ b/runtime/native/java_lang_VMClassLoader.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_VMClassLoader(JNIEnv* env);
diff --git a/runtime/native/java_lang_invoke_MethodHandle.cc b/runtime/native/java_lang_invoke_MethodHandle.cc
index 5309a28a09..819656fd05 100644
--- a/runtime/native/java_lang_invoke_MethodHandle.cc
+++ b/runtime/native/java_lang_invoke_MethodHandle.cc
@@ -27,7 +27,7 @@
#include "native_util.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
static void MethodHandle_invokeExactWithFrame(JNIEnv* env, jobject thiz, jobject arguments) {
ScopedObjectAccess soa(env);
diff --git a/runtime/native/java_lang_invoke_MethodHandle.h b/runtime/native/java_lang_invoke_MethodHandle.h
index 1f38ac7b27..f46f32426b 100644
--- a/runtime/native/java_lang_invoke_MethodHandle.h
+++ b/runtime/native/java_lang_invoke_MethodHandle.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_invoke_MethodHandle(JNIEnv* env);
diff --git a/runtime/native/java_lang_invoke_MethodHandleImpl.cc b/runtime/native/java_lang_invoke_MethodHandleImpl.cc
index 00ce01f11a..ccd3370ff7 100644
--- a/runtime/native/java_lang_invoke_MethodHandleImpl.cc
+++ b/runtime/native/java_lang_invoke_MethodHandleImpl.cc
@@ -28,7 +28,7 @@
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobject MethodHandleImpl_getMemberInternal(JNIEnv* env, jobject thiz) {
ScopedObjectAccess soa(env);
diff --git a/runtime/native/java_lang_invoke_MethodHandleImpl.h b/runtime/native/java_lang_invoke_MethodHandleImpl.h
index 0e50371697..49d4c2c9ec 100644
--- a/runtime/native/java_lang_invoke_MethodHandleImpl.h
+++ b/runtime/native/java_lang_invoke_MethodHandleImpl.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_invoke_MethodHandleImpl(JNIEnv* env);
diff --git a/runtime/native/java_lang_ref_FinalizerReference.cc b/runtime/native/java_lang_ref_FinalizerReference.cc
index 535b243411..52f6f734d9 100644
--- a/runtime/native/java_lang_ref_FinalizerReference.cc
+++ b/runtime/native/java_lang_ref_FinalizerReference.cc
@@ -26,7 +26,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jboolean FinalizerReference_makeCircularListIfUnenqueued(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_ref_FinalizerReference.h b/runtime/native/java_lang_ref_FinalizerReference.h
index 848a7aded6..13d1a12c34 100644
--- a/runtime/native/java_lang_ref_FinalizerReference.h
+++ b/runtime/native/java_lang_ref_FinalizerReference.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_ref_FinalizerReference(JNIEnv* env);
diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc
index bd7235e14f..4c411c8db4 100644
--- a/runtime/native/java_lang_ref_Reference.cc
+++ b/runtime/native/java_lang_ref_Reference.cc
@@ -26,7 +26,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobject Reference_getReferent(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_ref_Reference.h b/runtime/native/java_lang_ref_Reference.h
index 0cbf11646d..cc75069657 100644
--- a/runtime/native/java_lang_ref_Reference.h
+++ b/runtime/native/java_lang_ref_Reference.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_ref_Reference(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index ff94593cdf..9ac6e614b6 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -29,7 +29,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobject Array_createMultiArray(
JNIEnv* env, jclass, jclass javaElementClass, jintArray javaDimArray) {
diff --git a/runtime/native/java_lang_reflect_Array.h b/runtime/native/java_lang_reflect_Array.h
index 805bf7992a..35b87b7af4 100644
--- a/runtime/native/java_lang_reflect_Array.h
+++ b/runtime/native/java_lang_reflect_Array.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Array(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 98afddc260..f9278ab0d6 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -34,7 +34,7 @@
#include "reflection.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_reflect_Constructor.h b/runtime/native/java_lang_reflect_Constructor.h
index 7baae978e6..9c36ef4fed 100644
--- a/runtime/native/java_lang_reflect_Constructor.h
+++ b/runtime/native/java_lang_reflect_Constructor.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Constructor(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index 87c9f6c341..3f3b648ecf 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -35,7 +35,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/native/java_lang_reflect_Executable.h b/runtime/native/java_lang_reflect_Executable.h
index 0cfed62e49..05b0a234e0 100644
--- a/runtime/native/java_lang_reflect_Executable.h
+++ b/runtime/native/java_lang_reflect_Executable.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Executable(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index f2603d4c48..622b514ea3 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -37,7 +37,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/native/java_lang_reflect_Field.h b/runtime/native/java_lang_reflect_Field.h
index 1739711de8..b5368b97f0 100644
--- a/runtime/native/java_lang_reflect_Field.h
+++ b/runtime/native/java_lang_reflect_Field.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Field(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 5f02ad0fd9..8cbc070eee 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -32,7 +32,7 @@
#include "reflection.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static jobject Method_getDefaultValue(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/java_lang_reflect_Method.h b/runtime/native/java_lang_reflect_Method.h
index 3a93cd05d9..4b48ced9f4 100644
--- a/runtime/native/java_lang_reflect_Method.h
+++ b/runtime/native/java_lang_reflect_Method.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Method(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
index 263a56796f..fe9e4e3cbf 100644
--- a/runtime/native/java_lang_reflect_Parameter.cc
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -28,7 +28,7 @@
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
using android::base::StringPrintf;
diff --git a/runtime/native/java_lang_reflect_Parameter.h b/runtime/native/java_lang_reflect_Parameter.h
index f6322b146f..97873fbfaf 100644
--- a/runtime/native/java_lang_reflect_Parameter.h
+++ b/runtime/native/java_lang_reflect_Parameter.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Parameter(JNIEnv* env);
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index f723ed223d..a89f8274f8 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -27,7 +27,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "verify_object.h"
-namespace art {
+namespace art HIDDEN {
static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring name, jobjectArray interfaces,
jobject loader, jobjectArray methods, jobjectArray throws) {
diff --git a/runtime/native/java_lang_reflect_Proxy.h b/runtime/native/java_lang_reflect_Proxy.h
index e25f0f76b6..e6b3f241c7 100644
--- a/runtime/native/java_lang_reflect_Proxy.h
+++ b/runtime/native/java_lang_reflect_Proxy.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_lang_reflect_Proxy(JNIEnv* env);
diff --git a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
index fa288edcb8..3f4c609432 100644
--- a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
+++ b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
@@ -24,7 +24,7 @@
#include "jni/jni_internal.h"
#include "native_util.h"
-namespace art {
+namespace art HIDDEN {
static jboolean AtomicLong_VMSupportsCS8(JNIEnv*, jclass) {
return QuasiAtomic::LongAtomicsUseMutexes(kRuntimeISA) ? JNI_FALSE : JNI_TRUE;
diff --git a/runtime/native/java_util_concurrent_atomic_AtomicLong.h b/runtime/native/java_util_concurrent_atomic_AtomicLong.h
index 990dc861ff..de442ed39b 100644
--- a/runtime/native/java_util_concurrent_atomic_AtomicLong.h
+++ b/runtime/native/java_util_concurrent_atomic_AtomicLong.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_java_util_concurrent_atomic_AtomicLong(JNIEnv* env);
diff --git a/runtime/native/jdk_internal_misc_Unsafe.cc b/runtime/native/jdk_internal_misc_Unsafe.cc
index 9b2021d176..10c6b2da4f 100644
--- a/runtime/native/jdk_internal_misc_Unsafe.cc
+++ b/runtime/native/jdk_internal_misc_Unsafe.cc
@@ -36,7 +36,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace {
// Checks a JNI argument `size` fits inside a size_t and throws a RuntimeException if not (see
diff --git a/runtime/native/jdk_internal_misc_Unsafe.h b/runtime/native/jdk_internal_misc_Unsafe.h
index 779cd5fb3e..61b377bbfa 100644
--- a/runtime/native/jdk_internal_misc_Unsafe.h
+++ b/runtime/native/jdk_internal_misc_Unsafe.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_jdk_internal_misc_Unsafe(JNIEnv* env);
diff --git a/runtime/native/libcore_io_Memory.cc b/runtime/native/libcore_io_Memory.cc
index 5e38280259..66a16ed0ad 100644
--- a/runtime/native/libcore_io_Memory.cc
+++ b/runtime/native/libcore_io_Memory.cc
@@ -25,7 +25,7 @@
#include "nativehelper/scoped_primitive_array.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
// Use packed structures for access to unaligned data on targets with alignment restrictions.
// The compiler will generate appropriate code to access these structures without
diff --git a/runtime/native/libcore_io_Memory.h b/runtime/native/libcore_io_Memory.h
index 8c8a2ec17c..bf60986be4 100644
--- a/runtime/native/libcore_io_Memory.h
+++ b/runtime/native/libcore_io_Memory.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_libcore_io_Memory(JNIEnv* env);
diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc
index 46f8993a10..b497f1092d 100644
--- a/runtime/native/libcore_util_CharsetUtils.cc
+++ b/runtime/native/libcore_util_CharsetUtils.cc
@@ -28,7 +28,7 @@
#include "nativehelper/jni_macros.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static void CharsetUtils_asciiBytesToChars(JNIEnv* env, jclass, jbyteArray javaBytes, jint offset,
jint length, jcharArray javaChars) {
diff --git a/runtime/native/libcore_util_CharsetUtils.h b/runtime/native/libcore_util_CharsetUtils.h
index 3518bdb6f7..eaafcab30e 100644
--- a/runtime/native/libcore_util_CharsetUtils.h
+++ b/runtime/native/libcore_util_CharsetUtils.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_libcore_util_CharsetUtils(JNIEnv* env);
diff --git a/runtime/native/native_util.h b/runtime/native/native_util.h
index 784dba319e..f399359b11 100644
--- a/runtime/native/native_util.h
+++ b/runtime/native/native_util.h
@@ -23,7 +23,7 @@
#include "base/macros.h"
#include "nativehelper/scoped_local_ref.h"
-namespace art {
+namespace art HIDDEN {
ALWAYS_INLINE inline void RegisterNativeMethodsInternal(JNIEnv* env,
const char* jni_class_name,
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
index 419aed8578..b2e94f90cc 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
@@ -26,7 +26,7 @@
#include "nativehelper/scoped_primitive_array.h"
#include "scoped_fast_native_object_access-inl.h"
-namespace art {
+namespace art HIDDEN {
static void DdmServer_nativeSendChunk(JNIEnv* env, jclass, jint type,
jbyteArray javaData, jint offset, jint length) {
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.h b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.h
index 9a4645c1aa..fc5cfc9b59 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.h
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_org_apache_harmony_dalvik_ddmc_DdmServer(JNIEnv* env);
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index f20cd281e8..6da4529289 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -31,7 +31,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "thread_list.h"
-namespace art {
+namespace art HIDDEN {
static void DdmVmInternal_setRecentAllocationsTrackingEnabled(JNIEnv*, jclass, jboolean enable) {
Dbg::SetAllocTrackingEnabled(enable);
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
index 736e4c8793..5484f3682c 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(JNIEnv* env);
diff --git a/runtime/native/scoped_fast_native_object_access-inl.h b/runtime/native/scoped_fast_native_object_access-inl.h
index 0b8ad117d2..cd1a0b26d7 100644
--- a/runtime/native/scoped_fast_native_object_access-inl.h
+++ b/runtime/native/scoped_fast_native_object_access-inl.h
@@ -22,7 +22,7 @@
#include "art_method.h"
#include "scoped_thread_state_change-inl.h"
-namespace art {
+namespace art HIDDEN {
inline ScopedFastNativeObjectAccess::ScopedFastNativeObjectAccess(JNIEnv* env)
: ScopedObjectAccessAlreadyRunnable(env) {
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index 6a9365d517..a3b01d7701 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -19,9 +19,10 @@
#include <jni.h>
+#include "base/macros.h"
#include "scoped_thread_state_change.h"
-namespace art {
+namespace art HIDDEN {
// Variant of ScopedObjectAccess that does no runnable transitions. Should only be used by "fast"
// JNI methods.
diff --git a/runtime/native/string_array_utils.h b/runtime/native/string_array_utils.h
index 41d50933f9..f1fbe540f5 100644
--- a/runtime/native/string_array_utils.h
+++ b/runtime/native/string_array_utils.h
@@ -17,13 +17,14 @@
#ifndef ART_RUNTIME_NATIVE_STRING_ARRAY_UTILS_H_
#define ART_RUNTIME_NATIVE_STRING_ARRAY_UTILS_H_
+#include "base/macros.h"
#include "base/locks.h"
#include "class_root-inl.h"
#include "handle_scope-inl.h"
#include "mirror/object_array-alloc-inl.h"
#include "mirror/string.h"
-namespace art {
+namespace art HIDDEN {
namespace detail {
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index f1e47ee100..573b5a9db2 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -36,7 +36,7 @@
#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes-inl.h"
-namespace art {
+namespace art HIDDEN {
static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint expectedValue, jint newValue) {
diff --git a/runtime/native/sun_misc_Unsafe.h b/runtime/native/sun_misc_Unsafe.h
index 93194f4fad..fe120b5a9b 100644
--- a/runtime/native/sun_misc_Unsafe.h
+++ b/runtime/native/sun_misc_Unsafe.h
@@ -19,7 +19,9 @@
#include <jni.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
void register_sun_misc_Unsafe(JNIEnv* env);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 86a2ddabfd..590a596c1f 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -407,10 +407,6 @@ class DeoptimizeStackVisitor final : public StackVisitor {
return bottom_shadow_frame_;
}
- const std::vector<uint32_t>& GetDexPcs() const {
- return dex_pcs_;
- }
-
void FinishStackWalk() REQUIRES_SHARED(Locks::mutator_lock_) {
// This is the upcall, or the next full frame in single-frame deopt, or the
// code isn't deoptimizeable. We remember the frame and last pc so that we
@@ -519,14 +515,11 @@ class DeoptimizeStackVisitor final : public StackVisitor {
}
prev_shadow_frame_ = new_frame;
- if (single_frame_deopt_) {
- dex_pcs_.push_back(GetDexPc());
- if (!IsInInlinedFrame()) {
- // Single-frame deopt ends at the first non-inlined frame and needs to store that method.
- single_frame_done_ = true;
- single_frame_deopt_method_ = method;
- single_frame_deopt_quick_method_header_ = GetCurrentOatQuickMethodHeader();
- }
+ if (single_frame_deopt_ && !IsInInlinedFrame()) {
+ // Single-frame deopt ends at the first non-inlined frame and needs to store that method.
+ single_frame_done_ = true;
+ single_frame_deopt_method_ = method;
+ single_frame_deopt_quick_method_header_ = GetCurrentOatQuickMethodHeader();
}
callee_method_ = method;
return true;
@@ -666,7 +659,6 @@ class DeoptimizeStackVisitor final : public StackVisitor {
// a deopt after running method exit callbacks if the callback throws or requests events that
// need a deopt.
bool skip_method_exit_callbacks_;
- std::vector<uint32_t> dex_pcs_;
DISALLOW_COPY_AND_ASSIGN(DeoptimizeStackVisitor);
};
@@ -747,26 +739,11 @@ void QuickExceptionHandler::DeoptimizeSingleFrame(DeoptimizationKind kind) {
case Instruction::INVOKE_VIRTUAL:
case Instruction::INVOKE_INTERFACE_RANGE:
case Instruction::INVOKE_VIRTUAL_RANGE: {
- uint32_t encoded_dex_pc = InlineCache::EncodeDexPc(
- visitor.GetSingleFrameDeoptMethod(),
- visitor.GetDexPcs(),
- runtime->GetJit()->GetJitCompiler()->GetInlineMaxCodeUnits());
- if (encoded_dex_pc != static_cast<uint32_t>(-1)) {
- // The inline cache comes from the top-level method.
- runtime->GetJit()->GetCodeCache()->MaybeUpdateInlineCache(
- visitor.GetSingleFrameDeoptMethod(),
- encoded_dex_pc,
- shadow_frame->GetVRegReference(inst->VRegC())->GetClass(),
- self_);
- } else {
- // If the top-level inline cache did not exist, update the one for the
- // bottom method, we know it's the one that was used for compilation.
- runtime->GetJit()->GetCodeCache()->MaybeUpdateInlineCache(
- shadow_frame->GetMethod(),
- dex_pc,
- shadow_frame->GetVRegReference(inst->VRegC())->GetClass(),
- self_);
- }
+ runtime->GetJit()->GetCodeCache()->MaybeUpdateInlineCache(
+ shadow_frame->GetMethod(),
+ dex_pc,
+ shadow_frame->GetVRegReference(inst->VRegC())->GetClass(),
+ self_);
break;
}
default: {
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index d8f68c4080..83ab469c68 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -237,6 +237,7 @@ inline void Thread::TransitionToSuspendedAndRunCheckpoints(ThreadState new_state
StateAndFlags old_state_and_flags = GetStateAndFlags(std::memory_order_relaxed);
DCHECK_EQ(old_state_and_flags.GetState(), ThreadState::kRunnable);
if (UNLIKELY(old_state_and_flags.IsFlagSet(ThreadFlag::kCheckpointRequest))) {
+ IncrementStatsCounter(&checkpoint_count_);
RunCheckpointFunction();
continue;
}
@@ -255,6 +256,7 @@ inline void Thread::TransitionToSuspendedAndRunCheckpoints(ThreadState new_state
tls32_.state_and_flags.CompareAndSetWeakRelease(old_state_and_flags.GetValue(),
new_state_and_flags.GetValue());
if (LIKELY(done)) {
+ IncrementStatsCounter(&suspended_count_);
break;
}
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 719ecfbf9c..46856e3e99 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1724,8 +1724,10 @@ bool Thread::RequestSynchronousCheckpoint(Closure* function, ThreadState wait_st
}
}
if (!is_suspended) {
- bool success =
- Runtime::Current()->GetThreadList()->WaitForSuspendBarrier(&wrapped_barrier.barrier_);
+ bool success = !Runtime::Current()
+ ->GetThreadList()
+ ->WaitForSuspendBarrier(&wrapped_barrier.barrier_)
+ .has_value();
CHECK(success);
}
diff --git a/runtime/thread.h b/runtime/thread.h
index 49e9952e70..6de1e26615 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -2324,6 +2324,15 @@ class EXPORT Thread {
// Debug disable read barrier count, only is checked for debug builds and only in the runtime.
uint8_t debug_disallow_read_barrier_ = 0;
+ // Counters used only for debugging and error reporting. Likely to wrap. Small to avoid
+ // increasing Thread size.
+ // We currently maintain these unconditionally, since it doesn't cost much, and we seem to have
+ // persistent issues with suspension timeouts, which these should help to diagnose.
+ // TODO: Reconsider this.
+ std::atomic<uint8_t> suspended_count_ = 0; // Number of times we entered a suspended state after
+ // running checkpoints.
+ std::atomic<uint8_t> checkpoint_count_ = 0; // Number of checkpoints we started running.
+
// Note that it is not in the packed struct, may not be accessed for cross compilation.
uintptr_t poison_object_cookie_ = 0;
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index c07f53fbdb..d69ad35a9e 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -655,36 +655,107 @@ void ThreadList::FlipThreadRoots(Closure* thread_flip_visitor,
Locks::mutator_lock_->SharedUnlock(self);
}
-bool ThreadList::WaitForSuspendBarrier(AtomicInteger* barrier) {
#if ART_USE_FUTEXES
- // Only fail after multiple timeouts, to make us robust against app freezing.
- static constexpr int kIters = 5;
+static constexpr int kSuspendBarrierIters = 5;
+
+// Returns true if it timed out.
+static bool WaitOnceForSuspendBarrier(AtomicInteger* barrier,
+ int32_t cur_val,
+ uint64_t timeout_ns) {
timespec wait_timeout;
- InitTimeSpec(
- false, CLOCK_MONOTONIC, NsToMs(thread_suspend_timeout_ns_ / kIters), 0, &wait_timeout);
-#else
- static constexpr int kIters = 10'000'000;
-#endif
- for (int i = 0; i < kIters;) {
- int32_t cur_val = barrier->load(std::memory_order_acquire);
- if (cur_val <= 0) {
- DCHECK_EQ(cur_val, 0);
+ DCHECK_GE(NsToMs(timeout_ns / kSuspendBarrierIters), 100ul);
+ InitTimeSpec(false, CLOCK_MONOTONIC, NsToMs(timeout_ns / kSuspendBarrierIters), 0, &wait_timeout);
+ if (futex(barrier->Address(), FUTEX_WAIT_PRIVATE, cur_val, &wait_timeout, nullptr, 0) != 0) {
+ if (errno == ETIMEDOUT) {
return true;
+ } else if (errno != EAGAIN && errno != EINTR) {
+ PLOG(FATAL) << "futex wait for suspend barrier failed";
}
-#if ART_USE_FUTEXES
- if (futex(barrier->Address(), FUTEX_WAIT_PRIVATE, cur_val, &wait_timeout, nullptr, 0) != 0) {
- if (errno == ETIMEDOUT) {
- ++i;
- } else if (errno != EAGAIN && errno != EINTR) {
- PLOG(FATAL) << "futex wait for suspend barrier failed";
- }
+ }
+ return false;
+}
+
+#else
+static constexpr int kSuspendBarrierIters = 10;
+
+static bool WaitOnceForSuspendBarrier(AtomicInteger* barrier,
+ int32_t cur_val,
+ uint64_t timeout_ns) {
+ DCHECK_GE(NsToMs(timeout_ns / kSuspendBarrierIters), 100ul);
+ for (int i = 0; i < 1'000'000; ++i) {
+ sched_yield();
+ if (barrier->load(std::memory_order_acquire) == 0) {
+ return false;
}
+ }
+ return true;
+}
+#endif
+
+// Return a short string describing the scheduling state of the thread with the given tid.
+static std::string GetThreadState(pid_t t) {
+#if defined(__linux__)
+ static constexpr int BUF_SIZE = 90;
+ char file_name_buf[BUF_SIZE];
+ char buf[BUF_SIZE];
+ snprintf(file_name_buf, BUF_SIZE, "/proc/%d/stat", t);
+ int stat_fd = open(file_name_buf, O_RDONLY | O_CLOEXEC);
+ if (stat_fd < 0) {
+ return std::string("failed to get thread state: ") + std::string(strerror(errno));
+ }
+ CHECK(stat_fd >= 0) << strerror(errno);
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(stat_fd, buf, BUF_SIZE));
+ CHECK(bytes_read >= 0) << strerror(errno);
+ int ret = close(stat_fd);
+ DCHECK(ret == 0) << strerror(errno);
+ buf[BUF_SIZE - 1] = '\0';
+ return buf;
#else
- sched_yield(); // Not ideal, but ART_USE_FUTEXES is set on Linux, including all targets.
- ++i;
+ return "unknown state";
+#endif
+}
+
+std::optional<std::string> ThreadList::WaitForSuspendBarrier(AtomicInteger* barrier, pid_t t) {
+ // Only fail after kIter timeouts, to make us robust against app freezing.
+#if ART_USE_FUTEXES
+ const uint64_t start_time = NanoTime();
#endif
+ int32_t cur_val = barrier->load(std::memory_order_acquire);
+ if (cur_val <= 0) {
+ DCHECK_EQ(cur_val, 0);
+ return std::nullopt;
+ }
+ int i = 0;
+ if (WaitOnceForSuspendBarrier(barrier, cur_val, thread_suspend_timeout_ns_)) {
+ i = 1;
+ }
+ cur_val = barrier->load(std::memory_order_acquire);
+ if (cur_val <= 0) {
+ DCHECK_EQ(cur_val, 0);
+ return std::nullopt;
+ }
+
+ // Long wait; gather information in case of timeout.
+ std::string sampled_state = t == 0 ? "" : GetThreadState(t);
+ while (i < kSuspendBarrierIters) {
+ if (WaitOnceForSuspendBarrier(barrier, cur_val, thread_suspend_timeout_ns_)) {
+ ++i;
+#if ART_USE_FUTEXES
+ CHECK_GE(NanoTime() - start_time,
+ i * thread_suspend_timeout_ns_ / kSuspendBarrierIters - 1'000'000);
+#endif
+ }
+ cur_val = barrier->load(std::memory_order_acquire);
+ if (cur_val <= 0) {
+ DCHECK_EQ(cur_val, 0);
+ return std::nullopt;
+ }
}
- return barrier->load(std::memory_order_acquire) == 0;
+ std::string result = t == 0 ? "" :
+ "Target states: [" + sampled_state + ", " + GetThreadState(t) +
+ "]" + std::to_string(cur_val) + "@" +
+ std::to_string((uintptr_t)barrier) + "->";
+ return result + std::to_string(barrier->load(std::memory_order_acquire));
}
void ThreadList::SuspendAll(const char* cause, bool long_suspend) {
@@ -830,7 +901,7 @@ void ThreadList::SuspendAllInternal(Thread* self, SuspendReason reason) {
// We're already not runnable, so an attempt to suspend us should succeed.
}
- if (!WaitForSuspendBarrier(&pending_threads)) {
+ if (WaitForSuspendBarrier(&pending_threads).has_value()) {
const uint64_t wait_time = NanoTime() - start_time;
MutexLock mu(self, *Locks::thread_list_lock_);
MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
@@ -1005,7 +1076,7 @@ Thread* ThreadList::SuspendThreadByPeer(jobject peer, SuspendReason reason) {
usleep(kThreadSuspendSleepUs);
}
// Now wait for target to decrement suspend barrier.
- if (is_suspended || WaitForSuspendBarrier(&wrapped_barrier.barrier_)) {
+ if (is_suspended || !WaitForSuspendBarrier(&wrapped_barrier.barrier_).has_value()) {
// wrapped_barrier.barrier_ has been decremented and will no longer be accessed.
VLOG(threads) << "SuspendThreadByPeer thread suspended: " << *thread;
if (ATraceEnabled()) {
@@ -1035,7 +1106,11 @@ Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, SuspendReason re
CHECK_NE(thread_id, kInvalidThreadId);
VLOG(threads) << "SuspendThreadByThreadId starting";
Thread* thread;
+ pid_t tid;
+ uint8_t suspended_count;
+ uint8_t checkpoint_count;
WrappedSuspend1Barrier wrapped_barrier{};
+ static_assert(sizeof wrapped_barrier.barrier_ == sizeof(uint32_t));
for (int iter_count = 1;; ++iter_count) {
{
// Note: this will transition to runnable and potentially suspend.
@@ -1053,6 +1128,9 @@ Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, SuspendReason re
{
MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
if (LIKELY(self->GetSuspendCount() == 0)) {
+ tid = thread->GetTid();
+ suspended_count = thread->suspended_count_;
+ checkpoint_count = thread->checkpoint_count_;
thread->IncrementSuspendCount(self, nullptr, &wrapped_barrier, reason);
if (thread->IsSuspended()) {
// See the discussion in mutator_gc_coord.md and SuspendAllInternal for the race here.
@@ -1077,7 +1155,17 @@ Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, SuspendReason re
usleep(kThreadSuspendSleepUs);
}
// Now wait for target to decrement suspend barrier.
- if (is_suspended || WaitForSuspendBarrier(&wrapped_barrier.barrier_)) {
+ std::optional<std::string> failure_info;
+ if (!is_suspended) {
+ // As an experiment, redundantly trigger suspension. TODO: Remove this.
+ std::atomic_thread_fence(std::memory_order_seq_cst);
+ thread->TriggerSuspend();
+ failure_info = WaitForSuspendBarrier(&wrapped_barrier.barrier_, tid);
+ if (!failure_info.has_value()) {
+ is_suspended = true;
+ }
+ }
+ if (is_suspended) {
// wrapped_barrier.barrier_ has been decremented and will no longer be accessed.
VLOG(threads) << "SuspendThreadByThreadId thread suspended: " << *thread;
if (ATraceEnabled()) {
@@ -1099,15 +1187,20 @@ Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, SuspendReason re
MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
first_barrier = thread->tlsPtr_.active_suspend1_barriers;
}
+ // 'thread' should still be suspended, and hence stick around.
LOG(FATAL) << StringPrintf(
"SuspendThreadByThreadId timed out: %d (%s), state&flags: 0x%x, priority: %d,"
- " barriers: %p, ours: %p",
+ " barriers: %p, ours: %p, barrier value: %d, nsusps: %d, ncheckpts: %d, thread_info: %s",
thread_id,
name.c_str(),
thread->GetStateAndFlags(std::memory_order_relaxed).GetValue(),
thread->GetNativePriority(),
first_barrier,
- &wrapped_barrier);
+ &wrapped_barrier,
+ wrapped_barrier.barrier_.load(),
+ thread->suspended_count_ - suspended_count,
+ thread->checkpoint_count_ - checkpoint_count,
+ failure_info.value().c_str());
UNREACHABLE();
}
}
diff --git a/runtime/thread_list.h b/runtime/thread_list.h
index 55baed8a31..f5eb5fdb2a 100644
--- a/runtime/thread_list.h
+++ b/runtime/thread_list.h
@@ -211,8 +211,10 @@ class ThreadList {
REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
!Locks::mutator_lock_);
- // Wait for suspend barrier to reach zero. Return false on timeout.
- bool WaitForSuspendBarrier(AtomicInteger* barrier);
+ // Wait for suspend barrier to reach zero. Return a string possibly containing diagnostic
+ // information on timeout, nothing on success. The argument t specifies a thread to monitor for
+ // the diagnostic information. If 0 is passed, we return an empty string on timeout.
+ std::optional<std::string> WaitForSuspendBarrier(AtomicInteger* barrier, pid_t t = 0);
private:
uint32_t AllocThreadId(Thread* self);
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index 084e714b42..d1b882f9f4 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -42,7 +42,7 @@
#include "verifier/method_verifier.h"
#include "verifier/reg_type_cache.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
using android::base::StringPrintf;
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index 65bc28c299..75a5a35b7e 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -23,13 +23,14 @@
#include <android-base/thread_annotations.h>
#include "base/locks.h"
+#include "base/macros.h"
#include "handle.h"
#include "obj_ptr.h"
#include "verifier/method_verifier.h"
#include "verifier/reg_type_cache.h"
#include "verifier_enums.h"
-namespace art {
+namespace art HIDDEN {
class ClassLinker;
class CompilerCallbacks;
@@ -55,18 +56,17 @@ class ClassVerifier {
public:
// The main entrypoint for class verification. During AOT, `klass` can be
// null.
- static FailureKind VerifyClass(Thread* self,
- VerifierDeps* verifier_deps,
- const DexFile* dex_file,
- Handle<mirror::Class> klass,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- HardFailLogMode log_level,
- uint32_t api_level,
- std::string* error)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ EXPORT static FailureKind VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
+ const DexFile* dex_file,
+ Handle<mirror::Class> klass,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error) REQUIRES_SHARED(Locks::mutator_lock_);
private:
DISALLOW_COPY_AND_ASSIGN(ClassVerifier);
diff --git a/runtime/verifier/instruction_flags.cc b/runtime/verifier/instruction_flags.cc
index ca3c68796d..73fb375731 100644
--- a/runtime/verifier/instruction_flags.cc
+++ b/runtime/verifier/instruction_flags.cc
@@ -18,7 +18,7 @@
#include <string.h>
-namespace art {
+namespace art HIDDEN {
namespace verifier {
std::string InstructionFlags::ToString() const {
diff --git a/runtime/verifier/instruction_flags.h b/runtime/verifier/instruction_flags.h
index 6cd2865f25..da5e2cd178 100644
--- a/runtime/verifier/instruction_flags.h
+++ b/runtime/verifier/instruction_flags.h
@@ -22,7 +22,7 @@
#include "base/macros.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
class InstructionFlags final {
diff --git a/runtime/verifier/method_verifier-inl.h b/runtime/verifier/method_verifier-inl.h
index a9fb1a0773..a13a58eede 100644
--- a/runtime/verifier/method_verifier-inl.h
+++ b/runtime/verifier/method_verifier-inl.h
@@ -19,7 +19,7 @@
#include "method_verifier.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
inline RegisterLine* MethodVerifier::GetRegLine(uint32_t dex_pc) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9830bfc8d7..fc5a57ed26 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -65,7 +65,7 @@
#include "verifier/method_verifier.h"
#include "verifier_deps.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
using android::base::StringPrintf;
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 649a24526c..288043610e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -36,7 +36,7 @@
#include "register_line.h"
#include "verifier_enums.h"
-namespace art {
+namespace art HIDDEN {
class ClassLinker;
class DexFile;
@@ -97,25 +97,25 @@ class PcToRegisterLineTable {
// The verifier
class MethodVerifier {
public:
- static MethodVerifier* VerifyMethodAndDump(Thread* self,
- VariableIndentationOutputStream* vios,
- uint32_t method_idx,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- const dex::CodeItem* code_item,
- uint32_t method_access_flags,
- uint32_t api_level)
+ EXPORT static MethodVerifier* VerifyMethodAndDump(Thread* self,
+ VariableIndentationOutputStream* vios,
+ uint32_t method_idx,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ const dex::CodeItem* code_item,
+ uint32_t method_access_flags,
+ uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
// Calculates the type information at the given `dex_pc`.
// No classes will be loaded.
- static MethodVerifier* CalculateVerificationInfo(Thread* self,
- ArtMethod* method,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- uint32_t dex_pc)
+ EXPORT static MethodVerifier* CalculateVerificationInfo(Thread* self,
+ ArtMethod* method,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ uint32_t dex_pc)
REQUIRES_SHARED(Locks::mutator_lock_);
const DexFile& GetDexFile() const {
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 0f0fd17905..1c6ed7c9b0 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -30,7 +30,7 @@
#include "scoped_thread_state_change-inl.h"
#include "verifier_enums.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
using metrics::test::CounterValue;
diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h
index 7fb24b2602..8db2fe669a 100644
--- a/runtime/verifier/reg_type-inl.h
+++ b/runtime/verifier/reg_type-inl.h
@@ -25,7 +25,7 @@
#include "mirror/class.h"
#include "verifier_deps.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
inline bool RegType::CanAccess(const RegType& other) const {
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 0433c6dcc5..845bcdc087 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -35,7 +35,7 @@
#include <limits>
#include <sstream>
-namespace art {
+namespace art HIDDEN {
namespace verifier {
using android::base::StringPrintf;
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 6cc9880f8c..66f075e73f 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -33,7 +33,7 @@
#include "handle_scope.h"
#include "obj_ptr.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
class ClassLoader;
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index b987c2c59c..b619694714 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -28,7 +28,7 @@
#include "reg_type.h"
#include "reg_type_cache.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
inline const art::verifier::RegType& RegTypeCache::GetFromId(uint16_t id) const {
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 55b37338cf..e57290c418 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -32,7 +32,7 @@
#include "mirror/object-inl.h"
#include "reg_type-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
ALWAYS_INLINE static inline bool MatchingPrecisionForClass(const RegType* entry, bool precise)
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index d88d4db177..ae8b904ecd 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -28,7 +28,7 @@
#include "gc_root.h"
#include "handle_scope.h"
-namespace art {
+namespace art HIDDEN {
namespace mirror {
class Class;
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 8ab7fc8cae..ec4c23ee59 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -28,7 +28,7 @@
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
class RegTypeTest : public CommonRuntimeTest {
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 6fa87c6fec..3967aaa88e 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -23,7 +23,7 @@
#include "method_verifier.h"
#include "reg_type_cache-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
// Should we dump a warning on failures to verify balanced locking? That would be an indication to
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index 0e9e0d4a52..62f2eb3ec0 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -23,7 +23,7 @@
#include "reg_type-inl.h"
#include "register_line-inl.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
using android::base::StringPrintf;
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index 3db1efb38e..fc8c4cbc6c 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -24,10 +24,11 @@
#include <android-base/logging.h>
#include "base/locks.h"
+#include "base/macros.h"
#include "base/safe_map.h"
#include "base/scoped_arena_containers.h"
-namespace art {
+namespace art HIDDEN {
class Instruction;
diff --git a/runtime/verifier/scoped_newline.h b/runtime/verifier/scoped_newline.h
index fb29e3ece8..ef2fc92154 100644
--- a/runtime/verifier/scoped_newline.h
+++ b/runtime/verifier/scoped_newline.h
@@ -21,7 +21,9 @@
#include <android-base/logging.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace verifier {
// RAII to inject a newline after a message.
diff --git a/runtime/verifier/verifier_compiler_binding.h b/runtime/verifier/verifier_compiler_binding.h
index 2266d50171..f94ea02109 100644
--- a/runtime/verifier/verifier_compiler_binding.h
+++ b/runtime/verifier/verifier_compiler_binding.h
@@ -22,7 +22,7 @@
#include "base/macros.h"
#include "verifier_enums.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
ALWAYS_INLINE
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 3286a605e8..6740446c3d 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -35,7 +35,7 @@
#include "reg_type_cache-inl.h"
#include "runtime.h"
-namespace art {
+namespace art HIDDEN {
namespace verifier {
VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only)
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 46b35545cf..dfa13ea112 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -23,6 +23,7 @@
#include "base/array_ref.h"
#include "base/locks.h"
+#include "base/macros.h"
#include "dex/dex_file_structs.h"
#include "dex/dex_file_types.h"
#include "handle.h"
@@ -30,7 +31,7 @@
#include "thread.h"
#include "verifier_enums.h" // For MethodVerifier::FailureKind.
-namespace art {
+namespace art HIDDEN {
class ArtField;
class ArtMethod;
@@ -60,18 +61,21 @@ class RegType;
// changes in the classpath.
class VerifierDeps {
public:
- explicit VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only = true);
+ EXPORT explicit VerifierDeps(const std::vector<const DexFile*>& dex_files,
+ bool output_only = true);
// Marker to know whether a class is verified. A non-verified class will have
// this marker as its offset entry in the encoded data.
static uint32_t constexpr kNotVerifiedMarker = std::numeric_limits<uint32_t>::max();
// Fill dependencies from stored data. Returns true on success, false on failure.
- bool ParseStoredData(const std::vector<const DexFile*>& dex_files, ArrayRef<const uint8_t> data);
+ EXPORT bool ParseStoredData(const std::vector<const DexFile*>& dex_files,
+ ArrayRef<const uint8_t> data);
// Merge `other` into this `VerifierDeps`'. `other` and `this` must be for the
// same set of dex files.
- void MergeWith(std::unique_ptr<VerifierDeps> other, const std::vector<const DexFile*>& dex_files);
+ EXPORT void MergeWith(std::unique_ptr<VerifierDeps> other,
+ const std::vector<const DexFile*>& dex_files);
// Record information that a class was verified.
// Note that this function is different from MaybeRecordVerificationStatus() which
@@ -80,10 +84,10 @@ class VerifierDeps {
REQUIRES(!Locks::verifier_deps_lock_);
// Record the verification status of the class defined in `class_def`.
- static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
- const DexFile& dex_file,
- const dex::ClassDef& class_def,
- FailureKind failure_kind)
+ EXPORT static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
+ const dex::ClassDef& class_def,
+ FailureKind failure_kind)
REQUIRES(!Locks::verifier_deps_lock_);
// Record the outcome `is_assignable` of type assignability test from `source`
@@ -110,15 +114,16 @@ class VerifierDeps {
// Serialize the recorded dependencies and store the data into `buffer`.
// `dex_files` provides the order of the dex files in which the dependencies
// should be emitted.
- void Encode(const std::vector<const DexFile*>& dex_files, std::vector<uint8_t>* buffer) const;
+ EXPORT void Encode(const std::vector<const DexFile*>& dex_files,
+ std::vector<uint8_t>* buffer) const;
- void Dump(VariableIndentationOutputStream* vios) const;
+ EXPORT void Dump(VariableIndentationOutputStream* vios) const;
// Verify the encoded dependencies of this `VerifierDeps` are still valid.
- bool ValidateDependencies(Thread* self,
- Handle<mirror::ClassLoader> class_loader,
- const std::vector<const DexFile*>& dex_files,
- /* out */ std::string* error_msg) const
+ EXPORT bool ValidateDependencies(Thread* self,
+ Handle<mirror::ClassLoader> class_loader,
+ const std::vector<const DexFile*>& dex_files,
+ /* out */ std::string* error_msg) const
REQUIRES_SHARED(Locks::mutator_lock_);
const std::vector<bool>& GetVerifiedClasses(const DexFile& dex_file) const {
@@ -138,7 +143,7 @@ class VerifierDeps {
}
// Resets the data related to the given dex files.
- void ClearData(const std::vector<const DexFile*>& dex_files);
+ EXPORT void ClearData(const std::vector<const DexFile*>& dex_files);
// Parses raw VerifierDeps data to extract bitvectors of which class def indices
// were verified or not. The given `dex_files` must match the order and count of
@@ -195,7 +200,7 @@ class VerifierDeps {
// `dex_file` is not reported as being compiled.
DexFileDeps* GetDexFileDeps(const DexFile& dex_file);
- const DexFileDeps* GetDexFileDeps(const DexFile& dex_file) const;
+ EXPORT const DexFileDeps* GetDexFileDeps(const DexFile& dex_file) const;
// Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
// string ID. If not, an ID is assigned to the string and cached in `strings_`
diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h
index 9c55e99206..57994581db 100644
--- a/runtime/verifier/verifier_enums.h
+++ b/runtime/verifier/verifier_enums.h
@@ -19,7 +19,9 @@
#include <stdint.h>
-namespace art {
+#include "base/macros.h"
+
+namespace art HIDDEN {
namespace verifier {
// The mode that the verifier should run as.
diff --git a/test/2242-checker-lse-acquire-release-operations/src/Main.java b/test/2242-checker-lse-acquire-release-operations/src/Main.java
index 433a4cd343..4db0f359ef 100644
--- a/test/2242-checker-lse-acquire-release-operations/src/Main.java
+++ b/test/2242-checker-lse-acquire-release-operations/src/Main.java
@@ -24,63 +24,126 @@ class TestClass {
public class Main {
public static void main(String[] args) {
// Volatile accesses.
- assertEquals($noinline$testVolatileAccessesMustBeKept(new TestClass()), 3);
+ assertEquals(3, $noinline$testVolatileAccessesMustBeKept(new TestClass()));
+ assertEquals(3, $noinline$testSingletonVolatileAccessesCanBeRemoved());
// Volatile loads - Different fields shouldn't alias.
- assertEquals($noinline$testVolatileLoadDifferentFields(new TestClass(), new TestClass()), 3);
+ assertEquals(3, $noinline$testVolatileLoadDifferentFields(new TestClass(), new TestClass()));
assertEquals(
- $noinline$testVolatileLoadDifferentFieldsBlocking(new TestClass(), new TestClass()),
- 3);
+ 3, $noinline$testVolatileLoadDifferentFieldsBlocking(new TestClass(), new TestClass()));
// Volatile loads - Redundant store.
- assertEquals($noinline$testVolatileLoadRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testVolatileLoadRedundantStoreBlocking(new TestClass()), 2);
- assertEquals($noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
+ assertEquals(2, $noinline$testVolatileLoadRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testVolatileLoadRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(new TestClass()));
// Volatile loads - Set and merge values.
- assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), false), 2);
- assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testVolatileLoadSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileLoadSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), false));
- // Volatile stores - Different fields shouldn't alias.
- assertEquals($noinline$testVolatileStoreDifferentFields(new TestClass(), new TestClass()), 3);
+ // Volatile loads - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Volatile loads - Removal - Redundant store.
assertEquals(
- $noinline$testVolatileStoreDifferentFieldsBlocking(new TestClass(), new TestClass()),
- 3);
+ 2, $noinline$testVolatileLoadRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Volatile loads - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Volatile loads - Removal - with inlining
+ assertEquals(2, $noinline$testVolatileLoadInlineMethodWithSynchronizedScope(new TestClass()));
+
+ // Volatile stores - Different fields shouldn't alias.
+ assertEquals(3, $noinline$testVolatileStoreDifferentFields(new TestClass(), new TestClass()));
+ assertEquals(3,
+ $noinline$testVolatileStoreDifferentFieldsBlocking(new TestClass(), new TestClass()));
// Volatile stores - Redundant store.
- assertEquals($noinline$testVolatileStoreRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testVolatileStoreRedundantStoreBlocking(new TestClass()), 2);
- assertEquals($noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
+ assertEquals(2, $noinline$testVolatileStoreRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testVolatileStoreRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(new TestClass()));
// Volatile stores - Set and merge values.
- assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), false), 2);
- assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testVolatileStoreSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileStoreSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), true));
+ assertEquals(
+ 2, $noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), false));
+
+ // Volatile stores - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Volatile stores - Removal - Redundant store.
+ assertEquals(
+ 2, $noinline$testVolatileStoreRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Volatile stores - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Volatile stores - Removal - with inlining
+ assertEquals(2, $noinline$testVolatileStoreInlineMethodWithSynchronizedScope(new TestClass()));
// Monitor Operations - Different fields shouldn't alias.
+ // Make sure the static variable used for synchronization is non-null.
+ classForSync = new TestClass();
+
assertEquals(
- $noinline$testMonitorOperationDifferentFields(new TestClass(), new TestClass()), 3);
- assertEquals($noinline$testMonitorOperationDifferentFieldsBlocking(
- new TestClass(), new TestClass()),
- 3);
+ 3, $noinline$testMonitorOperationDifferentFields(new TestClass(), new TestClass()));
+ assertEquals(3,
+ $noinline$testMonitorOperationDifferentFieldsBlocking(
+ new TestClass(), new TestClass()));
// Monitor Operations - Redundant store.
- assertEquals($noinline$testMonitorOperationRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testMonitorOperationRedundantStoreBlocking(new TestClass()), 2);
- assertEquals(
- $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
- assertEquals($noinline$testMonitorOperationRedundantStoreBlockingExit(new TestClass()), 2);
+ assertEquals(2, $noinline$testMonitorOperationRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlockingExit(new TestClass()));
// Monitor Operations - Set and merge values.
- assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testMonitorOperationSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testMonitorOperationSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), true));
+ assertEquals(
+ 2, $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), false));
+
+ // Monitor Operations - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Monitor Operations - Removal - Redundant store.
assertEquals(
- $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), true), 1);
+ 2, $noinline$testMonitorOperationRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Monitor Operations - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Monitor Operations - Removal - with inlining
+ assertEquals(2, $noinline$testMonitorOperationInlineSynchronizedMethod(new TestClass()));
assertEquals(
- $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), false), 2);
+ 2, $noinline$testMonitorOperationInlineMethodWithSynchronizedScope(new TestClass()));
}
public static void assertEquals(int expected, int result) {
@@ -114,6 +177,31 @@ public class Main {
return result;
}
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testSingletonVolatileAccessesCanBeRemoved() {
+ Main m = new Main();
+ int result;
+ m.vi = 3;
+ // Redundant load can be removed.
+ result = m.vi;
+ result = m.vi;
+ // Redundant store can be removed.
+ m.vi = 3;
+ result = m.vi;
+ return result;
+ }
+
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
@@ -288,6 +376,136 @@ public class Main {
return obj.i;
}
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ int unused = m.vi;
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ int unused = m.vi;
+ obj.j = 2;
+ unused = m.vi;
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet field_name:Main.vi
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
+ Main m = new Main();
+
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ int unused = m.vi;
+ return obj.i;
+ }
+
+ // Can't eliminate the setters, or volatile getters in this method.
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileLoads(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileLoads(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ int $inline$SetterWithVolatileLoads(TestClass obj) {
+ obj.j = 1;
+ int unused = this.vi;
+ obj.j = 2;
+ unused = this.vi;
+ return obj.j;
+ }
+
+ // But we can eliminate once inlined.
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
+ static int $noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithVolatileLoads(obj);
+ }
+
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
@@ -462,6 +680,136 @@ public class Main {
return obj.i;
}
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ m.vi = 123;
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ m.vi = 123;
+ obj.j = 2;
+ m.vi = 123;
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
+ Main m = new Main();
+
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ m.vi = 123;
+ return obj.i;
+ }
+
+ // Can't eliminate the setters in this method.
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileStores(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileStores(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ int $inline$SetterWithVolatileStores(TestClass obj) {
+ obj.j = 1;
+ this.vi = 123;
+ obj.j = 2;
+ this.vi = 123;
+ return obj.j;
+ }
+
+ // But we can eliminate once inlined.
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
+ static int $noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithVolatileStores(obj);
+ }
+
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
@@ -483,15 +831,11 @@ public class Main {
// Unrelated monitor operations shouldn't block LSE.
static int $noinline$testMonitorOperationDifferentFields(TestClass obj1, TestClass obj2) {
- Main m = new Main();
- synchronized (m) {}
-
+ synchronized (classForSync) {}
obj1.i = 1;
obj2.j = 2;
int result = obj1.i + obj2.j;
-
- synchronized (m) {}
-
+ synchronized (classForSync) {}
return result;
}
@@ -513,11 +857,9 @@ public class Main {
// A synchronized operation blocks loads.
static int $noinline$testMonitorOperationDifferentFieldsBlocking(TestClass obj1, TestClass obj2) {
- Main m = new Main();
-
obj1.i = 1;
obj2.j = 2;
- synchronized (m) {
+ synchronized (classForSync) {
return obj1.i + obj2.j;
}
}
@@ -539,12 +881,10 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStore(TestClass obj) {
- Main m = new Main();
- synchronized (m) {
+ synchronized (classForSync) {
obj.j = 1;
obj.j = 2;
}
-
return obj.j;
}
@@ -565,13 +905,10 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlocking(TestClass obj) {
- Main m = new Main();
-
// This store must be kept due to the monitor operation.
obj.j = 1;
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.j = 2;
-
return obj.j;
}
@@ -592,13 +929,10 @@ public class Main {
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass obj) {
- Main m = new Main();
-
// This store can be safely removed.
obj.j = 1;
obj.j = 2;
- synchronized (m) {}
-
+ synchronized (classForSync) {}
// This load remains due to the monitor operation.
return obj.j;
}
@@ -622,16 +956,13 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass obj) {
- Main m = new Main();
-
- synchronized (m) {
+ synchronized (classForSync) {
// This store can be removed.
obj.j = 0;
// This store must be kept due to the monitor exit operation.
obj.j = 1;
}
obj.j = 2;
-
return obj.j;
}
@@ -658,13 +989,11 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValues(TestClass obj, boolean b) {
- Main m = new Main();
-
if (b) {
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.i = 1;
} else {
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.i = 2;
}
return obj.i;
@@ -690,6 +1019,102 @@ public class Main {
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass obj, boolean b) {
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ synchronized (classForSync) {}
+ return obj.i;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ synchronized (m) {}
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ synchronized (m) {}
+ obj.j = 2;
+ synchronized (m) {}
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: MonitorOperation kind:enter
+ /// CHECK-DAG: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
Main m = new Main();
if (b) {
@@ -700,4 +1125,75 @@ public class Main {
synchronized (m) {}
return obj.i;
}
+
+ synchronized int $inline$synchronizedSetter(TestClass obj) {
+ obj.j = 1;
+ obj.j = 2;
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) inliner (before)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) inliner (after)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+ static int $noinline$testMonitorOperationInlineSynchronizedMethod(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$synchronizedSetter(obj);
+ }
+
+ int $inline$SetterWithSynchronizedScope(TestClass obj) {
+ synchronized (this) {
+ obj.j = 1;
+ obj.j = 2;
+ return obj.j;
+ }
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) inliner (before)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) inliner (after)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+ static int $noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithSynchronizedScope(obj);
+ }
+
+ static TestClass classForSync;
+ volatile int vi;
}
diff --git a/test/2244-checker-remove-try-boundary/src/Main.java b/test/2244-checker-remove-try-boundary/src/Main.java
index 65c40c5daa..1b616a5ecc 100644
--- a/test/2244-checker-remove-try-boundary/src/Main.java
+++ b/test/2244-checker-remove-try-boundary/src/Main.java
@@ -158,30 +158,29 @@ public class Main {
}
// The throw gets eliminated by `SimplifyIfs` in DCE, so we can detect that nothing can throw in
- // the graph and eliminate the `TryBoundary` instructions. It does so in `after_gvn` since it
- // requires the VisitIf optimization which happens later in the graph.
+ // the graph and eliminate the `TryBoundary` instructions.
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before)
/// CHECK: Throw
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before)
/// CHECK: TryBoundary
/// CHECK: TryBoundary
/// CHECK: TryBoundary
/// CHECK: TryBoundary
/// CHECK-NOT: TryBoundary
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before)
/// CHECK: flags "catch_block"
/// CHECK-NOT: flags "catch_block"
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after)
/// CHECK-NOT: Throw
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after)
/// CHECK-NOT: TryBoundary
- /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after)
/// CHECK-NOT: flags "catch_block"
public static int $noinline$testOptimizeAfterOneBranchDisappears(int a, boolean val) {
try {
diff --git a/test/2247-checker-write-barrier-elimination/src/Main.java b/test/2247-checker-write-barrier-elimination/src/Main.java
index 76fb05a2c0..c03ada30b5 100644
--- a/test/2247-checker-write-barrier-elimination/src/Main.java
+++ b/test/2247-checker-write-barrier-elimination/src/Main.java
@@ -50,8 +50,8 @@ public class Main {
// instructions that can throw.
$noinline$testInstanceFieldSetsBlocked(
new Main(), new Object(), new Object(), new Object());
- $noinline$testStaticFieldSetsBlocked(new Object(), new Object(), new Object());
- $noinline$testArraySetsSameRTIBlocked();
+ $noinline$testStaticFieldSetsBlocked(new Main(), new Object(), new Object(), new Object());
+ $noinline$testArraySetsSameRTIBlocked(new Main());
}
/// CHECK-START: Main Main.$noinline$testInstanceFieldSets(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
@@ -273,46 +273,45 @@ public class Main {
return m;
}
- /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+ /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
/// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitWithNullCheck
/// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
/// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitWithNullCheck
/// CHECK: MonitorOperation kind:enter
/// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:EmitWithNullCheck
- /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+ /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK-NOT: ; card_table
- private static void $noinline$testStaticFieldSetsBlocked(Object o, Object o2, Object o3) {
+ private static void $noinline$testStaticFieldSetsBlocked(
+ Main m, Object o, Object o2, Object o3) {
inner_static = o;
$noinline$emptyMethod();
inner_static2 = o2;
- Main m = new Main();
synchronized (m) {
inner_static3 = o3;
}
}
- /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked() disassembly (after)
+ /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
/// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
/// CHECK: MonitorOperation kind:enter
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
- /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked() disassembly (after)
+ /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK-NOT: ; card_table
- private static java.lang.Object[] $noinline$testArraySetsSameRTIBlocked() {
+ private static java.lang.Object[] $noinline$testArraySetsSameRTIBlocked(Main m) {
Object[] arr = new Object[3];
arr[0] = inner_static;
$noinline$emptyMethod();
arr[1] = inner_static2;
- Main m = new Main();
synchronized (m) {
arr[2] = inner_static3;
}
diff --git a/test/2271-profile-inline-cache/src/Main.java b/test/2271-profile-inline-cache/src/Main.java
index 81ba535154..a95d4acd91 100644
--- a/test/2271-profile-inline-cache/src/Main.java
+++ b/test/2271-profile-inline-cache/src/Main.java
@@ -21,6 +21,12 @@ import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
+ private static File sFile = null;
+ private static Method sMethod1 = null;
+ private static Method sMethod2 = null;
+ private static Method sMethod3 = null;
+ private static Method sMethod4 = null;
+
public static void main(String[] args) throws Exception {
System.loadLibrary(args[0]);
@@ -29,69 +35,84 @@ public class Main {
return;
}
- File file = null;
- try {
- file = createTempFile();
- String codePath = System.getenv("DEX_LOCATION") + "/2271-profile-inline-cache.jar";
- VMRuntime.registerAppInfo("test.app", file.getPath(), file.getPath(),
- new String[] {codePath}, VMRuntime.CODE_PATH_TYPE_PRIMARY_APK);
-
- Derived1 derived1 = new Derived1();
- Derived2 derived2 = new Derived2();
-
- // This method is below the inline cache threshold.
- Method method1 = Main.class.getDeclaredMethod("$noinline$method1", Base.class);
- ensureJitBaselineCompiled(method1);
- // The baseline code doesn't update the inline cache if we are marking. Force a GC now
- // so that GC will unlikely take place during the method calls below.
- Runtime.getRuntime().gc();
+ sMethod1 = Main.class.getDeclaredMethod("$noinline$method1", Base.class);
+ sMethod2 = Main.class.getDeclaredMethod("$noinline$method2", Base.class);
+ sMethod3 = Main.class.getDeclaredMethod("$noinline$method3", Base.class);
+ sMethod4 = Main.class.getDeclaredMethod("$noinline$method4", Base.class);
+
+ sFile = createTempFile();
+ sFile.deleteOnExit();
+ String codePath = System.getenv("DEX_LOCATION") + "/2271-profile-inline-cache.jar";
+ VMRuntime.registerAppInfo("test.app", sFile.getPath(), sFile.getPath(),
+ new String[] {codePath}, VMRuntime.CODE_PATH_TYPE_PRIMARY_APK);
+
+ for (int i = 0; i < 10; i++) {
+ try {
+ test();
+ return;
+ } catch (ScopedAssertNoGc.NoGcAssertionFailure e) {
+ // This should rarely happen. When it happens, reset the state, delete the profile,
+ // and try again.
+ reset();
+ sFile.delete();
+ }
+ }
+
+ // The possibility of hitting this line only exists in theory, unless the test is wrong.
+ throw new RuntimeException("NoGcAssertionFailure occurred 10 times");
+ }
+
+ private static void test() throws Exception {
+ Derived1 derived1 = new Derived1();
+ Derived2 derived2 = new Derived2();
+
+ // This method is below the inline cache threshold.
+ ensureJitBaselineCompiled(sMethod1);
+ try (ScopedAssertNoGc noGc = new ScopedAssertNoGc()) {
$noinline$method1(derived1);
for (int i = 0; i < 2998; i++) {
$noinline$method1(derived2);
}
- checkMethodHasNoInlineCache(file, method1);
-
- // This method is right on the inline cache threshold.
- Method method2 = Main.class.getDeclaredMethod("$noinline$method2", Base.class);
- ensureJitBaselineCompiled(method2);
- // The baseline code doesn't update the inline cache if we are marking. Force a GC now
- // so that GC will unlikely take place during the method calls below.
- Runtime.getRuntime().gc();
+ }
+ checkMethodHasNoInlineCache(sFile, sMethod1);
+
+ // This method is right on the inline cache threshold.
+ ensureJitBaselineCompiled(sMethod2);
+ try (ScopedAssertNoGc noGc = new ScopedAssertNoGc()) {
$noinline$method2(derived1);
for (int i = 0; i < 2999; i++) {
$noinline$method2(derived2);
}
- checkMethodHasInlineCache(file, method2, Derived1.class, Derived2.class);
-
- // This method is above the inline cache threshold.
- Method method3 = Main.class.getDeclaredMethod("$noinline$method3", Base.class);
- ensureJitBaselineCompiled(method3);
- // The baseline code doesn't update the inline cache if we are marking. Force a GC now
- // so that GC will unlikely take place during the method calls below.
- Runtime.getRuntime().gc();
+ }
+ checkMethodHasInlineCache(sFile, sMethod2, Derived1.class, Derived2.class);
+
+ // This method is above the inline cache threshold.
+ ensureJitBaselineCompiled(sMethod3);
+ try (ScopedAssertNoGc noGc = new ScopedAssertNoGc()) {
for (int i = 0; i < 10000; i++) {
$noinline$method3(derived1);
}
for (int i = 0; i < 10000; i++) {
$noinline$method3(derived2);
}
- checkMethodHasInlineCache(file, method3, Derived1.class, Derived2.class);
-
- // This method is above the JIT threshold.
- Method method4 = Main.class.getDeclaredMethod("$noinline$method4", Base.class);
- ensureJitBaselineCompiled(method4);
- // The baseline code doesn't update the inline cache if we are marking. Force a GC now
- // so that GC will unlikely take place during the method calls below.
- Runtime.getRuntime().gc();
+ }
+ checkMethodHasInlineCache(sFile, sMethod3, Derived1.class, Derived2.class);
+
+ // This method is above the JIT threshold.
+ ensureJitBaselineCompiled(sMethod4);
+ try (ScopedAssertNoGc noGc = new ScopedAssertNoGc()) {
$noinline$method4(derived1);
$noinline$method4(derived2);
- ensureMethodJitCompiled(method4);
- checkMethodHasInlineCache(file, method4, Derived1.class, Derived2.class);
- } finally {
- if (file != null) {
- file.delete();
- }
}
+ ensureMethodJitCompiled(sMethod4);
+ checkMethodHasInlineCache(sFile, sMethod4, Derived1.class, Derived2.class);
+ }
+
+ private static void reset() {
+ removeJitCompiledMethod(sMethod1, false /* releaseMemory */);
+ removeJitCompiledMethod(sMethod2, false /* releaseMemory */);
+ removeJitCompiledMethod(sMethod3, false /* releaseMemory */);
+ removeJitCompiledMethod(sMethod4, false /* releaseMemory */);
}
public static void $noinline$method1(Base obj) {
@@ -152,6 +173,8 @@ public class Main {
public static native boolean hasInlineCacheInProfile(
String profile, Method method, Class<?>... targetTypes);
public static native boolean hasJit();
+ public static native int getCurrentGcNum();
+ public static native boolean removeJitCompiledMethod(Method method, boolean releaseMemory);
private static final String TEMP_FILE_NAME_PREFIX = "temp";
private static final String TEMP_FILE_NAME_SUFFIX = "-file";
@@ -170,13 +193,6 @@ public class Main {
}
}
- private static void sleep(long millis) {
- try {
- Thread.sleep(millis);
- } catch (InterruptedException ignored) {
- }
- }
-
private static class VMRuntime {
public static final int CODE_PATH_TYPE_PRIMARY_APK = 1 << 0;
private static final Method registerAppInfoMethod;
@@ -197,4 +213,37 @@ public class Main {
null, packageName, curProfile, refProfile, codePaths, codePathsType);
}
}
+
+ // This scope is intended to guard code that doesn't expect GC to take place. Because we can't
+ // really prevent GC in Java code (calling a native method that enters a GCCriticalSection will
+ // cause the runtime to hang forever when transitioning from native back to Java), this is a
+ // workaround that forces a GC at the beginning so that GC will unlikely take place within the
+ // scope. If a GC still takes place within the scope, this will throw NoGcAssertionFailure.
+ //
+ // The baseline code doesn't update the inline cache if we are marking, so we use this scope to
+ // guard calls to virtual methods for which we want inline cache to be updated.
+ private static class ScopedAssertNoGc implements AutoCloseable {
+ private final int mLastGcNum;
+
+ public ScopedAssertNoGc() {
+ System.gc();
+ mLastGcNum = getCurrentGcNum();
+ }
+
+ @Override
+ public void close() throws NoGcAssertionFailure {
+ int currentGcNum = getCurrentGcNum();
+ if (currentGcNum != mLastGcNum) {
+ throw new NoGcAssertionFailure(
+ String.format("GC happened within the scope (before: %d, after: %d)",
+ mLastGcNum, currentGcNum));
+ }
+ }
+
+ public static class NoGcAssertionFailure extends Exception {
+ public NoGcAssertionFailure(String message) {
+ super(message);
+ }
+ }
+ }
}
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 4539fae097..7c6d6091ee 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -1551,21 +1551,20 @@ public class Main {
return (double) imm;
}
- /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding$after_gvn (before)
- /// CHECK-DAG: Add
- /// CHECK-DAG: Shl
+ /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before)
/// CHECK-DAG: Add
+ /// CHECK-DAG: Mul
- /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding$after_gvn (before)
+ /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before)
/// CHECK-NOT: IntConstant 6
- /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after)
/// CHECK-NOT: Add
- /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding$after_gvn (after)
- /// CHECK-NOT: Shl
+ /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after)
+ /// CHECK-NOT: Mul
- /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after)
/// CHECK-DAG: <<Const:i\d+>> IntConstant 6
/// CHECK-DAG: Return [<<Const>>]
private static int $inline$SpecialCaseForZeroInt(int value) {
@@ -1575,21 +1574,20 @@ public class Main {
return value;
}
- /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding$after_gvn (before)
- /// CHECK-DAG: Add
- /// CHECK-DAG: Shl
+ /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before)
/// CHECK-DAG: Add
+ /// CHECK-DAG: Mul
- /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding$after_gvn (before)
+ /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before)
/// CHECK-NOT: LongConstant 6
- /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after)
/// CHECK-NOT: Add
- /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding$after_gvn (after)
- /// CHECK-NOT: Shl
+ /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after)
+ /// CHECK-NOT: Mul
- /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after)
/// CHECK-DAG: <<Const:j\d+>> LongConstant 6
/// CHECK-DAG: Return [<<Const>>]
private static long $inline$SpecialCaseForZeroLong(long value) {
@@ -1599,14 +1597,14 @@ public class Main {
return value;
}
- /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding$after_gvn (before)
+ /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (before)
/// CHECK-DAG: Add
/// CHECK-DAG: Mul
- /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding$after_gvn (after)
+ /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (after)
/// CHECK-NOT: FloatConstant 6
- /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding$after_gvn (after)
+ /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (after)
/// CHECK-DAG: Add
/// CHECK-DAG: Mul
private static float $noinline$SpecialCaseForZeroFloat(float value) {
@@ -1616,14 +1614,14 @@ public class Main {
return value;
}
- /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding$after_gvn (before)
+ /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (before)
/// CHECK-DAG: Add
/// CHECK-DAG: Mul
- /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding$after_gvn (after)
+ /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (after)
/// CHECK-NOT: DoubleConstant 6
- /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding$after_gvn (after)
+ /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (after)
/// CHECK-DAG: Add
/// CHECK-DAG: Mul
private static double $noinline$SpecialCaseForZeroDouble(double value) {
@@ -1634,17 +1632,17 @@ public class Main {
}
// Note that we have Add instead of sub since internally we do `Add(value, -1)`.
- /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (before)
/// CHECK-DAG: Add
/// CHECK-DAG: Div
- /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after)
/// CHECK-NOT: Add
- /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after)
/// CHECK-NOT: Div
- /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after)
/// CHECK-DAG: <<Const:i\d+>> IntConstant 1
/// CHECK-DAG: Return [<<Const>>]
private static int $noinline$NotEqualsPropagationInt(int value) {
@@ -1655,17 +1653,17 @@ public class Main {
}
}
- /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding$after_gvn (before)
+ /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (before)
/// CHECK-DAG: Sub
/// CHECK-DAG: Div
- /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after)
/// CHECK-NOT: Sub
- /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after)
/// CHECK-NOT: Div
- /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after)
/// CHECK-DAG: <<Const:j\d+>> LongConstant 1
/// CHECK-DAG: Return [<<Const>>]
private static long $noinline$NotEqualsPropagationLong(long value) {
@@ -1676,13 +1674,13 @@ public class Main {
}
}
- /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding$after_gvn (before)
+ /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (before)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
- /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding$after_gvn (after)
+ /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (after)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
private static float $noinline$NotEqualsPropagationFloat(float value) {
if (value != 3F) {
return value;
@@ -1691,13 +1689,13 @@ public class Main {
}
}
- /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding$after_gvn (before)
+ /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (before)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
- /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding$after_gvn (after)
+ /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (after)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
private static double $noinline$NotEqualsPropagationDouble(double value) {
if (value != 3D) {
return value;
@@ -1706,46 +1704,32 @@ public class Main {
}
}
- /// CHECK-START: int Main.$noinline$InlineCalleeWithSpecialCaseForZeroInt(int) constant_folding$after_gvn (before)
- /// CHECK-DAG: Add
- /// CHECK-DAG: Shl
- /// CHECK-DAG: Add
-
- /// CHECK-START: int Main.$noinline$InlineCalleeWithSpecialCaseForZeroInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after)
/// CHECK-NOT: Add
- /// CHECK-START: int Main.$noinline$InlineCalleeWithSpecialCaseForZeroInt(int) constant_folding$after_gvn (after)
- /// CHECK-NOT: Shl
+ /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after)
+ /// CHECK-NOT: Mul
- /// CHECK-START: int Main.$noinline$InlineCalleeWithSpecialCaseForZeroInt(int) dead_code_elimination$after_gvn (after)
- /// CHECK-DAG: <<Param:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const6:i\d+>> IntConstant 6
- /// CHECK-DAG: Return [<<Param>>]
- /// CHECK-DAG: Return [<<Const6>>]
- private static int $noinline$InlineCalleeWithSpecialCaseForZeroInt(int value) {
+ /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 6
+ /// CHECK-DAG: Return [<<Const>>]
+ private static int $noinline$InlineCaleeWithSpecialCaseForZeroInt(int value) {
if (value == 0) {
return $inline$SpecialCaseForZeroInt(value);
}
return value;
}
- /// CHECK-START: long Main.$noinline$InlineCalleeWithSpecialCaseForZeroLong(long) constant_folding$after_gvn (before)
- /// CHECK-DAG: Add
- /// CHECK-DAG: Shl
- /// CHECK-DAG: Add
-
- /// CHECK-START: long Main.$noinline$InlineCalleeWithSpecialCaseForZeroLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after)
/// CHECK-NOT: Add
- /// CHECK-START: long Main.$noinline$InlineCalleeWithSpecialCaseForZeroLong(long) constant_folding$after_gvn (after)
- /// CHECK-NOT: Shl
+ /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after)
+ /// CHECK-NOT: Mul
- /// CHECK-START: long Main.$noinline$InlineCalleeWithSpecialCaseForZeroLong(long) dead_code_elimination$after_gvn (after)
- /// CHECK-DAG: <<Param:j\d+>> ParameterValue
- /// CHECK-DAG: <<Const6:j\d+>> LongConstant 6
- /// CHECK-DAG: Return [<<Param>>]
- /// CHECK-DAG: Return [<<Const6>>]
- private static long $noinline$InlineCalleeWithSpecialCaseForZeroLong(long value) {
+ /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after)
+ /// CHECK-DAG: <<Const:j\d+>> LongConstant 6
+ /// CHECK-DAG: Return [<<Const>>]
+ private static long $noinline$InlineCaleeWithSpecialCaseForZeroLong(long value) {
if (value == 0L) {
return $inline$SpecialCaseForZeroLong(value);
}
@@ -1754,11 +1738,11 @@ public class Main {
// Check that don't propagate the value == 3 on `if not true` branch, as the `if true` branch also
// flows into the same block.
- /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (before)
/// CHECK-DAG: Add
/// CHECK-DAG: Div
- /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (after)
/// CHECK-DAG: Add
/// CHECK-DAG: Div
private static int $noinline$NotEqualsImplicitElseInt(int value) {
@@ -1768,11 +1752,11 @@ public class Main {
return (value - 1) / 2;
}
- /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding$after_gvn (before)
+ /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (before)
/// CHECK-DAG: Sub
/// CHECK-DAG: Div
- /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding$after_gvn (after)
+ /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (after)
/// CHECK-DAG: Sub
/// CHECK-DAG: Div
private static long $noinline$NotEqualsImplicitElseLong(long value) {
@@ -1782,13 +1766,13 @@ public class Main {
return (value - 1L) / 2L;
}
- /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding$after_gvn (before)
+ /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (before)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
- /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding$after_gvn (after)
+ /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (after)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
private static float $noinline$NotEqualsImplicitElseFloat(float value) {
if (value != 3F) {
value += 1F;
@@ -1796,13 +1780,13 @@ public class Main {
return (value - 1F) / 2F;
}
- /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding$after_gvn (before)
+ /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (before)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
- /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding$after_gvn (after)
+ /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (after)
/// CHECK-DAG: Sub
- /// CHECK-DAG: Mul
+ /// CHECK-DAG: Div
private static double $noinline$NotEqualsImplicitElseDouble(double value) {
if (value != 3D) {
value += 1D;
@@ -1810,39 +1794,37 @@ public class Main {
return (value - 1D) / 2D;
}
- // By propagating the boolean we can eliminate some equality comparisons as we already know their
+ // By propagating the boolean we can elimniate some equality comparisons as we already know their
// result. In turn, we also enable DeadCodeElimination to eliminate more code.
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) constant_folding$after_gvn (before)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Param>>]
- /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Param>>]
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (before)
+ /// CHECK-DAG: Equal
+ /// CHECK-DAG: Equal
+ /// CHECK-DAG: Equal
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) constant_folding$after_gvn (after)
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Const0>>]
- /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Const1>>]
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (after)
+ /// CHECK: Equal
+ /// CHECK-NOT: Equal
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) dead_code_elimination$after_gvn (before)
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (before)
/// CHECK-DAG: IntConstant 1
/// CHECK-DAG: IntConstant 2
/// CHECK-DAG: IntConstant 3
/// CHECK-DAG: IntConstant 4
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after)
/// CHECK-DAG: IntConstant 1
/// CHECK-DAG: IntConstant 4
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after)
/// CHECK-NOT: IntConstant 2
- /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean, int) dead_code_elimination$after_gvn (after)
+ /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after)
/// CHECK-NOT: IntConstant 3
- private static int $noinline$PropagatingParameterValue(boolean value, int initial_value) {
+ private static int $noinline$PropagatingParameterValue(boolean value) {
if (value) {
- return value ? initial_value + 1 : initial_value + 2;
+ return value ? 1 : 2;
} else {
- return value ? initial_value + 3 : initial_value + 4;
+ return value ? 3 : 4;
}
}
@@ -1980,7 +1962,7 @@ public class Main {
// Tests for propagating known values due to if clauses.
// Propagating within the same method. These are marked $inline$ since we used them in
- // `InlineCalleeWithSpecialCaseForZeroInt`.
+ // `InlineCaleeWithSpecialCaseForZeroInt`.
assertIntEquals(6, $inline$SpecialCaseForZeroInt(0));
assertIntEquals(3, $inline$SpecialCaseForZeroInt(3));
assertLongEquals(6L, $inline$SpecialCaseForZeroLong(0L));
@@ -2003,10 +1985,10 @@ public class Main {
assertDoubleEquals(1D, $noinline$NotEqualsPropagationDouble(3D));
// Propagating so that the inliner can use it.
- assertIntEquals(6, $noinline$InlineCalleeWithSpecialCaseForZeroInt(0));
- assertIntEquals(3, $noinline$InlineCalleeWithSpecialCaseForZeroInt(3));
- assertLongEquals(6L, $noinline$InlineCalleeWithSpecialCaseForZeroLong(0L));
- assertLongEquals(3L, $noinline$InlineCalleeWithSpecialCaseForZeroLong(3L));
+ assertIntEquals(6, $noinline$InlineCaleeWithSpecialCaseForZeroInt(0));
+ assertIntEquals(3, $noinline$InlineCaleeWithSpecialCaseForZeroInt(3));
+ assertLongEquals(6L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(0L));
+ assertLongEquals(3L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(3L));
// Propagating within the same method, with not equals
assertIntEquals(0, $noinline$NotEqualsImplicitElseInt(0));
@@ -2019,8 +2001,8 @@ public class Main {
assertDoubleEquals(1D, $noinline$NotEqualsImplicitElseDouble(3D));
// Propagating parameters.
- assertIntEquals(1, $noinline$PropagatingParameterValue(true, 0));
- assertIntEquals(4, $noinline$PropagatingParameterValue(false, 0));
+ assertIntEquals(1, $noinline$PropagatingParameterValue(true));
+ assertIntEquals(4, $noinline$PropagatingParameterValue(false));
}
Main() throws ClassNotFoundException {
diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali
index 5290bad3ed..3e7bca93c9 100644
--- a/test/485-checker-dce-loop-update/smali/TestCase.smali
+++ b/test/485-checker-dce-loop-update/smali/TestCase.smali
@@ -224,7 +224,7 @@
## CHECK-DAG: If [<<ArgY>>] loop:<<HeaderY>>
#
# ### Inner loop ###
-## CHECK-DAG: <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<XorZ>>] loop:<<HeaderZ:B\d+>>
+## CHECK-DAG: <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<Cst0>>] loop:<<HeaderZ:B\d+>>
## CHECK-DAG: <<XorZ>> Xor [<<PhiZ2>>,<<Cst1>>] loop:<<HeaderZ>>
## CHECK-DAG: <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>] loop:<<HeaderZ>>
## CHECK-DAG: If [<<CondZ>>] loop:<<HeaderZ>>
@@ -246,8 +246,8 @@
## CHECK-DAG: <<Add7>> Add [<<PhiX>>,<<Cst7>>] loop:<<HeaderY>>
#
# ### Inner loop ###
-## CHECK-DAG: <<PhiZ:i\d+>> Phi [<<ArgZ>>,<<XorZ:i\d+>>] loop:<<HeaderZ:B\d+>>
-## CHECK-DAG: <<XorZ>> Xor [<<PhiZ>>,<<Cst1>>] loop:<<HeaderZ>>
+## CHECK-DAG: <<PhiZ:i\d+>> Phi [<<ArgZ>>,<<Cst0>>] loop:<<HeaderZ:B\d+>>
+## CHECK-DAG: <<XorZ:i\d+>> Xor [<<PhiZ>>,<<Cst1>>] loop:<<HeaderZ>>
## CHECK-DAG: <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>] loop:<<HeaderZ>>
## CHECK-DAG: If [<<CondZ>>] loop:<<HeaderZ>>
#
diff --git a/test/543-checker-dce-trycatch/smali/TestCase.smali b/test/543-checker-dce-trycatch/smali/TestCase.smali
index 7ad9ba8e64..15eaabbc04 100644
--- a/test/543-checker-dce-trycatch/smali/TestCase.smali
+++ b/test/543-checker-dce-trycatch/smali/TestCase.smali
@@ -206,6 +206,7 @@
## CHECK-START: int TestCase.testCatchPhiInputs_DefinedInTryBlock(int, int, int, int) dead_code_elimination$after_inlining (before)
## CHECK-DAG: <<Arg0:i\d+>> ParameterValue
## CHECK-DAG: <<Arg1:i\d+>> ParameterValue
+## CHECK-DAG: <<Const0x0:i\d+>> IntConstant 0
## CHECK-DAG: <<Const0xa:i\d+>> IntConstant 10
## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11
## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12
@@ -215,7 +216,7 @@
## CHECK-DAG: <<Const0x10:i\d+>> IntConstant 16
## CHECK-DAG: <<Const0x11:i\d+>> IntConstant 17
## CHECK-DAG: <<Add:i\d+>> Add [<<Arg0>>,<<Arg1>>]
-## CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Const0xf>>] reg:3 is_catch_phi:false
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0x0>>,<<Const0xf>>] reg:3 is_catch_phi:false
## CHECK-DAG: Phi [<<Const0xa>>,<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true
## CHECK-DAG: Phi [<<Add>>,<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true
## CHECK-DAG: Phi [<<Phi>>,<<Const0x10>>,<<Const0x11>>] reg:3 is_catch_phi:true
@@ -248,7 +249,8 @@
if-eqz v3, :define_phi
const v3, 0xf
:define_phi
- # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi)
+ # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi).
+ # Note that the Add has to be equal to 0 since we do `if-eqz v3`
div-int/2addr p0, v2
:else
diff --git a/test/708-jit-cache-churn/jit.cc b/test/708-jit-cache-churn/jit.cc
deleted file mode 100644
index 1b80eb3c0c..0000000000
--- a/test/708-jit-cache-churn/jit.cc
+++ /dev/null
@@ -1,56 +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 "jni.h"
-
-#include "art_method.h"
-#include "jit/jit.h"
-#include "jit/jit_code_cache.h"
-#include "jni/jni_internal.h"
-#include "mirror/class.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread_list.h"
-
-namespace art {
-
-extern "C" JNIEXPORT
-jboolean
-Java_JitCacheChurnTest_removeJitCompiledMethod(JNIEnv* env,
- jclass,
- jobject javaMethod,
- jboolean releaseMemory) {
- if (!Runtime::Current()->UseJitCompilation()) {
- return JNI_FALSE;
- }
-
- jit::Jit* jit = Runtime::Current()->GetJit();
- jit->WaitForCompilationToFinish(Thread::Current());
-
- ScopedObjectAccess soa(env);
- ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
-
- jit::JitCodeCache* code_cache = jit->GetCodeCache();
-
- // Drop the shared mutator lock
- ScopedThreadSuspension selfSuspension(Thread::Current(), art::ThreadState::kNative);
- // Get exclusive mutator lock with suspend all.
- ScopedSuspendAll suspend("Removing JIT compiled method", /*long_suspend*/true);
- bool removed = code_cache->RemoveMethod(method, static_cast<bool>(releaseMemory));
- return removed ? JNI_TRUE : JNI_FALSE;
-}
-
-} // namespace art
diff --git a/test/708-jit-cache-churn/src/JitCacheChurnTest.java b/test/708-jit-cache-churn/src/JitCacheChurnTest.java
index abc5f35f70..8902d8db0f 100644
--- a/test/708-jit-cache-churn/src/JitCacheChurnTest.java
+++ b/test/708-jit-cache-churn/src/JitCacheChurnTest.java
@@ -244,7 +244,7 @@ public class JitCacheChurnTest {
System.err.println(e);
System.exit(-1);
}
- removeJitCompiledMethod(method, false);
+ Main.removeJitCompiledMethod(method, false);
}
private void removeJittedMethods(int mask) {
@@ -274,6 +274,4 @@ public class JitCacheChurnTest {
concurrentExecution.shutdown();
}
}
-
- private static native void removeJitCompiledMethod(Method method, boolean releaseMemory);
}
diff --git a/test/708-jit-cache-churn/src/Main.java b/test/708-jit-cache-churn/src/Main.java
index 0595aae506..4d11dae899 100644
--- a/test/708-jit-cache-churn/src/Main.java
+++ b/test/708-jit-cache-churn/src/Main.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import java.lang.reflect.Method;
+
public class Main {
public static void main(String[] args) throws Exception {
@@ -28,4 +30,5 @@ public class Main {
static native boolean hasJit();
static native void ensureJitCompiled(Class<?> klass, String methodName);
+ static native void removeJitCompiledMethod(Method method, boolean releaseMemory);
}
diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java
index 8e6b75f9a0..56c9364d45 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -262,6 +262,7 @@ public class Test912 {
"java.util.NoSuchElementException",
"java.io.FileNotFoundException", // b/63581208
"java.util.zip.ZipException", // b/63581208
+ "sun.invoke.util.Wrapper", // For "ClassEvents" thread in JIT/no-image config.
};
for (String s : PRELOAD_FOR_JIT) {
Class.forName(s);
diff --git a/test/Android.bp b/test/Android.bp
index fef4d99c2b..00c5f6be89 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -905,7 +905,6 @@ cc_defaults {
"667-jit-jni-stub/jit_jni_stub_test.cc",
"674-hiddenapi/hiddenapi.cc",
"692-vdex-inmem-loader/vdex_inmem_loader.cc",
- "708-jit-cache-churn/jit.cc",
"720-thread-priority/thread_priority.cc",
"800-smali/jni.cc",
"817-hiddenapi/test_native.cc",
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 27f1ebad12..8e0507327e 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -566,4 +566,36 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasInlineCacheInProfile(
return JNI_FALSE;
}
+extern "C" JNIEXPORT jint JNICALL Java_Main_getCurrentGcNum(JNIEnv* env, jclass) {
+ // Prevent any new GC before getting the current GC num.
+ ScopedObjectAccess soa(env);
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ heap->WaitForGcToComplete(gc::kGcCauseJitCodeCache, Thread::Current());
+ return heap->GetCurrentGcNum();
+}
+
+extern "C" JNIEXPORT jboolean Java_Main_removeJitCompiledMethod(JNIEnv* env,
+ jclass,
+ jobject java_method,
+ jboolean release_memory) {
+ if (!Runtime::Current()->UseJitCompilation()) {
+ return JNI_FALSE;
+ }
+
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ jit->WaitForCompilationToFinish(Thread::Current());
+
+ ScopedObjectAccess soa(env);
+ ArtMethod* method = ArtMethod::FromReflectedMethod(soa, java_method);
+
+ jit::JitCodeCache* code_cache = jit->GetCodeCache();
+
+ // Drop the shared mutator lock.
+ ScopedThreadSuspension self_suspension(Thread::Current(), art::ThreadState::kNative);
+ // Get exclusive mutator lock with suspend all.
+ ScopedSuspendAll suspend("Removing JIT compiled method", /*long_suspend=*/true);
+ bool removed = code_cache->RemoveMethod(method, static_cast<bool>(release_memory));
+ return removed ? JNI_TRUE : JNI_FALSE;
+}
+
} // namespace art
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
index 7b120cfcc4..ada2f6bdca 100644
--- a/tools/veridex/Android.bp
+++ b/tools/veridex/Android.bp
@@ -63,3 +63,99 @@ sh_binary_host {
src: "appcompat.sh",
filename_from_src: true,
}
+
+genrule {
+ name: "system_stub_dex_d8_input_jar",
+ srcs: [":system_android_jar"],
+ tools: ["zip2zip"],
+ out: ["system_stub_dex_d8_input.jar"],
+ cmd: "$(location zip2zip) " +
+ "-j -i $(in) " +
+ "-o $(out) \"**/*.class\" ",
+}
+
+genrule {
+ name: "system_stub_dex",
+ srcs: [
+ ":system_stub_dex_d8_input_jar",
+ ],
+ tools: [
+ "d8",
+ ],
+ out: [
+ "dex_dir/classes.dex",
+ "dex_dir/classes2.dex",
+ ],
+ cmd: "mkdir -p $(genDir)/dex_dir &&" +
+ "$(location d8) " +
+ "-JXmx4096M -JXX:+TieredCompilation -JXX:TieredStopAtLevel=1 " +
+ "-JDcom.android.tools.r8.emitRecordAnnotationsInDex " +
+ "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex " +
+ "-JXX:OnError=\"cat hs_err_pid%p.log\" " +
+ "-JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads " +
+ "--output $(genDir)/dex_dir " +
+ "--min-api 1000 " +
+ "$(in)",
+}
+
+genrule {
+ name: "public_oahl_stub_dex_d8_input_jar",
+ srcs: [":public.org.apache.http.legacy.jar"],
+ tools: ["zip2zip"],
+ out: ["oahl_stub_dex_d8_input.jar"],
+ cmd: "$(location zip2zip) " +
+ "-j -i $(in) " +
+ "-o $(out) \"**/*.class\" ",
+}
+
+genrule {
+ name: "public_oahl_stub_dex",
+ srcs: [
+ ":public_oahl_stub_dex_d8_input_jar",
+ ],
+ tools: [
+ "d8",
+ ],
+ out: [
+ "dex_dir/classes.dex",
+ ],
+ cmd: "mkdir -p $(genDir)/dex_dir &&" +
+ "$(location d8) " +
+ "-JXmx4096M -JXX:+TieredCompilation -JXX:TieredStopAtLevel=1 " +
+ "-JDcom.android.tools.r8.emitRecordAnnotationsInDex " +
+ "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex " +
+ "-JXX:OnError=\"cat hs_err_pid%p.log\" " +
+ "-JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads " +
+ "--output $(genDir)/dex_dir " +
+ "--min-api 1000 " +
+ "$(in)",
+}
+
+genrule {
+ name: "veridex_zip",
+ srcs: [
+ "appcompat.sh",
+ ":platform-bootclasspath{hiddenapi-flags.csv}",
+ ":system_stub_dex",
+ ":public_oahl_stub_dex",
+ ],
+ tools: [
+ "soong_zip",
+ "veridex",
+ ],
+ out: ["veridex.zip"],
+ cmd: "mkdir -p $(genDir)/tmp &&" +
+ "ls -1 $(locations :system_stub_dex) | sort > $(genDir)/tmp/system-stubs.zip.list && " +
+ "$(locations soong_zip) -o $(genDir)/tmp/system-stubs.zip" +
+ " -j -l $(genDir)/tmp/system-stubs.zip.list && " +
+ "ls -1 $(locations :public_oahl_stub_dex) | sort > $(genDir)/tmp/org.apache.http.legacy-stubs.zip.list && " +
+ "$(locations soong_zip) -o $(genDir)/tmp/org.apache.http.legacy-stubs.zip " +
+ " -j -l $(genDir)/tmp/org.apache.http.legacy-stubs.zip.list && " +
+ "$(locations soong_zip) -o $(out)" +
+ " -C `dirname $(location appcompat.sh)` -f $(location appcompat.sh)" +
+ " -C `dirname $(location :platform-bootclasspath{hiddenapi-flags.csv})` -f $(location :platform-bootclasspath{hiddenapi-flags.csv})" +
+ " -C `dirname $(location veridex)` -f $(location veridex)" +
+ " -j -f $(genDir)/tmp/system-stubs.zip" +
+ " -j -f $(genDir)/tmp/org.apache.http.legacy-stubs.zip",
+ visibility: ["//visibility:public"],
+}
diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk
index 9ea9b3a5be..3c7a16ded1 100644
--- a/tools/veridex/Android.mk
+++ b/tools/veridex/Android.mk
@@ -15,7 +15,7 @@
#
# TODO(b/172480617): Clean up the platform dependencies on this.
-
+# TODO(b/319389869 : Remove the Android.mk after the meta license be resolved.
LOCAL_PATH := $(call my-dir)
# The veridex tool takes stub dex files as input, so we generate both the system and oahl