summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/debug/elf_debug_info_writer.h9
-rw-r--r--compiler/debug/elf_debug_loc_writer.h6
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc4
-rw-r--r--compiler/dex/dex_to_dex_decompiler_test.cc9
-rw-r--r--compiler/driver/compiler_driver.cc29
-rw-r--r--compiler/driver/compiler_driver_test.cc14
-rw-r--r--compiler/exception_test.cc40
-rw-r--r--compiler/optimizing/code_generator.cc8
-rw-r--r--compiler/optimizing/code_generator_mips.cc3
-rw-r--r--compiler/optimizing/code_generator_mips64.cc3
-rw-r--r--compiler/optimizing/inliner.cc8
-rw-r--r--compiler/optimizing/instruction_simplifier.cc4
-rw-r--r--compiler/optimizing/intrinsics.cc5
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc2
-rw-r--r--compiler/optimizing/nodes.cc21
-rw-r--r--compiler/optimizing/nodes.h5
-rw-r--r--compiler/optimizing/optimizing_compiler.cc4
-rw-r--r--compiler/optimizing/reference_type_propagation.cc23
-rw-r--r--compiler/optimizing/stack_map_stream.cc708
-rw-r--r--compiler/optimizing/stack_map_stream.h240
-rw-r--r--compiler/optimizing/stack_map_test.cc565
-rw-r--r--compiler/optimizing/superblock_cloner.cc154
-rw-r--r--compiler/optimizing/superblock_cloner.h31
-rw-r--r--compiler/verifier_deps_test.cc51
-rw-r--r--dex2oat/dex2oat_test.cc50
-rw-r--r--dex2oat/linker/image_test.cc20
-rw-r--r--dex2oat/linker/image_test.h2
-rw-r--r--dex2oat/linker/image_writer.cc17
-rw-r--r--dex2oat/linker/oat_writer_test.cc3
-rw-r--r--dexdump/Android.bp4
-rw-r--r--dexdump/dexdump.cc5
-rw-r--r--libartbase/base/arena_allocator.cc1
-rw-r--r--libartbase/base/arena_allocator.h1
-rw-r--r--libartbase/base/bit_memory_region.h15
-rw-r--r--libartbase/base/bit_table.h247
-rw-r--r--libartbase/base/bit_table_test.cc131
-rw-r--r--libartbase/base/common_art_test.cc18
-rw-r--r--libartbase/base/common_art_test.h3
-rw-r--r--libartbase/base/file_utils_test.cc8
-rw-r--r--libartbase/base/scoped_arena_containers.h8
-rw-r--r--libdexfile/Android.bp1
-rw-r--r--libdexfile/dex/art_dex_file_loader_test.cc31
-rw-r--r--libdexfile/dex/class_accessor-inl.h131
-rw-r--r--libdexfile/dex/class_accessor.h196
-rw-r--r--libdexfile/dex/class_accessor_test.cc89
-rw-r--r--libdexfile/dex/dex_file.cc17
-rw-r--r--libdexfile/dex/dex_file.h4
-rw-r--r--libprofile/profile/profile_compilation_info_test.cc247
-rw-r--r--oatdump/oatdump.cc218
-rw-r--r--oatdump/oatdump_test.h4
-rw-r--r--openjdkjvm/OpenjdkJvm.cc2
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc15
-rw-r--r--openjdkjvmti/ti_class.cc6
-rw-r--r--openjdkjvmti/ti_class_definition.cc7
-rw-r--r--openjdkjvmti/ti_class_loader.h33
-rw-r--r--openjdkjvmti/ti_field.cc2
-rw-r--r--openjdkjvmti/ti_method.cc2
-rw-r--r--openjdkjvmti/ti_redefine.cc18
-rw-r--r--openjdkjvmti/ti_redefine.h18
-rw-r--r--openjdkjvmti/ti_stack.cc10
-rw-r--r--patchoat/patchoat.cc5
-rw-r--r--profman/boot_image_profile.cc52
-rw-r--r--profman/profile_assistant_test.cc58
-rw-r--r--profman/profman.cc19
-rw-r--r--runtime/Android.bp3
-rw-r--r--runtime/arch/code_offset.h94
-rw-r--r--runtime/arch/stub_test.cc3
-rw-r--r--runtime/art_field-inl.h39
-rw-r--r--runtime/art_field.cc7
-rw-r--r--runtime/art_field.h10
-rw-r--r--runtime/art_method-inl.h8
-rw-r--r--runtime/art_method.cc53
-rw-r--r--runtime/art_method.h2
-rw-r--r--runtime/check_jni.cc8
-rw-r--r--runtime/check_reference_map_visitor.h3
-rw-r--r--runtime/class_linker-inl.h129
-rw-r--r--runtime/class_linker.cc929
-rw-r--r--runtime/class_linker.h232
-rw-r--r--runtime/class_linker_test.cc24
-rw-r--r--runtime/class_root.cc36
-rw-r--r--runtime/class_root.h184
-rw-r--r--runtime/class_table-inl.h1
-rw-r--r--runtime/debug_print.cc2
-rw-r--r--runtime/debugger.cc11
-rw-r--r--runtime/dex/dex_file_annotations.cc73
-rw-r--r--runtime/dex/dex_file_annotations.h18
-rw-r--r--runtime/dex_register_location.h79
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h43
-rw-r--r--runtime/entrypoints/entrypoint_utils.h15
-rw-r--r--runtime/entrypoints/quick/callee_save_frame.h6
-rw-r--r--runtime/entrypoints/quick/quick_alloc_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc3
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc5
-rw-r--r--runtime/gc/accounting/mod_union_table_test.cc4
-rw-r--r--runtime/gc/collector/concurrent_copying.cc5
-rw-r--r--runtime/gc/heap.cc4
-rw-r--r--runtime/gc/heap_verification_test.cc6
-rw-r--r--runtime/gc/reference_processor-inl.h34
-rw-r--r--runtime/gc/reference_processor.cc29
-rw-r--r--runtime/gc/space/space_test.h8
-rw-r--r--runtime/hidden_api_test.cc4
-rw-r--r--runtime/hprof/hprof.cc4
-rw-r--r--runtime/image-inl.h1
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/indirect_reference_table-inl.h4
-rw-r--r--runtime/interpreter/interpreter_common.cc60
-rw-r--r--runtime/interpreter/interpreter_common.h11
-rw-r--r--runtime/interpreter/mterp/arm/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/arm/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/arm/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/arm/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/arm/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/arm/instruction_start_sister.S5
-rw-r--r--runtime/interpreter/mterp/arm64/header.S1
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/arm64/instruction_start_sister.S5
-rwxr-xr-xruntime/interpreter/mterp/gen_mterp.py38
-rw-r--r--runtime/interpreter/mterp/mips/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/mips/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/mips/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/mips/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/mips/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/mips/instruction_start_sister.S5
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/mips64/instruction_start_sister.S5
-rw-r--r--runtime/interpreter/mterp/mterp.cc2
-rw-r--r--runtime/interpreter/mterp/out/mterp_arm.S15
-rw-r--r--runtime/interpreter/mterp/out/mterp_arm64.S16
-rw-r--r--runtime/interpreter/mterp/out/mterp_mips.S15
-rw-r--r--runtime/interpreter/mterp/out/mterp_mips64.S15
-rw-r--r--runtime/interpreter/mterp/out/mterp_x86.S18
-rw-r--r--runtime/interpreter/mterp/out/mterp_x86_64.S18
-rw-r--r--runtime/interpreter/mterp/x86/entry.S1
-rw-r--r--runtime/interpreter/mterp/x86/header.S2
-rw-r--r--runtime/interpreter/mterp/x86/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/x86/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/x86/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/x86/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/x86/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/x86/instruction_start_sister.S5
-rw-r--r--runtime/interpreter/mterp/x86_64/entry.S1
-rw-r--r--runtime/interpreter/mterp/x86_64/header.S2
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_end.S3
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_end_alt.S3
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_end_sister.S3
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_start.S4
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_start_alt.S4
-rw-r--r--runtime/interpreter/mterp/x86_64/instruction_start_sister.S5
-rw-r--r--runtime/interpreter/unstarted_runtime.cc6
-rw-r--r--runtime/interpreter/unstarted_runtime_test.cc33
-rw-r--r--runtime/jit/jit.cc11
-rw-r--r--runtime/jit/jit_code_cache.cc2
-rw-r--r--runtime/jit/profiling_info_test.cc329
-rw-r--r--runtime/jni/jni_internal.cc82
-rw-r--r--runtime/method_handles.cc9
-rw-r--r--runtime/method_handles_test.cc20
-rw-r--r--runtime/mirror/array-inl.h48
-rw-r--r--runtime/mirror/array.cc56
-rw-r--r--runtime/mirror/array.h40
-rw-r--r--runtime/mirror/call_site.cc27
-rw-r--r--runtime/mirror/call_site.h10
-rw-r--r--runtime/mirror/class-inl.h72
-rw-r--r--runtime/mirror/class.cc62
-rw-r--r--runtime/mirror/class.h41
-rw-r--r--runtime/mirror/class_ext.cc24
-rw-r--r--runtime/mirror/class_ext.h7
-rw-r--r--runtime/mirror/dex_cache-inl.h2
-rw-r--r--runtime/mirror/dex_cache.h1
-rw-r--r--runtime/mirror/emulated_stack_frame.cc24
-rw-r--r--runtime/mirror/emulated_stack_frame.h10
-rw-r--r--runtime/mirror/executable.h1
-rw-r--r--runtime/mirror/field-inl.h3
-rw-r--r--runtime/mirror/field.cc30
-rw-r--r--runtime/mirror/field.h20
-rw-r--r--runtime/mirror/method.cc66
-rw-r--r--runtime/mirror/method.h43
-rw-r--r--runtime/mirror/method_handle_impl.cc33
-rw-r--r--runtime/mirror/method_handle_impl.h10
-rw-r--r--runtime/mirror/method_handles_lookup.cc26
-rw-r--r--runtime/mirror/method_handles_lookup.h11
-rw-r--r--runtime/mirror/method_type.cc25
-rw-r--r--runtime/mirror/method_type.h10
-rw-r--r--runtime/mirror/method_type_test.cc5
-rw-r--r--runtime/mirror/object-inl.h113
-rw-r--r--runtime/mirror/object.cc2
-rw-r--r--runtime/mirror/object.h196
-rw-r--r--runtime/mirror/object_array-inl.h27
-rw-r--r--runtime/mirror/object_array.h16
-rw-r--r--runtime/mirror/object_test.cc36
-rw-r--r--runtime/mirror/reference-inl.h7
-rw-r--r--runtime/mirror/reference.cc43
-rw-r--r--runtime/mirror/reference.h10
-rw-r--r--runtime/mirror/stack_trace_element.cc22
-rw-r--r--runtime/mirror/stack_trace_element.h12
-rw-r--r--runtime/mirror/string-inl.h21
-rw-r--r--runtime/mirror/string.cc20
-rw-r--r--runtime/mirror/string.h30
-rw-r--r--runtime/mirror/throwable.cc21
-rw-r--r--runtime/mirror/throwable.h13
-rw-r--r--runtime/mirror/var_handle.cc158
-rw-r--r--runtime/mirror/var_handle.h51
-rw-r--r--runtime/mirror/var_handle_test.cc49
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc33
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc2
-rw-r--r--runtime/native/java_lang_Class.cc58
-rw-r--r--runtime/native/java_lang_Object.cc6
-rw-r--r--runtime/native/java_lang_StringFactory.cc2
-rw-r--r--runtime/native/java_lang_Thread.cc9
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc13
-rw-r--r--runtime/native/java_lang_reflect_Array.cc11
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc10
-rw-r--r--runtime/native/java_lang_reflect_Executable.cc18
-rw-r--r--runtime/native/java_lang_reflect_Field.cc5
-rw-r--r--runtime/native/java_lang_reflect_Method.cc11
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/proxy_test.cc14
-rw-r--r--runtime/proxy_test.h41
-rw-r--r--runtime/quick_exception_handler.cc30
-rw-r--r--runtime/reference_table_test.cc21
-rw-r--r--runtime/reflection-inl.h2
-rw-r--r--runtime/reflection.cc2
-rw-r--r--runtime/reflection_test.cc4
-rw-r--r--runtime/runtime.cc36
-rw-r--r--runtime/stack.cc16
-rw-r--r--runtime/stack_map.cc240
-rw-r--r--runtime/stack_map.h898
-rw-r--r--runtime/thread.cc41
-rw-r--r--runtime/transaction_test.cc2
-rw-r--r--runtime/vdex_file.cc40
-rw-r--r--runtime/verifier/method_verifier.cc211
-rw-r--r--runtime/verifier/method_verifier.h21
-rw-r--r--runtime/verifier/method_verifier_test.cc2
-rw-r--r--runtime/verifier/reg_type.cc104
-rw-r--r--runtime/verifier/reg_type.h100
-rw-r--r--runtime/verifier/reg_type_cache-inl.h24
-rw-r--r--runtime/verifier/reg_type_cache.cc34
-rw-r--r--runtime/verifier/reg_type_cache.h18
-rw-r--r--runtime/verifier/verifier_deps.cc45
-rw-r--r--runtime/verifier/verifier_deps.h20
-rw-r--r--runtime/well_known_classes.cc31
-rw-r--r--runtime/well_known_classes.h10
-rw-r--r--test/137-cfi/cfi.cc5
-rw-r--r--test/166-bad-interface-super/build13
-rw-r--r--test/166-bad-interface-super/smali/BadSuper1.smali (renamed from test/476-checker-ctor-fence-redun-elim/build)11
-rw-r--r--[-rwxr-xr-x]test/166-bad-interface-super/smali/BadSuper2.smali (renamed from test/458-checker-instruct-simplification/build)11
-rwxr-xr-xtest/450-checker-types/build20
-rw-r--r--test/458-checker-instruct-simplification/smali/SmaliTests2.smali305
-rw-r--r--test/458-checker-instruct-simplification/src/Main.java200
-rwxr-xr-xtest/463-checker-boolean-simplifier/build20
-rw-r--r--test/463-checker-boolean-simplifier/smali/Main2.smali308
-rw-r--r--test/463-checker-boolean-simplifier/src-art/Main.java280
-rw-r--r--test/463-checker-boolean-simplifier/src/Main.java398
-rw-r--r--test/497-inlining-and-class-loader/clear_dex_cache.cc4
-rwxr-xr-xtest/530-checker-lse/build20
-rw-r--r--test/530-checker-lse/smali/Main.smali260
-rw-r--r--test/530-checker-lse/src/Main.java130
-rw-r--r--test/530-checker-peel-unroll/src/Main.java235
-rw-r--r--test/549-checker-types-merge/build20
-rw-r--r--test/567-checker-compare/build20
-rw-r--r--test/910-methods/build20
-rw-r--r--test/911-get-stack-trace/check31
-rw-r--r--test/911-get-stack-trace/expected.txt366
-rw-r--r--test/911-get-stack-trace/expected_d8.diff456
-rw-r--r--test/911-get-stack-trace/src/art/AllTraces.java2
-rw-r--r--test/911-get-stack-trace/src/art/OtherThread.java4
-rw-r--r--test/911-get-stack-trace/src/art/ThreadListTraces.java2
-rw-r--r--test/913-heaps/check2
-rw-r--r--test/dexdump/invoke-custom.dexbin8984 -> 31732 bytes
-rw-r--r--test/dexdump/invoke-custom.lst178
-rw-r--r--test/dexdump/invoke-custom.txt6610
-rw-r--r--test/dexdump/invoke-custom.xml844
-rwxr-xr-xtest/dexdump/run-all-tests92
-rwxr-xr-xtest/etc/default-build3
-rwxr-xr-xtest/run-test5
-rwxr-xr-xtest/testrunner/testrunner.py18
-rw-r--r--tools/build/var_list1
-rwxr-xr-xtools/buildbot-build.sh6
-rwxr-xr-xtools/cleanup-buildbot-device.sh2
-rwxr-xr-xtools/common/common.py8
-rw-r--r--tools/dexanalyze/dexanalyze.cc44
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.cc295
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.h55
-rwxr-xr-xtools/golem/build-target.sh2
-rw-r--r--tools/jfuzz/README.md10
-rwxr-xr-xtools/jfuzz/run_dex_fuzz_test.py14
-rwxr-xr-xtools/jfuzz/run_jfuzz_test.py8
-rwxr-xr-xtools/run-jdwp-tests.sh35
-rwxr-xr-xtools/run-libcore-tests.sh30
-rwxr-xr-xtools/teardown-buildbot-device.sh40
-rw-r--r--tools/veridex/Android.bp7
-rw-r--r--tools/veridex/Android.mk40
-rwxr-xr-xtools/veridex/appcompat.sh27
300 files changed, 13011 insertions, 8878 deletions
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 87e679fbea..f2002a0af6 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -204,12 +204,13 @@ class ElfCompilationUnitWriter {
// Decode dex register locations for all stack maps.
// It might be expensive, so do it just once and reuse the result.
+ std::unique_ptr<const CodeInfo> code_info;
std::vector<DexRegisterMap> dex_reg_maps;
if (accessor.HasCodeItem() && mi->code_info != nullptr) {
- const CodeInfo code_info(mi->code_info);
- for (size_t s = 0; s < code_info.GetNumberOfStackMaps(); ++s) {
- const StackMap stack_map = code_info.GetStackMapAt(s);
- dex_reg_maps.push_back(code_info.GetDexRegisterMapOf(
+ code_info.reset(new CodeInfo(mi->code_info));
+ for (size_t s = 0; s < code_info->GetNumberOfStackMaps(); ++s) {
+ const StackMap stack_map = code_info->GetStackMapAt(s);
+ dex_reg_maps.push_back(code_info->GetDexRegisterMapOf(
stack_map, accessor.RegistersSize()));
}
}
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index c1bf915212..8cb4e55bbc 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -149,11 +149,9 @@ static std::vector<VariableLocation> GetVariableLocations(
DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
DCHECK(dex_register_map.IsValid());
CodeItemDataAccessor accessor(*method_info->dex_file, method_info->code_item);
- reg_lo = dex_register_map.GetDexRegisterLocation(
- vreg, accessor.RegistersSize(), code_info);
+ reg_lo = dex_register_map.GetDexRegisterLocation(vreg);
if (is64bitValue) {
- reg_hi = dex_register_map.GetDexRegisterLocation(
- vreg + 1, accessor.RegistersSize(), code_info);
+ reg_hi = dex_register_map.GetDexRegisterLocation(vreg + 1);
}
// Add location entry for this address range.
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 68155d844a..fb6a72b1c5 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -635,13 +635,13 @@ void DexToDexCompiler::SetDexFiles(const std::vector<const DexFile*>& dex_files)
std::unordered_set<const DexFile::CodeItem*> seen_code_items;
for (const DexFile* dex_file : dex_files) {
for (ClassAccessor accessor : dex_file->GetClasses()) {
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const DexFile::CodeItem* code_item = method.GetCodeItem();
// Detect the shared code items.
if (!seen_code_items.insert(code_item).second) {
shared_code_items_.insert(code_item);
}
- });
+ }
}
}
VLOG(compiler) << "Shared code items " << shared_code_items_.size();
diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 082e6091d2..1fe42ad531 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -67,7 +67,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
class_loader = LoadDex(dex_name);
updated_dex_file = GetDexFiles(class_loader)[0];
Runtime::Current()->GetClassLinker()->RegisterDexFile(
- *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+ *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
}
// The dex files should be identical.
int cmp = memcmp(original_dex_file->Begin(),
@@ -85,10 +85,9 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
for (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
// Unquicken each method.
ClassAccessor accessor(*updated_dex_file, updated_dex_file->GetClassDef(i));
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(
- MethodReference(updated_dex_file,
- method.GetIndex()));
+ method.GetReference());
ArrayRef<const uint8_t> table;
if (compiled_method != nullptr) {
table = compiled_method->GetVmapTable();
@@ -97,7 +96,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
*accessor.GetCodeItem(method),
table,
/* decompile_return_instruction */ true);
- });
+ }
}
// Make sure after unquickening we go back to the same contents as the original dex file.
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1b809d232a..653e9edb45 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -391,7 +391,7 @@ static optimizer::DexToDexCompiler::CompilationLevel GetDexToDexCompilationLevel
DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled());
const char* descriptor = dex_file.GetClassDescriptor(class_def);
ClassLinker* class_linker = runtime->GetClassLinker();
- mirror::Class* klass = class_linker->FindClass(self, descriptor, class_loader);
+ ObjPtr<mirror::Class> klass = class_linker->FindClass(self, descriptor, class_loader);
if (klass == nullptr) {
CHECK(self->IsExceptionPending());
self->ClearException();
@@ -790,8 +790,7 @@ static void ResolveConstStrings(CompilerDriver* driver,
// FIXME: Make sure that inlining honors this. b/26687569
continue;
}
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
// Resolve const-strings in the code. Done to have deterministic allocation behavior. Right
// now this is single-threaded for simplicity.
// TODO: Collect the relevant string indices in parallel, then allocate them sequentially
@@ -812,7 +811,7 @@ static void ResolveConstStrings(CompilerDriver* driver,
break;
}
}
- });
+ }
}
}
}
@@ -880,10 +879,9 @@ static void InitializeTypeCheckBitstrings(CompilerDriver* driver,
}
// Direct and virtual methods.
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
InitializeTypeCheckBitstrings(driver, class_linker, dex_cache, *dex_file, method);
- });
+ }
}
}
}
@@ -1935,11 +1933,10 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
// Just update the compiled_classes_ map. The compiler doesn't need to resolve
// the type.
ClassReference ref(dex_file, class_def_idx);
- ClassStatus existing = ClassStatus::kNotReady;
- DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation();
+ const ClassStatus existing = ClassStatus::kNotReady;
ClassStateTable::InsertResult result =
compiled_classes_.Insert(ref, existing, ClassStatus::kVerified);
- CHECK_EQ(result, ClassStateTable::kInsertResultSuccess);
+ CHECK_EQ(result, ClassStateTable::kInsertResultSuccess) << ref.dex_file->GetLocation();
} else {
// Update the class status, so later compilation stages know they don't need to verify
// the class.
@@ -1950,9 +1947,9 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
// - We're only going to compile methods that did verify.
// - Quickening will not do checkcast ellision.
// TODO(ngeoffray): Reconsider this once we refactor compiler filters.
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
verification_results_->CreateVerifiedMethodFor(method.GetReference());
- });
+ }
}
} else if (!compiler_only_verifies) {
// Make sure later compilation stages know they should not try to verify
@@ -1962,8 +1959,8 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
class_loader,
soa.Self());
}
+ ++class_def_idx;
}
- ++class_def_idx;
}
return true;
}
@@ -2748,12 +2745,12 @@ static void CompileDexFile(CompilerDriver* driver,
// Compile direct and virtual methods.
int64_t previous_method_idx = -1;
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const uint32_t method_idx = method.GetIndex();
if (method_idx == previous_method_idx) {
// smali can create dex files with two encoded_methods sharing the same method_idx
// http://code.google.com/p/smali/issues/detail?id=119
- return;
+ continue;
}
previous_method_idx = method_idx;
compile_fn(soa.Self(),
@@ -2768,7 +2765,7 @@ static void CompileDexFile(CompilerDriver* driver,
dex_to_dex_compilation_level,
compilation_enabled,
dex_cache);
- });
+ }
};
context.ForAllLambda(0, dex_file.NumClassDefs(), compile, thread_count);
}
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 856cb36266..491e61f9b5 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -88,7 +88,7 @@ class CompilerDriverTest : public CommonCompilerTest {
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
+ ObjPtr<mirror::Class> c = class_linker->FindClass(soa.Self(), descriptor, loader);
CHECK(c != nullptr);
const auto pointer_size = class_linker->GetImagePointerSize();
for (auto& m : c->GetMethods(pointer_size)) {
@@ -115,14 +115,14 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
- const mirror::String* string = dex_cache->GetResolvedString(dex::StringIndex(i));
+ const ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(i));
EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
}
EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes());
for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
- mirror::Class* type = dex_cache->GetResolvedType(dex::TypeIndex(i));
- EXPECT_TRUE(type != nullptr) << "type_idx=" << i
- << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
+ const ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(dex::TypeIndex(i));
+ EXPECT_TRUE(type != nullptr)
+ << "type_idx=" << i << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
}
EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods()
|| dex.NumMethodIds() == dex_cache->NumResolvedMethods());
@@ -228,7 +228,7 @@ class CompilerDriverProfileTest : public CompilerDriverTest {
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
+ ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
ASSERT_NE(klass, nullptr);
const auto pointer_size = class_linker->GetImagePointerSize();
@@ -289,7 +289,7 @@ class CompilerDriverVerifyTest : public CompilerDriverTest {
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
+ ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
ASSERT_NE(klass, nullptr);
EXPECT_TRUE(klass->IsVerified());
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index c139fcf1d8..15c07870a1 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -34,6 +34,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/stack_trace_element.h"
#include "oat_quick_method_header.h"
+#include "obj_ptr-inl.h"
#include "optimizing/stack_map_stream.h"
#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
@@ -68,47 +69,38 @@ class ExceptionTest : public CommonRuntimeTest {
fake_code_.push_back(0x70 | i);
}
+ const uint32_t native_pc_offset = 4u;
+ CHECK_ALIGNED_PARAM(native_pc_offset, GetInstructionSetInstructionAlignment(kRuntimeISA));
+
MallocArenaPool pool;
ArenaStack arena_stack(&pool);
ScopedArenaAllocator allocator(&arena_stack);
StackMapStream stack_maps(&allocator, kRuntimeISA);
stack_maps.BeginStackMapEntry(kDexPc,
- /* native_pc_offset */ 3u,
+ native_pc_offset,
/* register_mask */ 0u,
/* sp_mask */ nullptr,
/* num_dex_registers */ 0u,
/* inlining_depth */ 0u);
stack_maps.EndStackMapEntry();
- size_t stack_maps_size = stack_maps.PrepareForFillIn();
- size_t stack_maps_offset = stack_maps_size + sizeof(OatQuickMethodHeader);
+ const size_t stack_maps_size = stack_maps.PrepareForFillIn();
+ const size_t header_size = sizeof(OatQuickMethodHeader);
+ const size_t code_alignment = GetInstructionSetAlignment(kRuntimeISA);
+ const size_t code_offset = RoundUp(stack_maps_size + header_size, code_alignment);
- fake_header_code_and_maps_.resize(stack_maps_offset + fake_code_.size());
+ fake_header_code_and_maps_.resize(code_offset + fake_code_.size());
MemoryRegion stack_maps_region(&fake_header_code_and_maps_[0], stack_maps_size);
stack_maps.FillInCodeInfo(stack_maps_region);
- OatQuickMethodHeader method_header(stack_maps_offset, 0u, 4 * sizeof(void*), 0u, 0u, code_size);
- memcpy(&fake_header_code_and_maps_[stack_maps_size], &method_header, sizeof(method_header));
+ OatQuickMethodHeader method_header(code_offset, 0u, 4 * sizeof(void*), 0u, 0u, code_size);
+ memcpy(&fake_header_code_and_maps_[code_offset - header_size], &method_header, header_size);
std::copy(fake_code_.begin(),
fake_code_.end(),
- fake_header_code_and_maps_.begin() + stack_maps_offset);
-
- // Align the code.
- const size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
- fake_header_code_and_maps_.reserve(fake_header_code_and_maps_.size() + alignment);
- const void* unaligned_code_ptr =
- fake_header_code_and_maps_.data() + (fake_header_code_and_maps_.size() - code_size);
- size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
- size_t padding = RoundUp(offset, alignment) - offset;
- // Make sure no resizing takes place.
- CHECK_GE(fake_header_code_and_maps_.capacity(), fake_header_code_and_maps_.size() + padding);
- fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(), padding, 0);
- const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
- CHECK_EQ(code_ptr,
- static_cast<const void*>(fake_header_code_and_maps_.data() +
- (fake_header_code_and_maps_.size() - code_size)));
+ fake_header_code_and_maps_.begin() + code_offset);
+ const void* code_ptr = fake_header_code_and_maps_.data() + code_offset;
if (kRuntimeISA == InstructionSet::kArm) {
// Check that the Thumb2 adjustment will be a NOP, see EntryPointToCodePointer().
- CHECK_ALIGNED(stack_maps_offset, 2);
+ CHECK_ALIGNED(code_ptr, 2);
}
method_f_ = my_klass_->FindClassMethod("f", "()I", kRuntimePointerSize);
@@ -131,7 +123,7 @@ class ExceptionTest : public CommonRuntimeTest {
ArtMethod* method_g_;
private:
- mirror::Class* my_klass_;
+ ObjPtr<mirror::Class> my_klass_;
};
TEST_F(ExceptionTest, FindCatchHandler) {
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index de1be5b871..4791fa3fba 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -63,6 +63,7 @@
#include "parallel_move_resolver.h"
#include "scoped_thread_state_change-inl.h"
#include "ssa_liveness_analysis.h"
+#include "stack_map.h"
#include "stack_map_stream.h"
#include "thread-current-inl.h"
#include "utils/assembler.h"
@@ -1161,8 +1162,8 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction,
// last emitted is different than the native pc of the stack map just emitted.
size_t number_of_stack_maps = stack_map_stream->GetNumberOfStackMaps();
if (number_of_stack_maps > 1) {
- DCHECK_NE(stack_map_stream->GetStackMap(number_of_stack_maps - 1).native_pc_code_offset,
- stack_map_stream->GetStackMap(number_of_stack_maps - 2).native_pc_code_offset);
+ DCHECK_NE(stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 1),
+ stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 2));
}
}
}
@@ -1174,8 +1175,7 @@ bool CodeGenerator::HasStackMapAtCurrentPc() {
if (count == 0) {
return false;
}
- CodeOffset native_pc_offset = stack_map_stream->GetStackMap(count - 1).native_pc_code_offset;
- return (native_pc_offset.Uint32Value(GetInstructionSet()) == pc);
+ return stack_map_stream->GetStackMapNativePcOffset(count - 1) == pc;
}
void CodeGenerator::MaybeRecordNativeDebugInfo(HInstruction* instruction,
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 7f3441fdf4..8be84a15bd 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1042,8 +1042,7 @@ void CodeGeneratorMIPS::Finalize(CodeAllocator* allocator) {
// Adjust native pc offsets in stack maps.
StackMapStream* stack_map_stream = GetStackMapStream();
for (size_t i = 0, num = stack_map_stream->GetNumberOfStackMaps(); i != num; ++i) {
- uint32_t old_position =
- stack_map_stream->GetStackMap(i).native_pc_code_offset.Uint32Value(InstructionSet::kMips);
+ uint32_t old_position = stack_map_stream->GetStackMapNativePcOffset(i);
uint32_t new_position = __ GetAdjustedPosition(old_position);
DCHECK_GE(new_position, old_position);
stack_map_stream->SetStackMapNativePcOffset(i, new_position);
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index ee32b96daf..cd9e0e521e 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -988,8 +988,7 @@ void CodeGeneratorMIPS64::Finalize(CodeAllocator* allocator) {
// Adjust native pc offsets in stack maps.
StackMapStream* stack_map_stream = GetStackMapStream();
for (size_t i = 0, num = stack_map_stream->GetNumberOfStackMaps(); i != num; ++i) {
- uint32_t old_position =
- stack_map_stream->GetStackMap(i).native_pc_code_offset.Uint32Value(InstructionSet::kMips64);
+ uint32_t old_position = stack_map_stream->GetStackMapNativePcOffset(i);
uint32_t new_position = __ GetAdjustedPosition(old_position);
DCHECK_GE(new_position, old_position);
stack_map_stream->SetStackMapNativePcOffset(i, new_position);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index ffa000e34e..6900cd883a 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -20,6 +20,7 @@
#include "base/enums.h"
#include "builder.h"
#include "class_linker.h"
+#include "class_root.h"
#include "constant_folding.h"
#include "data_type-inl.h"
#include "dead_code_elimination.h"
@@ -537,7 +538,7 @@ static Handle<mirror::ObjectArray<mirror::Class>> AllocateInlineCacheHolder(
Handle<mirror::ObjectArray<mirror::Class>> inline_cache = hs->NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(
self,
- class_linker->GetClassRoot(ClassLinker::kClassArrayClass),
+ GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker),
InlineCache::kIndividualCacheSize));
if (inline_cache == nullptr) {
// We got an OOME. Just clear the exception, and don't inline.
@@ -777,7 +778,7 @@ HInliner::InlineCacheType HInliner::ExtractClassesFromOfflineProfile(
HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker,
HInstruction* receiver,
uint32_t dex_pc) const {
- ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>(class_linker)->GetInstanceField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
HInstanceFieldGet* result = new (graph_->GetAllocator()) HInstanceFieldGet(
receiver,
@@ -2120,9 +2121,8 @@ bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction,
return true;
} else if (return_replacement->IsInstanceFieldGet()) {
HInstanceFieldGet* field_get = return_replacement->AsInstanceFieldGet();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (field_get->GetFieldInfo().GetField() ==
- class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0)) {
+ GetClassRoot<mirror::Object>()->GetInstanceField(0)) {
return true;
}
}
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index ca84d421a7..63704a470e 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -18,6 +18,7 @@
#include "art_method-inl.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "data_type-inl.h"
#include "escape.h"
#include "intrinsics.h"
@@ -1563,8 +1564,7 @@ static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
{
ScopedObjectAccess soa(Thread::Current());
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
if (field_get->GetFieldInfo().GetField() != field) {
return false;
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index dfe6d791c6..056f533398 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -272,7 +272,8 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo
ClassLinker* class_linker = runtime->GetClassLinker();
gc::Heap* heap = runtime->GetHeap();
IntegerValueOfInfo info;
- info.integer_cache = class_linker->FindSystemClass(self, "Ljava/lang/Integer$IntegerCache;");
+ info.integer_cache =
+ class_linker->FindSystemClass(self, "Ljava/lang/Integer$IntegerCache;").Ptr();
if (info.integer_cache == nullptr) {
self->ClearException();
return info;
@@ -281,7 +282,7 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo
// Optimization only works if the class is initialized and in the boot image.
return info;
}
- info.integer = class_linker->FindSystemClass(self, "Ljava/lang/Integer;");
+ info.integer = class_linker->FindSystemClass(self, "Ljava/lang/Integer;").Ptr();
if (info.integer == nullptr) {
self->ClearException();
return info;
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 5287b4b2fa..fecf1ccbfa 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -25,7 +25,7 @@
#include "mirror/array-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/reference.h"
-#include "mirror/string.h"
+#include "mirror/string-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 7f78dc257e..ef8a757ad0 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -22,6 +22,7 @@
#include "base/bit_vector-inl.h"
#include "base/stl_util.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "code_generator.h"
#include "common_dominator.h"
#include "intrinsics.h"
@@ -40,9 +41,8 @@ static constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD ==
void HGraph::InitializeInexactObjectRTI(VariableSizedHandleScope* handles) {
ScopedObjectAccess soa(Thread::Current());
// Create the inexact Object reference type and store it in the HGraph.
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
inexact_object_rti_ = ReferenceTypeInfo::Create(
- handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
+ handles->NewHandle(GetClassRoot<mirror::Object>()),
/* is_exact */ false);
}
@@ -1121,6 +1121,23 @@ void HEnvironment::RemoveAsUserOfInput(size_t index) const {
user->FixUpUserRecordsAfterEnvUseRemoval(before_env_use_node);
}
+void HEnvironment::ReplaceInput(HInstruction* replacement, size_t index) {
+ const HUserRecord<HEnvironment*>& env_use_record = vregs_[index];
+ HInstruction* orig_instr = env_use_record.GetInstruction();
+
+ DCHECK(orig_instr != replacement);
+
+ HUseList<HEnvironment*>::iterator before_use_node = env_use_record.GetBeforeUseNode();
+ // Note: fixup_end remains valid across splice_after().
+ auto fixup_end = replacement->env_uses_.empty() ? replacement->env_uses_.begin()
+ : ++replacement->env_uses_.begin();
+ replacement->env_uses_.splice_after(replacement->env_uses_.before_begin(),
+ env_use_record.GetInstruction()->env_uses_,
+ before_use_node);
+ replacement->FixUpUserRecordsAfterEnvUseInsertion(fixup_end);
+ orig_instr->FixUpUserRecordsAfterEnvUseRemoval(before_use_node);
+}
+
HInstruction* HInstruction::GetNextDisregardingMoves() const {
HInstruction* next = GetNext();
while (next != nullptr && next->IsParallelMove()) {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 09d9c57a33..3fd5b6b02d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1909,6 +1909,11 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
void RemoveAsUserOfInput(size_t index) const;
+ // Replaces the input at the position 'index' with the replacement; the replacement and old
+ // input instructions' env_uses_ lists are adjusted. The function works similar to
+ // HInstruction::ReplaceInput.
+ void ReplaceInput(HInstruction* replacement, size_t index);
+
size_t Size() const { return vregs_.size(); }
HEnvironment* GetParent() const { return parent_; }
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index c4977decd9..79ac6b9b9d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -31,6 +31,7 @@
#include "base/scoped_arena_allocator.h"
#include "base/timing_logger.h"
#include "builder.h"
+#include "class_root.h"
#include "code_generator.h"
#include "compiled_method.h"
#include "compiler.h"
@@ -1309,13 +1310,12 @@ bool OptimizingCompiler::JitCompile(Thread* self,
size_t method_info_size = 0;
codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size);
size_t number_of_roots = codegen->GetNumberOfJitRoots();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
// We allocate an object array to ensure the JIT roots that we will collect in EmitJitRoots
// will be visible by the GC between EmitLiterals and CommitCode. Once CommitCode is
// executed, this array is not needed.
Handle<mirror::ObjectArray<mirror::Object>> roots(
hs.NewHandle(mirror::ObjectArray<mirror::Object>::Alloc(
- self, class_linker->GetClassRoot(ClassLinker::kObjectArrayClass), number_of_roots)));
+ self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(), number_of_roots)));
if (roots == nullptr) {
// Out of memory, just clear the exception to avoid any Java exception uncaught problems.
MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kJitOutOfMemoryForCommit);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index ecfa790b91..f3fe62561f 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -22,6 +22,7 @@
#include "base/scoped_arena_containers.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
@@ -40,43 +41,40 @@ static inline ObjPtr<mirror::DexCache> FindDexCacheWithHint(
}
static inline ReferenceTypeInfo::TypeHandle GetRootHandle(VariableSizedHandleScope* handles,
- ClassLinker::ClassRoot class_root,
+ ClassRoot class_root,
ReferenceTypeInfo::TypeHandle* cache) {
if (!ReferenceTypeInfo::IsValidHandle(*cache)) {
// Mutator lock is required for NewHandle.
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
ScopedObjectAccess soa(Thread::Current());
- *cache = handles->NewHandle(linker->GetClassRoot(class_root));
+ *cache = handles->NewHandle(GetClassRoot(class_root));
}
return *cache;
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() {
- return GetRootHandle(handles_, ClassLinker::kJavaLangObject, &object_class_handle_);
+ return GetRootHandle(handles_, ClassRoot::kJavaLangObject, &object_class_handle_);
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() {
- return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_);
+ return GetRootHandle(handles_, ClassRoot::kJavaLangClass, &class_class_handle_);
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodHandleClassHandle() {
return GetRootHandle(handles_,
- ClassLinker::kJavaLangInvokeMethodHandleImpl,
+ ClassRoot::kJavaLangInvokeMethodHandleImpl,
&method_handle_class_handle_);
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodTypeClassHandle() {
- return GetRootHandle(handles_,
- ClassLinker::kJavaLangInvokeMethodType,
- &method_type_class_handle_);
+ return GetRootHandle(handles_, ClassRoot::kJavaLangInvokeMethodType, &method_type_class_handle_);
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() {
- return GetRootHandle(handles_, ClassLinker::kJavaLangString, &string_class_handle_);
+ return GetRootHandle(handles_, ClassRoot::kJavaLangString, &string_class_handle_);
}
ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() {
- return GetRootHandle(handles_, ClassLinker::kJavaLangThrowable, &throwable_class_handle_);
+ return GetRootHandle(handles_, ClassRoot::kJavaLangThrowable, &throwable_class_handle_);
}
class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor {
@@ -341,8 +339,7 @@ static void BoundTypeForClassCheck(HInstruction* check) {
{
ScopedObjectAccess soa(Thread::Current());
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
+ ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
if (field_get->GetFieldInfo().GetField() != field) {
return;
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index aa28c8b500..d99beac59f 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -16,577 +16,311 @@
#include "stack_map_stream.h"
+#include <memory>
+
#include "art_method-inl.h"
#include "base/stl_util.h"
#include "dex/dex_file_types.h"
#include "optimizing/optimizing_compiler.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
+#include "stack_map.h"
namespace art {
+constexpr static bool kVerifyStackMaps = kIsDebugBuild;
+
+uint32_t StackMapStream::GetStackMapNativePcOffset(size_t i) {
+ return StackMap::UnpackNativePc(stack_maps_[i].packed_native_pc, instruction_set_);
+}
+
+void StackMapStream::SetStackMapNativePcOffset(size_t i, uint32_t native_pc_offset) {
+ stack_maps_[i].packed_native_pc = StackMap::PackNativePc(native_pc_offset, instruction_set_);
+}
+
void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
uint32_t native_pc_offset,
uint32_t register_mask,
- BitVector* sp_mask,
+ BitVector* stack_mask,
uint32_t num_dex_registers,
uint8_t inlining_depth) {
- DCHECK_EQ(0u, current_entry_.dex_pc) << "EndStackMapEntry not called after BeginStackMapEntry";
- current_entry_.dex_pc = dex_pc;
- current_entry_.native_pc_code_offset = CodeOffset::FromOffset(native_pc_offset, instruction_set_);
- current_entry_.register_mask = register_mask;
- current_entry_.sp_mask = sp_mask;
- current_entry_.inlining_depth = inlining_depth;
- current_entry_.inline_infos_start_index = inline_infos_.size();
- current_entry_.stack_mask_index = 0;
- current_entry_.dex_method_index = dex::kDexNoIndex;
- current_entry_.dex_register_entry.num_dex_registers = num_dex_registers;
- current_entry_.dex_register_entry.locations_start_index = dex_register_locations_.size();
- current_entry_.dex_register_entry.live_dex_registers_mask = nullptr;
- if (num_dex_registers != 0u) {
- current_entry_.dex_register_entry.live_dex_registers_mask =
- ArenaBitVector::Create(allocator_, num_dex_registers, true, kArenaAllocStackMapStream);
- current_entry_.dex_register_entry.live_dex_registers_mask->ClearAllBits();
+ DCHECK(!in_stack_map_) << "Mismatched Begin/End calls";
+ in_stack_map_ = true;
+
+ current_stack_map_ = StackMapEntry {
+ .packed_native_pc = StackMap::PackNativePc(native_pc_offset, instruction_set_),
+ .dex_pc = dex_pc,
+ .register_mask_index = kNoValue,
+ .stack_mask_index = kNoValue,
+ .inline_info_index = kNoValue,
+ .dex_register_mask_index = kNoValue,
+ .dex_register_map_index = kNoValue,
+ };
+ if (register_mask != 0) {
+ uint32_t shift = LeastSignificantBit(register_mask);
+ RegisterMaskEntry entry = { register_mask >> shift, shift };
+ current_stack_map_.register_mask_index = register_masks_.Dedup(&entry);
}
- if (sp_mask != nullptr) {
- stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
+ // The compiler assumes the bit vector will be read during PrepareForFillIn(),
+ // and it might modify the data before that. Therefore, just store the pointer.
+ // See ClearSpillSlotsFromLoopPhisInStackMap in code_generator.h.
+ lazy_stack_masks_.push_back(stack_mask);
+ current_inline_infos_ = 0;
+ current_dex_registers_.clear();
+ expected_num_dex_registers_ = num_dex_registers;
+
+ if (kVerifyStackMaps) {
+ size_t stack_map_index = stack_maps_.size();
+ // Create lambda method, which will be executed at the very end to verify data.
+ // Parameters and local variables will be captured(stored) by the lambda "[=]".
+ dchecks_.emplace_back([=](const CodeInfo& code_info) {
+ StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
+ CHECK_EQ(stack_map.GetNativePcOffset(instruction_set_), native_pc_offset);
+ CHECK_EQ(stack_map.GetDexPc(), dex_pc);
+ CHECK_EQ(code_info.GetRegisterMaskOf(stack_map), register_mask);
+ BitMemoryRegion seen_stack_mask = code_info.GetStackMaskOf(stack_map);
+ CHECK_GE(seen_stack_mask.size_in_bits(), stack_mask ? stack_mask->GetNumberOfBits() : 0);
+ for (size_t b = 0; b < seen_stack_mask.size_in_bits(); b++) {
+ CHECK_EQ(seen_stack_mask.LoadBit(b), stack_mask != nullptr && stack_mask->IsBitSet(b));
+ }
+ CHECK_EQ(stack_map.HasInlineInfo(), (inlining_depth != 0));
+ if (inlining_depth != 0) {
+ CHECK_EQ(code_info.GetInlineInfoOf(stack_map).GetDepth(), inlining_depth);
+ }
+ CHECK_EQ(stack_map.HasDexRegisterMap(), (num_dex_registers != 0));
+ });
}
-
- current_dex_register_ = 0;
}
void StackMapStream::EndStackMapEntry() {
- current_entry_.dex_register_map_index = AddDexRegisterMapEntry(current_entry_.dex_register_entry);
- stack_maps_.push_back(current_entry_);
- current_entry_ = StackMapEntry();
+ DCHECK(in_stack_map_) << "Mismatched Begin/End calls";
+ in_stack_map_ = false;
+ DCHECK_EQ(expected_num_dex_registers_, current_dex_registers_.size());
+
+ // Mark the last inline info as last in the list for the stack map.
+ if (current_inline_infos_ > 0) {
+ inline_infos_[inline_infos_.size() - 1].is_last = InlineInfo::kLast;
+ }
+
+ stack_maps_.Add(current_stack_map_);
}
void StackMapStream::AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value) {
- if (kind != DexRegisterLocation::Kind::kNone) {
- // Ensure we only use non-compressed location kind at this stage.
- DCHECK(DexRegisterLocation::IsShortLocationKind(kind)) << kind;
- DexRegisterLocation location(kind, value);
-
- // Look for Dex register `location` in the location catalog (using the
- // companion hash map of locations to indices). Use its index if it
- // is already in the location catalog. If not, insert it (in the
- // location catalog and the hash map) and use the newly created index.
- auto it = location_catalog_entries_indices_.Find(location);
- if (it != location_catalog_entries_indices_.end()) {
- // Retrieve the index from the hash map.
- dex_register_locations_.push_back(it->second);
- } else {
- // Create a new entry in the location catalog and the hash map.
- size_t index = location_catalog_entries_.size();
- location_catalog_entries_.push_back(location);
- dex_register_locations_.push_back(index);
- location_catalog_entries_indices_.Insert(std::make_pair(location, index));
- }
- DexRegisterMapEntry* const entry = in_inline_frame_
- ? &current_inline_info_.dex_register_entry
- : &current_entry_.dex_register_entry;
- DCHECK_LT(current_dex_register_, entry->num_dex_registers);
- entry->live_dex_registers_mask->SetBit(current_dex_register_);
- entry->hash += (1 <<
- (current_dex_register_ % (sizeof(DexRegisterMapEntry::hash) * kBitsPerByte)));
- entry->hash += static_cast<uint32_t>(value);
- entry->hash += static_cast<uint32_t>(kind);
+ current_dex_registers_.push_back(DexRegisterLocation(kind, value));
+
+ // We have collected all the dex registers for StackMap/InlineInfo - create the map.
+ if (current_dex_registers_.size() == expected_num_dex_registers_) {
+ CreateDexRegisterMap();
}
- current_dex_register_++;
}
void StackMapStream::AddInvoke(InvokeType invoke_type, uint32_t dex_method_index) {
- current_entry_.invoke_type = invoke_type;
- current_entry_.dex_method_index = dex_method_index;
+ uint32_t packed_native_pc = current_stack_map_.packed_native_pc;
+ size_t invoke_info_index = invoke_infos_.size();
+ invoke_infos_.Add(InvokeInfoEntry {
+ .packed_native_pc = packed_native_pc,
+ .invoke_type = invoke_type,
+ .method_info_index = method_infos_.Dedup(&dex_method_index),
+ });
+
+ if (kVerifyStackMaps) {
+ dchecks_.emplace_back([=](const CodeInfo& code_info) {
+ InvokeInfo invoke_info = code_info.GetInvokeInfo(invoke_info_index);
+ CHECK_EQ(invoke_info.GetNativePcOffset(instruction_set_),
+ StackMap::UnpackNativePc(packed_native_pc, instruction_set_));
+ CHECK_EQ(invoke_info.GetInvokeType(), invoke_type);
+ CHECK_EQ(method_infos_[invoke_info.GetMethodIndexIdx()], dex_method_index);
+ });
+ }
}
void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
uint32_t dex_pc,
uint32_t num_dex_registers,
const DexFile* outer_dex_file) {
- DCHECK(!in_inline_frame_);
- in_inline_frame_ = true;
+ DCHECK(!in_inline_info_) << "Mismatched Begin/End calls";
+ in_inline_info_ = true;
+ DCHECK_EQ(expected_num_dex_registers_, current_dex_registers_.size());
+
+ InlineInfoEntry entry = {
+ .is_last = InlineInfo::kMore,
+ .dex_pc = dex_pc,
+ .method_info_index = kNoValue,
+ .art_method_hi = kNoValue,
+ .art_method_lo = kNoValue,
+ .dex_register_mask_index = kNoValue,
+ .dex_register_map_index = kNoValue,
+ };
if (EncodeArtMethodInInlineInfo(method)) {
- current_inline_info_.method = method;
+ entry.art_method_hi = High32Bits(reinterpret_cast<uintptr_t>(method));
+ entry.art_method_lo = Low32Bits(reinterpret_cast<uintptr_t>(method));
} else {
if (dex_pc != static_cast<uint32_t>(-1) && kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
DCHECK(IsSameDexFile(*outer_dex_file, *method->GetDexFile()));
}
- current_inline_info_.method_index = method->GetDexMethodIndexUnchecked();
+ uint32_t dex_method_index = method->GetDexMethodIndexUnchecked();
+ entry.method_info_index = method_infos_.Dedup(&dex_method_index);
}
- current_inline_info_.dex_pc = dex_pc;
- current_inline_info_.dex_register_entry.num_dex_registers = num_dex_registers;
- current_inline_info_.dex_register_entry.locations_start_index = dex_register_locations_.size();
- current_inline_info_.dex_register_entry.live_dex_registers_mask = nullptr;
- if (num_dex_registers != 0) {
- current_inline_info_.dex_register_entry.live_dex_registers_mask =
- ArenaBitVector::Create(allocator_, num_dex_registers, true, kArenaAllocStackMapStream);
- current_inline_info_.dex_register_entry.live_dex_registers_mask->ClearAllBits();
+ if (current_inline_infos_++ == 0) {
+ current_stack_map_.inline_info_index = inline_infos_.size();
+ }
+ inline_infos_.Add(entry);
+
+ current_dex_registers_.clear();
+ expected_num_dex_registers_ = num_dex_registers;
+
+ if (kVerifyStackMaps) {
+ size_t stack_map_index = stack_maps_.size();
+ size_t depth = current_inline_infos_ - 1;
+ dchecks_.emplace_back([=](const CodeInfo& code_info) {
+ StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ CHECK_EQ(inline_info.GetDexPcAtDepth(depth), dex_pc);
+ bool encode_art_method = EncodeArtMethodInInlineInfo(method);
+ CHECK_EQ(inline_info.EncodesArtMethodAtDepth(depth), encode_art_method);
+ if (encode_art_method) {
+ CHECK_EQ(inline_info.GetArtMethodAtDepth(depth), method);
+ } else {
+ CHECK_EQ(method_infos_[inline_info.GetMethodIndexIdxAtDepth(depth)],
+ method->GetDexMethodIndexUnchecked());
+ }
+ CHECK_EQ(inline_info.HasDexRegisterMapAtDepth(depth), (num_dex_registers != 0));
+ });
}
- current_dex_register_ = 0;
}
void StackMapStream::EndInlineInfoEntry() {
- current_inline_info_.dex_register_map_index =
- AddDexRegisterMapEntry(current_inline_info_.dex_register_entry);
- DCHECK(in_inline_frame_);
- DCHECK_EQ(current_dex_register_, current_inline_info_.dex_register_entry.num_dex_registers)
- << "Inline information contains less registers than expected";
- in_inline_frame_ = false;
- inline_infos_.push_back(current_inline_info_);
- current_inline_info_ = InlineInfoEntry();
+ DCHECK(in_inline_info_) << "Mismatched Begin/End calls";
+ in_inline_info_ = false;
+ DCHECK_EQ(expected_num_dex_registers_, current_dex_registers_.size());
}
-size_t StackMapStream::ComputeDexRegisterLocationCatalogSize() const {
- size_t size = DexRegisterLocationCatalog::kFixedSize;
- for (const DexRegisterLocation& dex_register_location : location_catalog_entries_) {
- size += DexRegisterLocationCatalog::EntrySize(dex_register_location);
+// Create dex register map (bitmap + indices + catalogue entries)
+// based on the currently accumulated list of DexRegisterLocations.
+void StackMapStream::CreateDexRegisterMap() {
+ // Create mask and map based on current registers.
+ temp_dex_register_mask_.ClearAllBits();
+ temp_dex_register_map_.clear();
+ for (size_t i = 0; i < current_dex_registers_.size(); i++) {
+ DexRegisterLocation reg = current_dex_registers_[i];
+ if (reg.IsLive()) {
+ DexRegisterEntry entry = DexRegisterEntry {
+ .kind = static_cast<uint32_t>(reg.GetKind()),
+ .packed_value = DexRegisterInfo::PackValue(reg.GetKind(), reg.GetValue()),
+ };
+ temp_dex_register_mask_.SetBit(i);
+ temp_dex_register_map_.push_back(dex_register_catalog_.Dedup(&entry));
+ }
}
- return size;
-}
-size_t StackMapStream::DexRegisterMapEntry::ComputeSize(size_t catalog_size) const {
- // For num_dex_registers == 0u live_dex_registers_mask may be null.
- if (num_dex_registers == 0u) {
- return 0u; // No register map will be emitted.
+ // Set the mask and map for the current StackMap/InlineInfo.
+ uint32_t mask_index = StackMap::kNoValue; // Represents mask with all zero bits.
+ if (temp_dex_register_mask_.GetNumberOfBits() != 0) {
+ mask_index = dex_register_masks_.Dedup(temp_dex_register_mask_.GetRawStorage(),
+ temp_dex_register_mask_.GetNumberOfBits());
}
- size_t number_of_live_dex_registers = live_dex_registers_mask->NumSetBits();
- if (live_dex_registers_mask->NumSetBits() == 0) {
- return 0u; // No register map will be emitted.
+ uint32_t map_index = dex_register_maps_.Dedup(temp_dex_register_map_.data(),
+ temp_dex_register_map_.size());
+ if (current_inline_infos_ > 0) {
+ inline_infos_[inline_infos_.size() - 1].dex_register_mask_index = mask_index;
+ inline_infos_[inline_infos_.size() - 1].dex_register_map_index = map_index;
+ } else {
+ current_stack_map_.dex_register_mask_index = mask_index;
+ current_stack_map_.dex_register_map_index = map_index;
+ }
+
+ if (kVerifyStackMaps) {
+ size_t stack_map_index = stack_maps_.size();
+ int32_t depth = current_inline_infos_ - 1;
+ // We need to make copy of the current registers for later (when the check is run).
+ auto expected_dex_registers = std::make_shared<std::vector<DexRegisterLocation>>(
+ current_dex_registers_.begin(), current_dex_registers_.end());
+ dchecks_.emplace_back([=](const CodeInfo& code_info) {
+ StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
+ size_t num_dex_registers = expected_dex_registers->size();
+ DexRegisterMap map = (depth == -1)
+ ? code_info.GetDexRegisterMapOf(stack_map, num_dex_registers)
+ : code_info.GetDexRegisterMapAtDepth(depth,
+ code_info.GetInlineInfoOf(stack_map),
+ num_dex_registers);
+ CHECK_EQ(map.size(), num_dex_registers);
+ for (size_t r = 0; r < num_dex_registers; r++) {
+ CHECK_EQ(expected_dex_registers->at(r), map.Get(r));
+ }
+ });
}
- DCHECK(live_dex_registers_mask != nullptr);
-
- // Size of the map in bytes.
- size_t size = DexRegisterMap::kFixedSize;
- // Add the live bit mask for the Dex register liveness.
- size += DexRegisterMap::GetLiveBitMaskSize(num_dex_registers);
- // Compute the size of the set of live Dex register entries.
- size_t map_entries_size_in_bits =
- DexRegisterMap::SingleEntrySizeInBits(catalog_size) * number_of_live_dex_registers;
- size_t map_entries_size_in_bytes =
- RoundUp(map_entries_size_in_bits, kBitsPerByte) / kBitsPerByte;
- size += map_entries_size_in_bytes;
- return size;
}
void StackMapStream::FillInMethodInfo(MemoryRegion region) {
{
- MethodInfo info(region.begin(), method_indices_.size());
- for (size_t i = 0; i < method_indices_.size(); ++i) {
- info.SetMethodIndex(i, method_indices_[i]);
+ MethodInfo info(region.begin(), method_infos_.size());
+ for (size_t i = 0; i < method_infos_.size(); ++i) {
+ info.SetMethodIndex(i, method_infos_[i]);
}
}
- if (kIsDebugBuild) {
+ if (kVerifyStackMaps) {
// Check the data matches.
MethodInfo info(region.begin());
const size_t count = info.NumMethodIndices();
- DCHECK_EQ(count, method_indices_.size());
+ DCHECK_EQ(count, method_infos_.size());
for (size_t i = 0; i < count; ++i) {
- DCHECK_EQ(info.GetMethodIndex(i), method_indices_[i]);
+ DCHECK_EQ(info.GetMethodIndex(i), method_infos_[i]);
}
}
}
-template<typename Vector>
-static MemoryRegion EncodeMemoryRegion(Vector* out, size_t* bit_offset, uint32_t bit_length) {
- uint32_t byte_length = BitsToBytesRoundUp(bit_length);
- EncodeVarintBits(out, bit_offset, byte_length);
- *bit_offset = RoundUp(*bit_offset, kBitsPerByte);
- out->resize(out->size() + byte_length);
- MemoryRegion region(out->data() + *bit_offset / kBitsPerByte, byte_length);
- *bit_offset += kBitsPerByte * byte_length;
- return region;
-}
-
-template<uint32_t NumColumns>
-using ScopedBitTableBuilder = BitTableBuilder<NumColumns, ScopedArenaAllocatorAdapter<uint32_t>>;
-
size_t StackMapStream::PrepareForFillIn() {
- size_t bit_offset = 0;
- out_.clear();
-
- // Decide the offsets of dex register map entries, but do not write them out yet.
- // Needs to be done first as it modifies the stack map entry.
- size_t dex_register_map_bytes = 0;
- for (DexRegisterMapEntry& entry : dex_register_entries_) {
- size_t size = entry.ComputeSize(location_catalog_entries_.size());
- entry.offset = size == 0 ? DexRegisterMapEntry::kOffsetUnassigned : dex_register_map_bytes;
- dex_register_map_bytes += size;
- }
-
- // Must be done before calling ComputeInlineInfoEncoding since ComputeInlineInfoEncoding requires
- // dex_method_index_idx to be filled in.
- PrepareMethodIndices();
-
- // Dedup stack masks. Needs to be done first as it modifies the stack map entry.
- size_t stack_mask_bits = stack_mask_max_ + 1; // Need room for max element too.
- size_t num_stack_masks = PrepareStackMasks(stack_mask_bits);
-
- // Dedup register masks. Needs to be done first as it modifies the stack map entry.
- size_t num_register_masks = PrepareRegisterMasks();
-
- // Write dex register maps.
- MemoryRegion dex_register_map_region =
- EncodeMemoryRegion(&out_, &bit_offset, dex_register_map_bytes * kBitsPerByte);
- for (DexRegisterMapEntry& entry : dex_register_entries_) {
- size_t entry_size = entry.ComputeSize(location_catalog_entries_.size());
- if (entry_size != 0) {
- DexRegisterMap dex_register_map(
- dex_register_map_region.Subregion(entry.offset, entry_size));
- FillInDexRegisterMap(dex_register_map,
- entry.num_dex_registers,
- *entry.live_dex_registers_mask,
- entry.locations_start_index);
+ static_assert(sizeof(StackMapEntry) == StackMap::kCount * sizeof(uint32_t), "Layout");
+ static_assert(sizeof(InvokeInfoEntry) == InvokeInfo::kCount * sizeof(uint32_t), "Layout");
+ static_assert(sizeof(InlineInfoEntry) == InlineInfo::kCount * sizeof(uint32_t), "Layout");
+ static_assert(sizeof(DexRegisterEntry) == DexRegisterInfo::kCount * sizeof(uint32_t), "Layout");
+ DCHECK_EQ(out_.size(), 0u);
+
+ // Read the stack masks now. The compiler might have updated them.
+ for (size_t i = 0; i < lazy_stack_masks_.size(); i++) {
+ BitVector* stack_mask = lazy_stack_masks_[i];
+ if (stack_mask != nullptr && stack_mask->GetNumberOfBits() != 0) {
+ stack_maps_[i].stack_mask_index =
+ stack_masks_.Dedup(stack_mask->GetRawStorage(), stack_mask->GetNumberOfBits());
}
}
- // Write dex register catalog.
- EncodeVarintBits(&out_, &bit_offset, location_catalog_entries_.size());
- size_t location_catalog_bytes = ComputeDexRegisterLocationCatalogSize();
- MemoryRegion dex_register_location_catalog_region =
- EncodeMemoryRegion(&out_, &bit_offset, location_catalog_bytes * kBitsPerByte);
- DexRegisterLocationCatalog dex_register_location_catalog(dex_register_location_catalog_region);
- // Offset in `dex_register_location_catalog` where to store the next
- // register location.
- size_t location_catalog_offset = DexRegisterLocationCatalog::kFixedSize;
- for (DexRegisterLocation dex_register_location : location_catalog_entries_) {
- dex_register_location_catalog.SetRegisterInfo(location_catalog_offset, dex_register_location);
- location_catalog_offset += DexRegisterLocationCatalog::EntrySize(dex_register_location);
- }
- // Ensure we reached the end of the Dex registers location_catalog.
- DCHECK_EQ(location_catalog_offset, dex_register_location_catalog_region.size());
-
- // Write stack maps.
- ScopedArenaAllocatorAdapter<void> adapter = allocator_->Adapter(kArenaAllocStackMapStream);
- ScopedBitTableBuilder<StackMap::Field::kCount> stack_map_builder((adapter));
- ScopedBitTableBuilder<InvokeInfo::Field::kCount> invoke_info_builder((adapter));
- ScopedBitTableBuilder<InlineInfo::Field::kCount> inline_info_builder((adapter));
- for (const StackMapEntry& entry : stack_maps_) {
- if (entry.dex_method_index != dex::kDexNoIndex) {
- invoke_info_builder.AddRow(
- entry.native_pc_code_offset.CompressedValue(),
- entry.invoke_type,
- entry.dex_method_index_idx);
- }
-
- // Set the inlining info.
- uint32_t inline_info_index = StackMap::kNoValue;
- DCHECK_LE(entry.inline_infos_start_index + entry.inlining_depth, inline_infos_.size());
- for (size_t depth = 0; depth < entry.inlining_depth; ++depth) {
- InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index];
- uint32_t method_index_idx = inline_entry.dex_method_index_idx;
- uint32_t extra_data = 1;
- if (inline_entry.method != nullptr) {
- method_index_idx = High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method));
- extra_data = Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method));
- }
- uint32_t index = inline_info_builder.AddRow(
- (depth == entry.inlining_depth - 1) ? InlineInfo::kLast : InlineInfo::kMore,
- method_index_idx,
- inline_entry.dex_pc,
- extra_data,
- dex_register_entries_[inline_entry.dex_register_map_index].offset);
- if (depth == 0) {
- inline_info_index = index;
- }
- }
- stack_map_builder.AddRow(
- entry.native_pc_code_offset.CompressedValue(),
- entry.dex_pc,
- dex_register_entries_[entry.dex_register_map_index].offset,
- inline_info_index,
- entry.register_mask_index,
- entry.stack_mask_index);
- }
- stack_map_builder.Encode(&out_, &bit_offset);
- invoke_info_builder.Encode(&out_, &bit_offset);
- inline_info_builder.Encode(&out_, &bit_offset);
-
- // Write register masks table.
- ScopedBitTableBuilder<1> register_mask_builder((adapter));
- for (size_t i = 0; i < num_register_masks; ++i) {
- register_mask_builder.AddRow(register_masks_[i]);
- }
- register_mask_builder.Encode(&out_, &bit_offset);
-
- // Write stack masks table.
- EncodeVarintBits(&out_, &bit_offset, stack_mask_bits);
- out_.resize(BitsToBytesRoundUp(bit_offset + stack_mask_bits * num_stack_masks));
- BitMemoryRegion stack_mask_region(MemoryRegion(out_.data(), out_.size()),
- bit_offset,
- stack_mask_bits * num_stack_masks);
- if (stack_mask_bits > 0) {
- for (size_t i = 0; i < num_stack_masks; ++i) {
- size_t stack_mask_bytes = BitsToBytesRoundUp(stack_mask_bits);
- BitMemoryRegion src(MemoryRegion(&stack_masks_[i * stack_mask_bytes], stack_mask_bytes));
- BitMemoryRegion dst = stack_mask_region.Subregion(i * stack_mask_bits, stack_mask_bits);
- for (size_t bit_index = 0; bit_index < stack_mask_bits; bit_index += BitSizeOf<uint32_t>()) {
- size_t num_bits = std::min<size_t>(stack_mask_bits - bit_index, BitSizeOf<uint32_t>());
- dst.StoreBits(bit_index, src.LoadBits(bit_index, num_bits), num_bits);
- }
- }
- }
+ size_t bit_offset = 0;
+ stack_maps_.Encode(&out_, &bit_offset);
+ register_masks_.Encode(&out_, &bit_offset);
+ stack_masks_.Encode(&out_, &bit_offset);
+ invoke_infos_.Encode(&out_, &bit_offset);
+ inline_infos_.Encode(&out_, &bit_offset);
+ dex_register_masks_.Encode(&out_, &bit_offset);
+ dex_register_maps_.Encode(&out_, &bit_offset);
+ dex_register_catalog_.Encode(&out_, &bit_offset);
return UnsignedLeb128Size(out_.size()) + out_.size();
}
void StackMapStream::FillInCodeInfo(MemoryRegion region) {
- DCHECK_EQ(0u, current_entry_.dex_pc) << "EndStackMapEntry not called after BeginStackMapEntry";
+ DCHECK(in_stack_map_ == false) << "Mismatched Begin/End calls";
+ DCHECK(in_inline_info_ == false) << "Mismatched Begin/End calls";
DCHECK_NE(0u, out_.size()) << "PrepareForFillIn not called before FillIn";
DCHECK_EQ(region.size(), UnsignedLeb128Size(out_.size()) + out_.size());
uint8_t* ptr = EncodeUnsignedLeb128(region.begin(), out_.size());
region.CopyFromVector(ptr - region.begin(), out_);
- // Verify all written data in debug build.
- if (kIsDebugBuild) {
- CheckCodeInfo(region);
- }
-}
-
-void StackMapStream::FillInDexRegisterMap(DexRegisterMap dex_register_map,
- uint32_t num_dex_registers,
- const BitVector& live_dex_registers_mask,
- uint32_t start_index_in_dex_register_locations) const {
- dex_register_map.SetLiveBitMask(num_dex_registers, live_dex_registers_mask);
- // Set the dex register location mapping data.
- size_t number_of_live_dex_registers = live_dex_registers_mask.NumSetBits();
- DCHECK_LE(number_of_live_dex_registers, dex_register_locations_.size());
- DCHECK_LE(start_index_in_dex_register_locations,
- dex_register_locations_.size() - number_of_live_dex_registers);
- for (size_t index_in_dex_register_locations = 0;
- index_in_dex_register_locations != number_of_live_dex_registers;
- ++index_in_dex_register_locations) {
- size_t location_catalog_entry_index = dex_register_locations_[
- start_index_in_dex_register_locations + index_in_dex_register_locations];
- dex_register_map.SetLocationCatalogEntryIndex(
- index_in_dex_register_locations,
- location_catalog_entry_index,
- num_dex_registers,
- location_catalog_entries_.size());
- }
-}
-
-size_t StackMapStream::AddDexRegisterMapEntry(const DexRegisterMapEntry& entry) {
- const size_t current_entry_index = dex_register_entries_.size();
- auto entries_it = dex_map_hash_to_stack_map_indices_.find(entry.hash);
- if (entries_it == dex_map_hash_to_stack_map_indices_.end()) {
- // We don't have a perfect hash functions so we need a list to collect all stack maps
- // which might have the same dex register map.
- ScopedArenaVector<uint32_t> stack_map_indices(allocator_->Adapter(kArenaAllocStackMapStream));
- stack_map_indices.push_back(current_entry_index);
- dex_map_hash_to_stack_map_indices_.Put(entry.hash, std::move(stack_map_indices));
- } else {
- // We might have collisions, so we need to check whether or not we really have a match.
- for (uint32_t test_entry_index : entries_it->second) {
- if (DexRegisterMapEntryEquals(dex_register_entries_[test_entry_index], entry)) {
- return test_entry_index;
- }
- }
- entries_it->second.push_back(current_entry_index);
- }
- dex_register_entries_.push_back(entry);
- return current_entry_index;
-}
-
-bool StackMapStream::DexRegisterMapEntryEquals(const DexRegisterMapEntry& a,
- const DexRegisterMapEntry& b) const {
- if ((a.live_dex_registers_mask == nullptr) != (b.live_dex_registers_mask == nullptr)) {
- return false;
- }
- if (a.num_dex_registers != b.num_dex_registers) {
- return false;
- }
- if (a.num_dex_registers != 0u) {
- DCHECK(a.live_dex_registers_mask != nullptr);
- DCHECK(b.live_dex_registers_mask != nullptr);
- if (!a.live_dex_registers_mask->Equal(b.live_dex_registers_mask)) {
- return false;
- }
- size_t number_of_live_dex_registers = a.live_dex_registers_mask->NumSetBits();
- DCHECK_LE(number_of_live_dex_registers, dex_register_locations_.size());
- DCHECK_LE(a.locations_start_index,
- dex_register_locations_.size() - number_of_live_dex_registers);
- DCHECK_LE(b.locations_start_index,
- dex_register_locations_.size() - number_of_live_dex_registers);
- auto a_begin = dex_register_locations_.begin() + a.locations_start_index;
- auto b_begin = dex_register_locations_.begin() + b.locations_start_index;
- if (!std::equal(a_begin, a_begin + number_of_live_dex_registers, b_begin)) {
- return false;
- }
- }
- return true;
-}
-
-// Helper for CheckCodeInfo - check that register map has the expected content.
-void StackMapStream::CheckDexRegisterMap(const CodeInfo& code_info,
- const DexRegisterMap& dex_register_map,
- size_t num_dex_registers,
- BitVector* live_dex_registers_mask,
- size_t dex_register_locations_index) const {
- for (size_t reg = 0; reg < num_dex_registers; reg++) {
- // Find the location we tried to encode.
- DexRegisterLocation expected = DexRegisterLocation::None();
- if (live_dex_registers_mask->IsBitSet(reg)) {
- size_t catalog_index = dex_register_locations_[dex_register_locations_index++];
- expected = location_catalog_entries_[catalog_index];
- }
- // Compare to the seen location.
- if (expected.GetKind() == DexRegisterLocation::Kind::kNone) {
- DCHECK(!dex_register_map.IsValid() || !dex_register_map.IsDexRegisterLive(reg))
- << dex_register_map.IsValid() << " " << dex_register_map.IsDexRegisterLive(reg);
- } else {
- DCHECK(dex_register_map.IsDexRegisterLive(reg));
- DexRegisterLocation seen = dex_register_map.GetDexRegisterLocation(
- reg, num_dex_registers, code_info);
- DCHECK_EQ(expected.GetKind(), seen.GetKind());
- DCHECK_EQ(expected.GetValue(), seen.GetValue());
- }
- }
- if (num_dex_registers == 0) {
- DCHECK(!dex_register_map.IsValid());
- }
-}
-
-size_t StackMapStream::PrepareRegisterMasks() {
- register_masks_.resize(stack_maps_.size(), 0u);
- ScopedArenaUnorderedMap<uint32_t, size_t> dedupe(allocator_->Adapter(kArenaAllocStackMapStream));
- for (StackMapEntry& stack_map : stack_maps_) {
- const size_t index = dedupe.size();
- stack_map.register_mask_index = dedupe.emplace(stack_map.register_mask, index).first->second;
- register_masks_[index] = stack_map.register_mask;
- }
- return dedupe.size();
-}
-
-void StackMapStream::PrepareMethodIndices() {
- CHECK(method_indices_.empty());
- method_indices_.resize(stack_maps_.size() + inline_infos_.size());
- ScopedArenaUnorderedMap<uint32_t, size_t> dedupe(allocator_->Adapter(kArenaAllocStackMapStream));
- for (StackMapEntry& stack_map : stack_maps_) {
- const size_t index = dedupe.size();
- const uint32_t method_index = stack_map.dex_method_index;
- if (method_index != dex::kDexNoIndex) {
- stack_map.dex_method_index_idx = dedupe.emplace(method_index, index).first->second;
- method_indices_[index] = method_index;
- }
- }
- for (InlineInfoEntry& inline_info : inline_infos_) {
- const size_t index = dedupe.size();
- const uint32_t method_index = inline_info.method_index;
- CHECK_NE(method_index, dex::kDexNoIndex);
- inline_info.dex_method_index_idx = dedupe.emplace(method_index, index).first->second;
- method_indices_[index] = method_index;
- }
- method_indices_.resize(dedupe.size());
-}
-
-
-size_t StackMapStream::PrepareStackMasks(size_t entry_size_in_bits) {
- // Preallocate memory since we do not want it to move (the dedup map will point into it).
- const size_t byte_entry_size = RoundUp(entry_size_in_bits, kBitsPerByte) / kBitsPerByte;
- stack_masks_.resize(byte_entry_size * stack_maps_.size(), 0u);
- // For deduplicating we store the stack masks as byte packed for simplicity. We can bit pack later
- // when copying out from stack_masks_.
- ScopedArenaUnorderedMap<MemoryRegion,
- size_t,
- FNVHash<MemoryRegion>,
- MemoryRegion::ContentEquals> dedup(
- stack_maps_.size(), allocator_->Adapter(kArenaAllocStackMapStream));
- for (StackMapEntry& stack_map : stack_maps_) {
- size_t index = dedup.size();
- MemoryRegion stack_mask(stack_masks_.data() + index * byte_entry_size, byte_entry_size);
- BitMemoryRegion stack_mask_bits(stack_mask);
- for (size_t i = 0; i < entry_size_in_bits; i++) {
- stack_mask_bits.StoreBit(i, stack_map.sp_mask != nullptr && stack_map.sp_mask->IsBitSet(i));
- }
- stack_map.stack_mask_index = dedup.emplace(stack_mask, index).first->second;
- }
- return dedup.size();
-}
-
-// Check that all StackMapStream inputs are correctly encoded by trying to read them back.
-void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
- CodeInfo code_info(region);
- DCHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size());
- DCHECK_EQ(code_info.GetNumberOfStackMaskBits(), static_cast<uint32_t>(stack_mask_max_ + 1));
- DCHECK_EQ(code_info.GetNumberOfLocationCatalogEntries(), location_catalog_entries_.size());
- size_t invoke_info_index = 0;
- for (size_t s = 0; s < stack_maps_.size(); ++s) {
- const StackMap stack_map = code_info.GetStackMapAt(s);
- StackMapEntry entry = stack_maps_[s];
-
- // Check main stack map fields.
- DCHECK_EQ(stack_map.GetNativePcOffset(instruction_set_),
- entry.native_pc_code_offset.Uint32Value(instruction_set_));
- DCHECK_EQ(stack_map.GetDexPc(), entry.dex_pc);
- DCHECK_EQ(stack_map.GetRegisterMaskIndex(), entry.register_mask_index);
- DCHECK_EQ(code_info.GetRegisterMaskOf(stack_map), entry.register_mask);
- const size_t num_stack_mask_bits = code_info.GetNumberOfStackMaskBits();
- DCHECK_EQ(stack_map.GetStackMaskIndex(), entry.stack_mask_index);
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
- if (entry.sp_mask != nullptr) {
- DCHECK_GE(stack_mask.size_in_bits(), entry.sp_mask->GetNumberOfBits());
- for (size_t b = 0; b < num_stack_mask_bits; b++) {
- DCHECK_EQ(stack_mask.LoadBit(b), entry.sp_mask->IsBitSet(b));
- }
- } else {
- for (size_t b = 0; b < num_stack_mask_bits; b++) {
- DCHECK_EQ(stack_mask.LoadBit(b), 0u);
- }
- }
- if (entry.dex_method_index != dex::kDexNoIndex) {
- InvokeInfo invoke_info = code_info.GetInvokeInfo(invoke_info_index);
- DCHECK_EQ(invoke_info.GetNativePcOffset(instruction_set_),
- entry.native_pc_code_offset.Uint32Value(instruction_set_));
- DCHECK_EQ(invoke_info.GetInvokeType(), entry.invoke_type);
- DCHECK_EQ(invoke_info.GetMethodIndexIdx(), entry.dex_method_index_idx);
- invoke_info_index++;
- }
- CheckDexRegisterMap(code_info,
- code_info.GetDexRegisterMapOf(
- stack_map, entry.dex_register_entry.num_dex_registers),
- entry.dex_register_entry.num_dex_registers,
- entry.dex_register_entry.live_dex_registers_mask,
- entry.dex_register_entry.locations_start_index);
-
- // Check inline info.
- DCHECK_EQ(stack_map.HasInlineInfo(), (entry.inlining_depth != 0));
- if (entry.inlining_depth != 0) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- DCHECK_EQ(inline_info.GetDepth(), entry.inlining_depth);
- for (size_t d = 0; d < entry.inlining_depth; ++d) {
- size_t inline_info_index = entry.inline_infos_start_index + d;
- DCHECK_LT(inline_info_index, inline_infos_.size());
- InlineInfoEntry inline_entry = inline_infos_[inline_info_index];
- DCHECK_EQ(inline_info.GetDexPcAtDepth(d), inline_entry.dex_pc);
- if (inline_info.EncodesArtMethodAtDepth(d)) {
- DCHECK_EQ(inline_info.GetArtMethodAtDepth(d),
- inline_entry.method);
- } else {
- const size_t method_index_idx =
- inline_info.GetMethodIndexIdxAtDepth(d);
- DCHECK_EQ(method_index_idx, inline_entry.dex_method_index_idx);
- DCHECK_EQ(method_indices_[method_index_idx], inline_entry.method_index);
- }
-
- CheckDexRegisterMap(code_info,
- code_info.GetDexRegisterMapAtDepth(
- d,
- inline_info,
- inline_entry.dex_register_entry.num_dex_registers),
- inline_entry.dex_register_entry.num_dex_registers,
- inline_entry.dex_register_entry.live_dex_registers_mask,
- inline_entry.dex_register_entry.locations_start_index);
- }
+ // Verify all written data (usually only in debug builds).
+ if (kVerifyStackMaps) {
+ CodeInfo code_info(region);
+ CHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size());
+ for (const auto& dcheck : dchecks_) {
+ dcheck(code_info);
}
}
}
size_t StackMapStream::ComputeMethodInfoSize() const {
DCHECK_NE(0u, out_.size()) << "PrepareForFillIn not called before " << __FUNCTION__;
- return MethodInfo::ComputeSize(method_indices_.size());
+ return MethodInfo::ComputeSize(method_infos_.size());
}
} // namespace art
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index ea97cf6530..c758bca951 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -17,42 +17,20 @@
#ifndef ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_
#define ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_
+#include "base/allocator.h"
+#include "base/arena_bit_vector.h"
+#include "base/bit_table.h"
#include "base/bit_vector-inl.h"
-#include "base/hash_map.h"
#include "base/memory_region.h"
#include "base/scoped_arena_containers.h"
#include "base/value_object.h"
+#include "dex_register_location.h"
#include "method_info.h"
#include "nodes.h"
-#include "stack_map.h"
namespace art {
-// Helper to build art::StackMapStream::LocationCatalogEntriesIndices.
-class LocationCatalogEntriesIndicesEmptyFn {
- public:
- void MakeEmpty(std::pair<DexRegisterLocation, size_t>& item) const {
- item.first = DexRegisterLocation::None();
- }
- bool IsEmpty(const std::pair<DexRegisterLocation, size_t>& item) const {
- return item.first == DexRegisterLocation::None();
- }
-};
-
-// Hash function for art::StackMapStream::LocationCatalogEntriesIndices.
-// This hash function does not create collisions.
-class DexRegisterLocationHashFn {
- public:
- size_t operator()(DexRegisterLocation key) const {
- // Concatenate `key`s fields to create a 64-bit value to be hashed.
- int64_t kind_and_value =
- (static_cast<int64_t>(key.kind_) << 32) | static_cast<int64_t>(key.value_);
- return inner_hash_fn_(kind_and_value);
- }
- private:
- std::hash<int64_t> inner_hash_fn_;
-};
-
+class CodeInfo;
/**
* Collects and builds stack maps for a method. All the stack maps
@@ -61,74 +39,26 @@ class DexRegisterLocationHashFn {
class StackMapStream : public ValueObject {
public:
explicit StackMapStream(ScopedArenaAllocator* allocator, InstructionSet instruction_set)
- : allocator_(allocator),
- instruction_set_(instruction_set),
- stack_maps_(allocator->Adapter(kArenaAllocStackMapStream)),
- location_catalog_entries_(allocator->Adapter(kArenaAllocStackMapStream)),
- location_catalog_entries_indices_(allocator->Adapter(kArenaAllocStackMapStream)),
- dex_register_locations_(allocator->Adapter(kArenaAllocStackMapStream)),
- inline_infos_(allocator->Adapter(kArenaAllocStackMapStream)),
- stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
- register_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
- method_indices_(allocator->Adapter(kArenaAllocStackMapStream)),
- dex_register_entries_(allocator->Adapter(kArenaAllocStackMapStream)),
- stack_mask_max_(-1),
+ : instruction_set_(instruction_set),
+ stack_maps_(allocator),
+ register_masks_(allocator),
+ stack_masks_(allocator),
+ invoke_infos_(allocator),
+ inline_infos_(allocator),
+ dex_register_masks_(allocator),
+ dex_register_maps_(allocator),
+ dex_register_catalog_(allocator),
out_(allocator->Adapter(kArenaAllocStackMapStream)),
- dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(),
- allocator->Adapter(kArenaAllocStackMapStream)),
- current_entry_(),
- current_inline_info_(),
- current_dex_register_(0),
- in_inline_frame_(false) {
- stack_maps_.reserve(10);
- out_.reserve(64);
- location_catalog_entries_.reserve(4);
- dex_register_locations_.reserve(10 * 4);
- inline_infos_.reserve(2);
+ method_infos_(allocator),
+ lazy_stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
+ in_stack_map_(false),
+ in_inline_info_(false),
+ current_inline_infos_(0),
+ current_dex_registers_(allocator->Adapter(kArenaAllocStackMapStream)),
+ temp_dex_register_mask_(allocator, 32, true, kArenaAllocStackMapStream),
+ temp_dex_register_map_(allocator->Adapter(kArenaAllocStackMapStream)) {
}
- // A dex register map entry for a single stack map entry, contains what registers are live as
- // well as indices into the location catalog.
- class DexRegisterMapEntry {
- public:
- static const uint32_t kOffsetUnassigned = -1;
-
- BitVector* live_dex_registers_mask;
- uint32_t num_dex_registers;
- size_t locations_start_index;
- // Computed fields
- size_t hash = 0;
- uint32_t offset = kOffsetUnassigned;
-
- size_t ComputeSize(size_t catalog_size) const;
- };
-
- // See runtime/stack_map.h to know what these fields contain.
- struct StackMapEntry {
- uint32_t dex_pc;
- CodeOffset native_pc_code_offset;
- uint32_t register_mask;
- BitVector* sp_mask;
- uint32_t inlining_depth;
- size_t inline_infos_start_index;
- uint32_t stack_mask_index;
- uint32_t register_mask_index;
- DexRegisterMapEntry dex_register_entry;
- size_t dex_register_map_index;
- InvokeType invoke_type;
- uint32_t dex_method_index;
- uint32_t dex_method_index_idx; // Index into dex method index table.
- };
-
- struct InlineInfoEntry {
- uint32_t dex_pc; // dex::kDexNoIndex for intrinsified native methods.
- ArtMethod* method;
- uint32_t method_index;
- DexRegisterMapEntry dex_register_entry;
- size_t dex_register_map_index;
- uint32_t dex_method_index_idx; // Index into the dex method index table.
- };
-
void BeginStackMapEntry(uint32_t dex_pc,
uint32_t native_pc_offset,
uint32_t register_mask,
@@ -151,14 +81,8 @@ class StackMapStream : public ValueObject {
return stack_maps_.size();
}
- const StackMapEntry& GetStackMap(size_t i) const {
- return stack_maps_[i];
- }
-
- void SetStackMapNativePcOffset(size_t i, uint32_t native_pc_offset) {
- stack_maps_[i].native_pc_code_offset =
- CodeOffset::FromOffset(native_pc_offset, instruction_set_);
- }
+ uint32_t GetStackMapNativePcOffset(size_t i);
+ void SetStackMapNativePcOffset(size_t i, uint32_t native_pc_offset);
// Prepares the stream to fill in a memory region. Must be called before FillIn.
// Returns the size (in bytes) needed to store this stream.
@@ -169,68 +93,82 @@ class StackMapStream : public ValueObject {
size_t ComputeMethodInfoSize() const;
private:
- size_t ComputeDexRegisterLocationCatalogSize() const;
-
- // Returns the number of unique stack masks.
- size_t PrepareStackMasks(size_t entry_size_in_bits);
+ static constexpr uint32_t kNoValue = -1;
- // Returns the number of unique register masks.
- size_t PrepareRegisterMasks();
+ // The fields must be uint32_t and mirror the StackMap accessor in stack_map.h!
+ struct StackMapEntry {
+ uint32_t packed_native_pc;
+ uint32_t dex_pc;
+ uint32_t register_mask_index;
+ uint32_t stack_mask_index;
+ uint32_t inline_info_index;
+ uint32_t dex_register_mask_index;
+ uint32_t dex_register_map_index;
+ };
- // Prepare and deduplicate method indices.
- void PrepareMethodIndices();
+ // The fields must be uint32_t and mirror the InlineInfo accessor in stack_map.h!
+ struct InlineInfoEntry {
+ uint32_t is_last;
+ uint32_t dex_pc;
+ uint32_t method_info_index;
+ uint32_t art_method_hi;
+ uint32_t art_method_lo;
+ uint32_t dex_register_mask_index;
+ uint32_t dex_register_map_index;
+ };
- // Deduplicate entry if possible and return the corresponding index into dex_register_entries_
- // array. If entry is not a duplicate, a new entry is added to dex_register_entries_.
- size_t AddDexRegisterMapEntry(const DexRegisterMapEntry& entry);
+ // The fields must be uint32_t and mirror the InvokeInfo accessor in stack_map.h!
+ struct InvokeInfoEntry {
+ uint32_t packed_native_pc;
+ uint32_t invoke_type;
+ uint32_t method_info_index;
+ };
- // Return true if the two dex register map entries are equal.
- bool DexRegisterMapEntryEquals(const DexRegisterMapEntry& a, const DexRegisterMapEntry& b) const;
+ // The fields must be uint32_t and mirror the DexRegisterInfo accessor in stack_map.h!
+ struct DexRegisterEntry {
+ uint32_t kind;
+ uint32_t packed_value;
+ };
- // Fill in the corresponding entries of a register map.
- void FillInDexRegisterMap(DexRegisterMap dex_register_map,
- uint32_t num_dex_registers,
- const BitVector& live_dex_registers_mask,
- uint32_t start_index_in_dex_register_locations) const;
+ // The fields must be uint32_t and mirror the RegisterMask accessor in stack_map.h!
+ struct RegisterMaskEntry {
+ uint32_t value;
+ uint32_t shift;
+ };
- void CheckDexRegisterMap(const CodeInfo& code_info,
- const DexRegisterMap& dex_register_map,
- size_t num_dex_registers,
- BitVector* live_dex_registers_mask,
- size_t dex_register_locations_index) const;
- void CheckCodeInfo(MemoryRegion region) const;
+ void CreateDexRegisterMap();
- ScopedArenaAllocator* const allocator_;
const InstructionSet instruction_set_;
- ScopedArenaVector<StackMapEntry> stack_maps_;
-
- // A catalog of unique [location_kind, register_value] pairs (per method).
- ScopedArenaVector<DexRegisterLocation> location_catalog_entries_;
- // Map from Dex register location catalog entries to their indices in the
- // location catalog.
- using LocationCatalogEntriesIndices = ScopedArenaHashMap<DexRegisterLocation,
- size_t,
- LocationCatalogEntriesIndicesEmptyFn,
- DexRegisterLocationHashFn>;
- LocationCatalogEntriesIndices location_catalog_entries_indices_;
-
- // A set of concatenated maps of Dex register locations indices to `location_catalog_entries_`.
- ScopedArenaVector<size_t> dex_register_locations_;
- ScopedArenaVector<InlineInfoEntry> inline_infos_;
- ScopedArenaVector<uint8_t> stack_masks_;
- ScopedArenaVector<uint32_t> register_masks_;
- ScopedArenaVector<uint32_t> method_indices_;
- ScopedArenaVector<DexRegisterMapEntry> dex_register_entries_;
- int stack_mask_max_;
-
+ BitTableBuilder<StackMapEntry> stack_maps_;
+ BitTableBuilder<RegisterMaskEntry> register_masks_;
+ BitmapTableBuilder stack_masks_;
+ BitTableBuilder<InvokeInfoEntry> invoke_infos_;
+ BitTableBuilder<InlineInfoEntry> inline_infos_;
+ BitmapTableBuilder dex_register_masks_;
+ BitTableBuilder<uint32_t> dex_register_maps_;
+ BitTableBuilder<DexRegisterEntry> dex_register_catalog_;
ScopedArenaVector<uint8_t> out_;
- ScopedArenaSafeMap<uint32_t, ScopedArenaVector<uint32_t>> dex_map_hash_to_stack_map_indices_;
+ BitTableBuilder<uint32_t> method_infos_;
+
+ ScopedArenaVector<BitVector*> lazy_stack_masks_;
+
+ // Variables which track the current state between Begin/End calls;
+ bool in_stack_map_;
+ bool in_inline_info_;
+ StackMapEntry current_stack_map_;
+ uint32_t current_inline_infos_;
+ ScopedArenaVector<DexRegisterLocation> current_dex_registers_;
+ size_t expected_num_dex_registers_;
+
+ // Temporary variables used in CreateDexRegisterMap.
+ // They are here so that we can reuse the reserved memory.
+ ArenaBitVector temp_dex_register_mask_;
+ ScopedArenaVector<uint32_t> temp_dex_register_map_;
- StackMapEntry current_entry_;
- InlineInfoEntry current_inline_info_;
- uint32_t current_dex_register_;
- bool in_inline_frame_;
+ // A set of lambda functions to be executed at the end to verify
+ // the encoded data. It is generally only used in debug builds.
+ std::vector<std::function<void(CodeInfo&)>> dchecks_;
DISALLOW_COPY_AND_ASSIGN(StackMapStream);
};
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 9db7588b3a..262c240bc7 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -32,10 +32,10 @@ static bool CheckStackMask(
const StackMap& stack_map,
const BitVector& bit_vector) {
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
- if (bit_vector.GetNumberOfBits() > code_info.GetNumberOfStackMaskBits()) {
+ if (bit_vector.GetNumberOfBits() > stack_mask.size_in_bits()) {
return false;
}
- for (size_t i = 0; i < code_info.GetNumberOfStackMaskBits(); ++i) {
+ for (size_t i = 0; i < stack_mask.size_in_bits(); ++i) {
if (stack_mask.LoadBit(i) != bit_vector.IsBitSet(i)) {
return false;
}
@@ -45,6 +45,8 @@ static bool CheckStackMask(
using Kind = DexRegisterLocation::Kind;
+constexpr static uint32_t kPcAlign = GetInstructionSetInstructionAlignment(kRuntimeISA);
+
TEST(StackMapTest, Test1) {
MallocArenaPool pool;
ArenaStack arena_stack(&pool);
@@ -53,7 +55,7 @@ TEST(StackMapTest, Test1) {
ArenaBitVector sp_mask(&allocator, 0, false);
size_t number_of_dex_registers = 2;
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Short location.
stream.EndStackMapEntry();
@@ -68,18 +70,12 @@ TEST(StackMapTest, Test1) {
uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(2u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
- // The Dex register location catalog contains:
- // - one 1-byte short Dex register location, and
- // - one 5-byte large Dex register location.
- size_t expected_location_catalog_size = 1u + 5u;
- ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64 * kPcAlign)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(64u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask));
@@ -89,37 +85,17 @@ TEST(StackMapTest, Test1) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_dex_register_map_size = 1u + 1u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(0u, index0);
- ASSERT_EQ(1u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
ASSERT_EQ(Kind::kInStack, location0.GetKind());
ASSERT_EQ(Kind::kConstant, location1.GetKind());
- ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
- ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
@@ -138,7 +114,7 @@ TEST(StackMapTest, Test2) {
sp_mask1.SetBit(4);
size_t number_of_dex_registers = 2;
size_t number_of_dex_registers_in_inline_info = 0;
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask1, number_of_dex_registers, 2);
stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
@@ -150,7 +126,7 @@ TEST(StackMapTest, Test2) {
ArenaBitVector sp_mask2(&allocator, 0, true);
sp_mask2.SetBit(3);
sp_mask2.SetBit(8);
- stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(1, 128 * kPcAlign, 0xFF, &sp_mask2, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 18); // Short location.
stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location.
stream.EndStackMapEntry();
@@ -158,7 +134,7 @@ TEST(StackMapTest, Test2) {
ArenaBitVector sp_mask3(&allocator, 0, true);
sp_mask3.SetBit(1);
sp_mask3.SetBit(5);
- stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(2, 192 * kPcAlign, 0xAB, &sp_mask3, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 6); // Short location.
stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8); // Short location.
stream.EndStackMapEntry();
@@ -166,7 +142,7 @@ TEST(StackMapTest, Test2) {
ArenaBitVector sp_mask4(&allocator, 0, true);
sp_mask4.SetBit(6);
sp_mask4.SetBit(7);
- stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(3, 256 * kPcAlign, 0xCD, &sp_mask4, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location, same in stack map 2.
stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1); // Short location.
stream.EndStackMapEntry();
@@ -181,20 +157,14 @@ TEST(StackMapTest, Test2) {
uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(7u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
- // The Dex register location catalog contains:
- // - six 1-byte short Dex register locations, and
- // - one 5-byte large Dex register location.
- size_t expected_location_catalog_size = 6u * 1u + 5u;
- ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
// First stack map.
{
StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64 * kPcAlign)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(64u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
@@ -204,37 +174,17 @@ TEST(StackMapTest, Test2) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_dex_register_map_size = 1u + 1u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(0u, index0);
- ASSERT_EQ(1u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
ASSERT_EQ(Kind::kInStack, location0.GetKind());
ASSERT_EQ(Kind::kConstant, location1.GetKind());
- ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
- ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
@@ -251,9 +201,9 @@ TEST(StackMapTest, Test2) {
{
StackMap stack_map = code_info.GetStackMapAt(1);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u * kPcAlign)));
ASSERT_EQ(1u, stack_map.GetDexPc());
- ASSERT_EQ(128u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(128u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask2));
@@ -263,38 +213,17 @@ TEST(StackMapTest, Test2) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_dex_register_map_size = 1u + 1u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(18, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(3, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(2u, index0);
- ASSERT_EQ(3u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(18, dex_register_map.GetMachineRegister(0));
+ ASSERT_EQ(3, dex_register_map.GetMachineRegister(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(2);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(3);
ASSERT_EQ(Kind::kInRegister, location0.GetKind());
ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
- ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
- ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
ASSERT_EQ(18, location0.GetValue());
ASSERT_EQ(3, location1.GetValue());
@@ -305,9 +234,9 @@ TEST(StackMapTest, Test2) {
{
StackMap stack_map = code_info.GetStackMapAt(2);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u * kPcAlign)));
ASSERT_EQ(2u, stack_map.GetDexPc());
- ASSERT_EQ(192u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(192u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask3));
@@ -317,38 +246,17 @@ TEST(StackMapTest, Test2) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_dex_register_map_size = 1u + 1u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(6, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(8, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(4u, index0);
- ASSERT_EQ(5u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(6, dex_register_map.GetMachineRegister(0));
+ ASSERT_EQ(8, dex_register_map.GetMachineRegister(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(4);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(5);
ASSERT_EQ(Kind::kInRegister, location0.GetKind());
ASSERT_EQ(Kind::kInRegisterHigh, location1.GetKind());
- ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
- ASSERT_EQ(Kind::kInRegisterHigh, location1.GetInternalKind());
ASSERT_EQ(6, location0.GetValue());
ASSERT_EQ(8, location1.GetValue());
@@ -359,9 +267,9 @@ TEST(StackMapTest, Test2) {
{
StackMap stack_map = code_info.GetStackMapAt(3);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u * kPcAlign)));
ASSERT_EQ(3u, stack_map.GetDexPc());
- ASSERT_EQ(256u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(256u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask4));
@@ -371,38 +279,17 @@ TEST(StackMapTest, Test2) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_dex_register_map_size = 1u + 1u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(3, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(1, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(3u, index0); // Shared with second stack map.
- ASSERT_EQ(6u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(3, dex_register_map.GetMachineRegister(0));
+ ASSERT_EQ(1, dex_register_map.GetMachineRegister(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(3);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(6);
ASSERT_EQ(Kind::kInFpuRegister, location0.GetKind());
ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetKind());
- ASSERT_EQ(Kind::kInFpuRegister, location0.GetInternalKind());
- ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetInternalKind());
ASSERT_EQ(3, location0.GetValue());
ASSERT_EQ(1, location1.GetValue());
@@ -422,7 +309,7 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
sp_mask1.SetBit(4);
const size_t number_of_dex_registers = 2;
const size_t number_of_dex_registers_in_inline_info = 2;
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 1);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask1, number_of_dex_registers, 1);
stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
@@ -441,20 +328,14 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(2u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
- // The Dex register location catalog contains:
- // - one 1-byte short Dex register locations, and
- // - one 5-byte large Dex register location.
- const size_t expected_location_catalog_size = 1u + 5u;
- ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
// First stack map.
{
StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64 * kPcAlign)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(64u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
@@ -463,35 +344,17 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers));
ASSERT_TRUE(map.IsDexRegisterLive(0));
ASSERT_TRUE(map.IsDexRegisterLive(1));
- ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask, and
- // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
- size_t expected_map_size = 1u + 1u;
- ASSERT_EQ(expected_map_size, map.Size());
-
- ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstant,
- map.GetLocationKind(1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kInStack,
- map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstantLargeValue,
- map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
- ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
- ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info));
-
- const size_t index0 =
- map.GetLocationCatalogEntryIndex(0, number_of_dex_registers, number_of_catalog_entries);
- const size_t index1 =
- map.GetLocationCatalogEntryIndex(1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(0u, index0);
- ASSERT_EQ(1u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
+ ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kConstant, map.GetLocationKind(1));
+ ASSERT_EQ(0, map.GetStackOffsetInBytes(0));
+ ASSERT_EQ(-2, map.GetConstant(1));
+
+ DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
ASSERT_EQ(Kind::kInStack, location0.GetKind());
ASSERT_EQ(Kind::kConstant, location1.GetKind());
- ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
- ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
@@ -499,8 +362,8 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
// one.
ASSERT_TRUE(stack_map.HasInlineInfo());
InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
- EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(0),
- stack_map.GetDexRegisterMapOffset());
+ EXPECT_EQ(inline_info.GetDexRegisterMapIndexAtDepth(0),
+ stack_map.GetDexRegisterMapIndex());
}
}
@@ -512,7 +375,7 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
ArenaBitVector sp_mask(&allocator, 0, false);
uint32_t number_of_dex_registers = 2;
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kNone, 0); // No location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
@@ -527,17 +390,12 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(1u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
- // The Dex register location catalog contains:
- // - one 5-byte large Dex register location.
- size_t expected_location_catalog_size = 5u;
- ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64 * kPcAlign)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(64u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
ASSERT_TRUE(stack_map.HasDexRegisterMap());
@@ -545,107 +403,19 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
- ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The Dex register map contains:
- // - one 1-byte live bit mask.
- // No space is allocated for the sole location catalog entry index, as it is useless.
- size_t expected_dex_register_map_size = 1u + 0u;
- ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
-
- ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info));
- ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
-
- size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
- 0, number_of_dex_registers, number_of_catalog_entries);
- size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
- 1, number_of_dex_registers, number_of_catalog_entries);
- ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
- ASSERT_EQ(0u, index1);
- DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
- DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
- ASSERT_EQ(Kind::kNone, location0.GetKind());
+ ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters());
+
+ ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(0));
+ ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+
+ DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(0);
ASSERT_EQ(Kind::kConstant, location1.GetKind());
- ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
- ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
- ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
ASSERT_FALSE(stack_map.HasInlineInfo());
}
-// Generate a stack map whose dex register offset is
-// StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
-// not treat it as kNoDexRegisterMap.
-TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
- MallocArenaPool pool;
- ArenaStack arena_stack(&pool);
- ScopedArenaAllocator allocator(&arena_stack);
- StackMapStream stream(&allocator, kRuntimeISA);
-
- ArenaBitVector sp_mask(&allocator, 0, false);
- uint32_t number_of_dex_registers = 1024;
- // Create the first stack map (and its Dex register map).
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
- uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
- for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
- // Use two different Dex register locations to populate this map,
- // as using a single value (in the whole CodeInfo object) would
- // make this Dex register mapping data empty (see
- // art::DexRegisterMap::SingleEntrySizeInBits).
- stream.AddDexRegisterEntry(Kind::kConstant, i % 2); // Short location.
- }
- stream.EndStackMapEntry();
- // Create the second stack map (and its Dex register map).
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
- for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
- stream.AddDexRegisterEntry(Kind::kConstant, 0); // Short location.
- }
- stream.EndStackMapEntry();
-
- size_t size = stream.PrepareForFillIn();
- void* memory = allocator.Alloc(size, kArenaAllocMisc);
- MemoryRegion region(memory, size);
- stream.FillInCodeInfo(region);
-
- CodeInfo code_info(region);
- // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
- // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
- // has a size of 1 bit.
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
- ASSERT_EQ(2u, number_of_catalog_entries);
- ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
-
- // The first Dex register map contains:
- // - a live register bit mask for 1024 registers (that is, 128 bytes of
- // data); and
- // - Dex register mapping information for 1016 1-bit Dex (live) register
- // locations (that is, 127 bytes of data).
- // Hence it has a size of 255 bytes, and therefore...
- ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
- StackMap stack_map0 = code_info.GetStackMapAt(0);
- DexRegisterMap dex_register_map0 =
- code_info.GetDexRegisterMapOf(stack_map0, number_of_dex_registers);
- ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
- number_of_catalog_entries));
- ASSERT_EQ(255u, dex_register_map0.Size());
-
- StackMap stack_map1 = code_info.GetStackMapAt(1);
- ASSERT_TRUE(stack_map1.HasDexRegisterMap());
- // ...the offset of the second Dex register map (relative to the
- // beginning of the Dex register maps region) is 255 (i.e.,
- // kNoDexRegisterMapSmallEncoding).
- ASSERT_NE(stack_map1.GetDexRegisterMapOffset(),
- StackMap::kNoValue);
- ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(), 0xFFu);
-}
-
TEST(StackMapTest, TestShareDexRegisterMap) {
MallocArenaPool pool;
ArenaStack arena_stack(&pool);
@@ -655,17 +425,17 @@ TEST(StackMapTest, TestShareDexRegisterMap) {
ArenaBitVector sp_mask(&allocator, 0, false);
uint32_t number_of_dex_registers = 2;
// First stack map.
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
// Second stack map, which should share the same dex register map.
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
// Third stack map (doesn't share the dex register map).
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 2); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
@@ -680,28 +450,28 @@ TEST(StackMapTest, TestShareDexRegisterMap) {
// Verify first stack map.
StackMap sm0 = ci.GetStackMapAt(0);
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, number_of_dex_registers);
- ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci));
- ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci));
+ ASSERT_EQ(0, dex_registers0.GetMachineRegister(0));
+ ASSERT_EQ(-2, dex_registers0.GetConstant(1));
// Verify second stack map.
StackMap sm1 = ci.GetStackMapAt(1);
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, number_of_dex_registers);
- ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci));
- ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci));
+ ASSERT_EQ(0, dex_registers1.GetMachineRegister(0));
+ ASSERT_EQ(-2, dex_registers1.GetConstant(1));
// Verify third stack map.
StackMap sm2 = ci.GetStackMapAt(2);
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, number_of_dex_registers);
- ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci));
- ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci));
+ ASSERT_EQ(2, dex_registers2.GetMachineRegister(0));
+ ASSERT_EQ(-2, dex_registers2.GetConstant(1));
// Verify dex register map offsets.
- ASSERT_EQ(sm0.GetDexRegisterMapOffset(),
- sm1.GetDexRegisterMapOffset());
- ASSERT_NE(sm0.GetDexRegisterMapOffset(),
- sm2.GetDexRegisterMapOffset());
- ASSERT_NE(sm1.GetDexRegisterMapOffset(),
- sm2.GetDexRegisterMapOffset());
+ ASSERT_EQ(sm0.GetDexRegisterMapIndex(),
+ sm1.GetDexRegisterMapIndex());
+ ASSERT_NE(sm0.GetDexRegisterMapIndex(),
+ sm2.GetDexRegisterMapIndex());
+ ASSERT_NE(sm1.GetDexRegisterMapIndex(),
+ sm2.GetDexRegisterMapIndex());
}
TEST(StackMapTest, TestNoDexRegisterMap) {
@@ -712,11 +482,12 @@ TEST(StackMapTest, TestNoDexRegisterMap) {
ArenaBitVector sp_mask(&allocator, 0, false);
uint32_t number_of_dex_registers = 0;
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.EndStackMapEntry();
number_of_dex_registers = 1;
- stream.BeginStackMapEntry(1, 68, 0x4, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(1, 68 * kPcAlign, 0x4, &sp_mask, number_of_dex_registers, 0);
+ stream.AddDexRegisterEntry(Kind::kNone, 0);
stream.EndStackMapEntry();
size_t size = stream.PrepareForFillIn();
@@ -729,14 +500,12 @@ TEST(StackMapTest, TestNoDexRegisterMap) {
uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(0u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
- ASSERT_EQ(0u, location_catalog.Size());
StackMap stack_map = code_info.GetStackMapAt(0);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64 * kPcAlign)));
ASSERT_EQ(0u, stack_map.GetDexPc());
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(64u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
ASSERT_FALSE(stack_map.HasDexRegisterMap());
@@ -744,12 +513,12 @@ TEST(StackMapTest, TestNoDexRegisterMap) {
stack_map = code_info.GetStackMapAt(1);
ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68 * kPcAlign)));
ASSERT_EQ(1u, stack_map.GetDexPc());
- ASSERT_EQ(68u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(68u * kPcAlign, stack_map.GetNativePcOffset(kRuntimeISA));
ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_FALSE(stack_map.HasDexRegisterMap());
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
ASSERT_FALSE(stack_map.HasInlineInfo());
}
@@ -765,7 +534,7 @@ TEST(StackMapTest, InlineTest) {
sp_mask1.SetBit(4);
// First stack map.
- stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
+ stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask1, 2, 2);
stream.AddDexRegisterEntry(Kind::kInStack, 0);
stream.AddDexRegisterEntry(Kind::kConstant, 4);
@@ -781,7 +550,7 @@ TEST(StackMapTest, InlineTest) {
stream.EndStackMapEntry();
// Second stack map.
- stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
+ stream.BeginStackMapEntry(2, 22 * kPcAlign, 0x3, &sp_mask1, 2, 3);
stream.AddDexRegisterEntry(Kind::kInStack, 56);
stream.AddDexRegisterEntry(Kind::kConstant, 0);
@@ -799,13 +568,13 @@ TEST(StackMapTest, InlineTest) {
stream.EndStackMapEntry();
// Third stack map.
- stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
+ stream.BeginStackMapEntry(4, 56 * kPcAlign, 0x3, &sp_mask1, 2, 0);
stream.AddDexRegisterEntry(Kind::kNone, 0);
stream.AddDexRegisterEntry(Kind::kConstant, 4);
stream.EndStackMapEntry();
// Fourth stack map.
- stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
+ stream.BeginStackMapEntry(6, 78 * kPcAlign, 0x3, &sp_mask1, 2, 3);
stream.AddDexRegisterEntry(Kind::kInStack, 56);
stream.AddDexRegisterEntry(Kind::kConstant, 0);
@@ -833,8 +602,8 @@ TEST(StackMapTest, InlineTest) {
StackMap sm0 = ci.GetStackMapAt(0);
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, 2);
- ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
- ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
+ ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0));
+ ASSERT_EQ(4, dex_registers0.GetConstant(1));
InlineInfo if0 = ci.GetInlineInfoOf(sm0);
ASSERT_EQ(2u, if0.GetDepth());
@@ -844,12 +613,12 @@ TEST(StackMapTest, InlineTest) {
ASSERT_TRUE(if0.EncodesArtMethodAtDepth(1));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
- ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+ ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0));
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, 3);
- ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
- ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci));
- ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci));
+ ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0));
+ ASSERT_EQ(20, dex_registers2.GetConstant(1));
+ ASSERT_EQ(15, dex_registers2.GetMachineRegister(2));
}
{
@@ -857,8 +626,8 @@ TEST(StackMapTest, InlineTest) {
StackMap sm1 = ci.GetStackMapAt(1);
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, 2);
- ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
- ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
+ ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
+ ASSERT_EQ(0, dex_registers0.GetConstant(1));
InlineInfo if1 = ci.GetInlineInfoOf(sm1);
ASSERT_EQ(3u, if1.GetDepth());
@@ -870,12 +639,12 @@ TEST(StackMapTest, InlineTest) {
ASSERT_TRUE(if1.EncodesArtMethodAtDepth(2));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
- ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+ ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0));
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, 3);
- ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
- ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci));
- ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci));
+ ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0));
+ ASSERT_EQ(10, dex_registers2.GetConstant(1));
+ ASSERT_EQ(5, dex_registers2.GetMachineRegister(2));
ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
}
@@ -886,7 +655,7 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, 2);
ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
- ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
+ ASSERT_EQ(4, dex_registers0.GetConstant(1));
ASSERT_FALSE(sm2.HasInlineInfo());
}
@@ -895,8 +664,8 @@ TEST(StackMapTest, InlineTest) {
StackMap sm3 = ci.GetStackMapAt(3);
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, 2);
- ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
- ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
+ ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
+ ASSERT_EQ(0, dex_registers0.GetConstant(1));
InlineInfo if2 = ci.GetInlineInfoOf(sm3);
ASSERT_EQ(3u, if2.GetDepth());
@@ -910,34 +679,40 @@ TEST(StackMapTest, InlineTest) {
ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1);
- ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci));
+ ASSERT_EQ(2, dex_registers1.GetMachineRegister(0));
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2);
ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
- ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci));
+ ASSERT_EQ(3, dex_registers2.GetMachineRegister(1));
}
}
-TEST(StackMapTest, CodeOffsetTest) {
+TEST(StackMapTest, PackedNativePcTest) {
// Test minimum alignments, and decoding.
- CodeOffset offset_thumb2 =
- CodeOffset::FromOffset(kThumb2InstructionAlignment, InstructionSet::kThumb2);
- CodeOffset offset_arm64 =
- CodeOffset::FromOffset(kArm64InstructionAlignment, InstructionSet::kArm64);
- CodeOffset offset_x86 =
- CodeOffset::FromOffset(kX86InstructionAlignment, InstructionSet::kX86);
- CodeOffset offset_x86_64 =
- CodeOffset::FromOffset(kX86_64InstructionAlignment, InstructionSet::kX86_64);
- CodeOffset offset_mips =
- CodeOffset::FromOffset(kMipsInstructionAlignment, InstructionSet::kMips);
- CodeOffset offset_mips64 =
- CodeOffset::FromOffset(kMips64InstructionAlignment, InstructionSet::kMips64);
- EXPECT_EQ(offset_thumb2.Uint32Value(InstructionSet::kThumb2), kThumb2InstructionAlignment);
- EXPECT_EQ(offset_arm64.Uint32Value(InstructionSet::kArm64), kArm64InstructionAlignment);
- EXPECT_EQ(offset_x86.Uint32Value(InstructionSet::kX86), kX86InstructionAlignment);
- EXPECT_EQ(offset_x86_64.Uint32Value(InstructionSet::kX86_64), kX86_64InstructionAlignment);
- EXPECT_EQ(offset_mips.Uint32Value(InstructionSet::kMips), kMipsInstructionAlignment);
- EXPECT_EQ(offset_mips64.Uint32Value(InstructionSet::kMips64), kMips64InstructionAlignment);
+ uint32_t packed_thumb2 =
+ StackMap::PackNativePc(kThumb2InstructionAlignment, InstructionSet::kThumb2);
+ uint32_t packed_arm64 =
+ StackMap::PackNativePc(kArm64InstructionAlignment, InstructionSet::kArm64);
+ uint32_t packed_x86 =
+ StackMap::PackNativePc(kX86InstructionAlignment, InstructionSet::kX86);
+ uint32_t packed_x86_64 =
+ StackMap::PackNativePc(kX86_64InstructionAlignment, InstructionSet::kX86_64);
+ uint32_t packed_mips =
+ StackMap::PackNativePc(kMipsInstructionAlignment, InstructionSet::kMips);
+ uint32_t packed_mips64 =
+ StackMap::PackNativePc(kMips64InstructionAlignment, InstructionSet::kMips64);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_thumb2, InstructionSet::kThumb2),
+ kThumb2InstructionAlignment);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_arm64, InstructionSet::kArm64),
+ kArm64InstructionAlignment);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_x86, InstructionSet::kX86),
+ kX86InstructionAlignment);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_x86_64, InstructionSet::kX86_64),
+ kX86_64InstructionAlignment);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_mips, InstructionSet::kMips),
+ kMipsInstructionAlignment);
+ EXPECT_EQ(StackMap::UnpackNativePc(packed_mips64, InstructionSet::kMips64),
+ kMips64InstructionAlignment);
}
TEST(StackMapTest, TestDeduplicateStackMask) {
@@ -949,9 +724,9 @@ TEST(StackMapTest, TestDeduplicateStackMask) {
ArenaBitVector sp_mask(&allocator, 0, true);
sp_mask.SetBit(1);
sp_mask.SetBit(4);
- stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
+ stream.BeginStackMapEntry(0, 4 * kPcAlign, 0x3, &sp_mask, 0, 0);
stream.EndStackMapEntry();
- stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
+ stream.BeginStackMapEntry(0, 8 * kPcAlign, 0x3, &sp_mask, 0, 0);
stream.EndStackMapEntry();
size_t size = stream.PrepareForFillIn();
@@ -962,8 +737,8 @@ TEST(StackMapTest, TestDeduplicateStackMask) {
CodeInfo code_info(region);
ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
- StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4);
- StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8);
+ StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4 * kPcAlign);
+ StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8 * kPcAlign);
EXPECT_EQ(stack_map1.GetStackMaskIndex(),
stack_map2.GetStackMaskIndex());
}
@@ -976,13 +751,13 @@ TEST(StackMapTest, TestInvokeInfo) {
ArenaBitVector sp_mask(&allocator, 0, true);
sp_mask.SetBit(1);
- stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
+ stream.BeginStackMapEntry(0, 4 * kPcAlign, 0x3, &sp_mask, 0, 0);
stream.AddInvoke(kSuper, 1);
stream.EndStackMapEntry();
- stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
+ stream.BeginStackMapEntry(0, 8 * kPcAlign, 0x3, &sp_mask, 0, 0);
stream.AddInvoke(kStatic, 3);
stream.EndStackMapEntry();
- stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
+ stream.BeginStackMapEntry(0, 16 * kPcAlign, 0x3, &sp_mask, 0, 0);
stream.AddInvoke(kDirect, 65535);
stream.EndStackMapEntry();
@@ -999,9 +774,9 @@ TEST(StackMapTest, TestInvokeInfo) {
MethodInfo method_info(method_info_region.begin());
ASSERT_EQ(3u, code_info.GetNumberOfStackMaps());
- InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4));
- InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8));
- InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16));
+ InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4 * kPcAlign));
+ InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8 * kPcAlign));
+ InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16 * kPcAlign));
InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12));
EXPECT_FALSE(invoke_invalid.IsValid()); // No entry for that index.
EXPECT_TRUE(invoke1.IsValid());
@@ -1009,13 +784,13 @@ TEST(StackMapTest, TestInvokeInfo) {
EXPECT_TRUE(invoke3.IsValid());
EXPECT_EQ(invoke1.GetInvokeType(), kSuper);
EXPECT_EQ(invoke1.GetMethodIndex(method_info), 1u);
- EXPECT_EQ(invoke1.GetNativePcOffset(kRuntimeISA), 4u);
+ EXPECT_EQ(invoke1.GetNativePcOffset(kRuntimeISA), 4u * kPcAlign);
EXPECT_EQ(invoke2.GetInvokeType(), kStatic);
EXPECT_EQ(invoke2.GetMethodIndex(method_info), 3u);
- EXPECT_EQ(invoke2.GetNativePcOffset(kRuntimeISA), 8u);
+ EXPECT_EQ(invoke2.GetNativePcOffset(kRuntimeISA), 8u * kPcAlign);
EXPECT_EQ(invoke3.GetInvokeType(), kDirect);
EXPECT_EQ(invoke3.GetMethodIndex(method_info), 65535u);
- EXPECT_EQ(invoke3.GetNativePcOffset(kRuntimeISA), 16u);
+ EXPECT_EQ(invoke3.GetNativePcOffset(kRuntimeISA), 16u * kPcAlign);
}
} // namespace art
diff --git a/compiler/optimizing/superblock_cloner.cc b/compiler/optimizing/superblock_cloner.cc
index fad7729956..1b43618538 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -409,7 +409,7 @@ void SuperblockCloner::ResolvePhi(HPhi* phi) {
// Main algorithm methods.
//
-void SuperblockCloner::SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits) {
+void SuperblockCloner::SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits) const {
DCHECK(exits->empty());
for (uint32_t block_id : orig_bb_set_.Indexes()) {
HBasicBlock* block = GetBlockById(block_id);
@@ -521,6 +521,113 @@ void SuperblockCloner::ResolveDataFlow() {
}
//
+// Helpers for live-outs processing and Subgraph-closed SSA.
+//
+
+bool SuperblockCloner::CollectLiveOutsAndCheckClonable(HInstructionMap* live_outs) const {
+ DCHECK(live_outs->empty());
+ for (uint32_t idx : orig_bb_set_.Indexes()) {
+ HBasicBlock* block = GetBlockById(idx);
+
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
+ DCHECK(instr->IsClonable());
+
+ if (IsUsedOutsideRegion(instr, orig_bb_set_)) {
+ live_outs->FindOrAdd(instr, instr);
+ }
+ }
+
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
+ if (!instr->IsClonable()) {
+ return false;
+ }
+
+ if (IsUsedOutsideRegion(instr, orig_bb_set_)) {
+ // TODO: Investigate why HNewInstance, HCheckCast has a requirement for the input.
+ if (instr->IsLoadClass()) {
+ return false;
+ }
+ live_outs->FindOrAdd(instr, instr);
+ }
+ }
+ }
+ return true;
+}
+
+void SuperblockCloner::ConstructSubgraphClosedSSA() {
+ if (live_outs_.empty()) {
+ return;
+ }
+
+ ArenaVector<HBasicBlock*> exits(arena_->Adapter(kArenaAllocSuperblockCloner));
+ SearchForSubgraphExits(&exits);
+ if (exits.empty()) {
+ DCHECK(live_outs_.empty());
+ return;
+ }
+
+ DCHECK_EQ(exits.size(), 1u);
+ HBasicBlock* exit_block = exits[0];
+ // There should be no critical edges.
+ DCHECK_EQ(exit_block->GetPredecessors().size(), 1u);
+ DCHECK(exit_block->GetPhis().IsEmpty());
+
+ // For each live-out value insert a phi into the loop exit and replace all the value's uses
+ // external to the loop with this phi. The phi will have the original value as its only input;
+ // after copying is done FixSubgraphClosedSSAAfterCloning will add a corresponding copy of the
+ // original value as the second input thus merging data flow from the original and copy parts of
+ // the subgraph. Also update the record in the live_outs_ map from (value, value) to
+ // (value, new_phi).
+ for (auto live_out_it = live_outs_.begin(); live_out_it != live_outs_.end(); ++live_out_it) {
+ HInstruction* value = live_out_it->first;
+ HPhi* phi = new (arena_) HPhi(arena_, kNoRegNumber, 0, value->GetType());
+
+ if (value->GetType() == DataType::Type::kReference) {
+ phi->SetReferenceTypeInfo(value->GetReferenceTypeInfo());
+ }
+
+ exit_block->AddPhi(phi);
+ live_out_it->second = phi;
+
+ const HUseList<HInstruction*>& uses = value->GetUses();
+ for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
+ HInstruction* user = it->GetUser();
+ size_t index = it->GetIndex();
+ // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
+ ++it;
+ if (!IsInOrigBBSet(user->GetBlock())) {
+ user->ReplaceInput(phi, index);
+ }
+ }
+
+ const HUseList<HEnvironment*>& env_uses = value->GetEnvUses();
+ for (auto it = env_uses.begin(), e = env_uses.end(); it != e; /* ++it below */) {
+ HEnvironment* env = it->GetUser();
+ size_t index = it->GetIndex();
+ ++it;
+ if (!IsInOrigBBSet(env->GetHolder()->GetBlock())) {
+ env->ReplaceInput(phi, index);
+ }
+ }
+
+ phi->AddInput(value);
+ }
+}
+
+void SuperblockCloner::FixSubgraphClosedSSAAfterCloning() {
+ for (auto it : live_outs_) {
+ DCHECK(it.first != it.second);
+ HInstruction* orig_value = it.first;
+ HPhi* phi = it.second->AsPhi();
+ HInstruction* copy_value = GetInstrCopy(orig_value);
+ // Copy edges are inserted after the original so we can just add new input to the phi.
+ phi->AddInput(copy_value);
+ }
+}
+
+//
// Debug and logging methods.
//
@@ -644,7 +751,6 @@ void DumpBBSet(const ArenaBitVector* set) {
}
void SuperblockCloner::DumpInputSets() {
- std::cout << graph_->PrettyMethod() << "\n";
std::cout << "orig_bb_set:\n";
for (uint32_t idx : orig_bb_set_.Indexes()) {
std::cout << idx << "\n";
@@ -680,7 +786,9 @@ SuperblockCloner::SuperblockCloner(HGraph* graph,
bb_map_(bb_map),
hir_map_(hir_map),
outer_loop_(nullptr),
- outer_loop_bb_set_(arena_, orig_bb_set->GetSizeOf(), true, kArenaAllocSuperblockCloner) {
+ outer_loop_bb_set_(arena_, orig_bb_set->GetSizeOf(), true, kArenaAllocSuperblockCloner),
+ live_outs_(std::less<HInstruction*>(),
+ graph->GetAllocator()->Adapter(kArenaAllocSuperblockCloner)) {
orig_bb_set_.Copy(orig_bb_set);
}
@@ -699,26 +807,19 @@ bool SuperblockCloner::IsSubgraphClonable() const {
return false;
}
- // Check that there are no instructions defined in the subgraph and used outside.
- // TODO: Improve this by accepting graph with such uses but only one exit.
- for (uint32_t idx : orig_bb_set_.Indexes()) {
- HBasicBlock* block = GetBlockById(idx);
+ HInstructionMap live_outs(
+ std::less<HInstruction*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
- for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- if (!instr->IsClonable() ||
- IsUsedOutsideRegion(instr, orig_bb_set_)) {
- return false;
- }
- }
+ if (!CollectLiveOutsAndCheckClonable(&live_outs)) {
+ return false;
+ }
- for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
- HInstruction* instr = it.Current();
- if (!instr->IsClonable() ||
- IsUsedOutsideRegion(instr, orig_bb_set_)) {
- return false;
- }
- }
+ ArenaVector<HBasicBlock*> exits(arena_->Adapter(kArenaAllocSuperblockCloner));
+ SearchForSubgraphExits(&exits);
+
+ // The only loops with live-outs which are currently supported are loops with a single exit.
+ if (!live_outs.empty() && exits.size() != 1) {
+ return false;
}
return true;
@@ -794,8 +895,10 @@ void SuperblockCloner::Run() {
DumpInputSets();
}
+ CollectLiveOutsAndCheckClonable(&live_outs_);
// Find an area in the graph for which control flow information should be adjusted.
FindAndSetLocalAreaForAdjustments();
+ ConstructSubgraphClosedSSA();
// Clone the basic blocks from the orig_bb_set_; data flow is invalid after the call and is to be
// adjusted.
CloneBasicBlocks();
@@ -819,6 +922,7 @@ void SuperblockCloner::Run() {
AdjustControlFlowInfo();
// Fix data flow of the graph.
ResolveDataFlow();
+ FixSubgraphClosedSSAAfterCloning();
}
void SuperblockCloner::CleanUp() {
@@ -985,8 +1089,14 @@ HBasicBlock* PeelUnrollHelper::DoPeelUnrollImpl(bool to_unroll) {
HBasicBlock* loop_header = loop_info_->GetHeader();
// Check that loop info is up-to-date.
DCHECK(loop_info_ == loop_header->GetLoopInformation());
-
HGraph* graph = loop_header->GetGraph();
+
+ if (kSuperblockClonerLogging) {
+ std::cout << "Method: " << graph->PrettyMethod() << std::endl;
+ std::cout << "Scalar loop " << (to_unroll ? "unrolling" : "peeling") <<
+ " was applied to the loop <" << loop_header->GetBlockId() << ">." << std::endl;
+ }
+
ArenaAllocator allocator(graph->GetAllocator()->GetArenaPool());
HEdgeSet remap_orig_internal(graph->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
diff --git a/compiler/optimizing/superblock_cloner.h b/compiler/optimizing/superblock_cloner.h
index e0931674cb..f21172131b 100644
--- a/compiler/optimizing/superblock_cloner.h
+++ b/compiler/optimizing/superblock_cloner.h
@@ -218,7 +218,7 @@ class SuperblockCloner : public ValueObject {
private:
// Fills the 'exits' vector with the subgraph exits.
- void SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits);
+ void SearchForSubgraphExits(ArenaVector<HBasicBlock*>* exits) const;
// Finds and records information about the area in the graph for which control flow (back edges,
// loops, dominators) needs to be adjusted.
@@ -240,6 +240,33 @@ class SuperblockCloner : public ValueObject {
void ResolveDataFlow();
//
+ // Helpers for live-outs processing and Subgraph-closed SSA.
+ //
+ // - live-outs - values which are defined inside the subgraph and have uses outside.
+ // - Subgraph-closed SSA - SSA form for which all the values defined inside the subgraph
+ // have no outside uses except for the phi-nodes in the subgraph exits.
+ //
+ // Note: now if the subgraph has live-outs it is only clonable if it has a single exit; this
+ // makes the subgraph-closed SSA form construction much easier.
+ //
+ // TODO: Support subgraphs with live-outs and multiple exits.
+ //
+
+ // For each live-out value 'val' in the region puts a record <val, val> into the map.
+ // Returns whether all of the instructions in the subgraph are clonable.
+ bool CollectLiveOutsAndCheckClonable(HInstructionMap* live_outs_) const;
+
+ // Constructs Subgraph-closed SSA; precondition - a subgraph has a single exit.
+ //
+ // For each live-out 'val' in 'live_outs_' map inserts a HPhi 'phi' into the exit node, updates
+ // the record in the map to <val, phi> and replaces all outside uses with this phi.
+ void ConstructSubgraphClosedSSA();
+
+ // Fixes the data flow for the live-out 'val' by adding a 'copy_val' input to the corresponding
+ // (<val, phi>) phi after the cloning is done.
+ void FixSubgraphClosedSSAAfterCloning();
+
+ //
// Helpers for CloneBasicBlock.
//
@@ -316,6 +343,8 @@ class SuperblockCloner : public ValueObject {
HLoopInformation* outer_loop_;
HBasicBlockSet outer_loop_bb_set_;
+ HInstructionMap live_outs_;
+
ART_FRIEND_TEST(SuperblockClonerTest, AdjustControlFlowInfo);
ART_FRIEND_TEST(SuperblockClonerTest, IsGraphConnected);
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 103862beff..3fe2ec0ac0 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -65,17 +65,16 @@ class VerifierDepsTest : public CommonCompilerTest {
callbacks_.reset(new VerifierDepsCompilerCallbacks());
}
- mirror::Class* FindClassByName(const std::string& name, ScopedObjectAccess* soa)
+ ObjPtr<mirror::Class> FindClassByName(ScopedObjectAccess& soa, const std::string& name)
REQUIRES_SHARED(Locks::mutator_lock_) {
- StackHandleScope<1> hs(Thread::Current());
+ StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader_handle(
- hs.NewHandle(soa->Decode<mirror::ClassLoader>(class_loader_)));
- mirror::Class* klass = class_linker_->FindClass(Thread::Current(),
- name.c_str(),
- class_loader_handle);
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_)));
+ ObjPtr<mirror::Class> klass =
+ class_linker_->FindClass(soa.Self(), name.c_str(), class_loader_handle);
if (klass == nullptr) {
- DCHECK(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
+ DCHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
}
return klass;
}
@@ -114,16 +113,16 @@ class VerifierDepsTest : public CommonCompilerTest {
callbacks->SetVerifierDeps(verifier_deps_.get());
}
- void LoadDexFile(ScopedObjectAccess* soa, const char* name1, const char* name2 = nullptr)
+ void LoadDexFile(ScopedObjectAccess& soa, const char* name1, const char* name2 = nullptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
class_loader_ = (name2 == nullptr) ? LoadDex(name1) : LoadMultiDex(name1, name2);
dex_files_ = GetDexFiles(class_loader_);
primary_dex_file_ = dex_files_.front();
SetVerifierDeps(dex_files_);
- StackHandleScope<1> hs(soa->Self());
+ StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader =
- hs.NewHandle(soa->Decode<mirror::ClassLoader>(class_loader_));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_));
for (const DexFile* dex_file : dex_files_) {
class_linker_->RegisterDexFile(*dex_file, loader.Get());
}
@@ -133,16 +132,16 @@ class VerifierDepsTest : public CommonCompilerTest {
compiler_driver_->SetDexFilesForOatFile(dex_files_);
}
- void LoadDexFile(ScopedObjectAccess* soa) REQUIRES_SHARED(Locks::mutator_lock_) {
+ void LoadDexFile(ScopedObjectAccess& soa) REQUIRES_SHARED(Locks::mutator_lock_) {
LoadDexFile(soa, "VerifierDeps");
CHECK_EQ(dex_files_.size(), 1u);
- klass_Main_ = FindClassByName("LMain;", soa);
+ klass_Main_ = FindClassByName(soa, "LMain;");
CHECK(klass_Main_ != nullptr);
}
bool VerifyMethod(const std::string& method_name) {
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa);
+ LoadDexFile(soa);
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader_handle(
@@ -155,8 +154,7 @@ class VerifierDepsTest : public CommonCompilerTest {
bool has_failures = true;
bool found_method = false;
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
ArtMethod* resolved_method =
class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
method.GetIndex(),
@@ -186,7 +184,7 @@ class VerifierDepsTest : public CommonCompilerTest {
has_failures = verifier.HasFailures();
found_method = true;
}
- });
+ }
CHECK(found_method) << "Expected to find method " << method_name;
return !has_failures;
}
@@ -194,7 +192,7 @@ class VerifierDepsTest : public CommonCompilerTest {
void VerifyDexFile(const char* multidex = nullptr) {
{
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa, "VerifierDeps", multidex);
+ LoadDexFile(soa, "VerifierDeps", multidex);
}
SetupCompilerDriver();
VerifyWithCompilerDriver(/* verifier_deps */ nullptr);
@@ -205,13 +203,14 @@ class VerifierDepsTest : public CommonCompilerTest {
bool is_strict,
bool is_assignable) {
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa);
- mirror::Class* klass_dst = FindClassByName(dst, &soa);
+ LoadDexFile(soa);
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::Class> klass_dst = hs.NewHandle(FindClassByName(soa, dst));
DCHECK(klass_dst != nullptr) << dst;
- mirror::Class* klass_src = FindClassByName(src, &soa);
+ ObjPtr<mirror::Class> klass_src = FindClassByName(soa, src);
DCHECK(klass_src != nullptr) << src;
verifier_deps_->AddAssignability(*primary_dex_file_,
- klass_dst,
+ klass_dst.Get(),
klass_src,
is_strict,
is_assignable);
@@ -454,12 +453,12 @@ class VerifierDepsTest : public CommonCompilerTest {
std::vector<const DexFile*> dex_files_;
const DexFile* primary_dex_file_;
jobject class_loader_;
- mirror::Class* klass_Main_;
+ ObjPtr<mirror::Class> klass_Main_;
};
TEST_F(VerifierDepsTest, StringToId) {
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa);
+ LoadDexFile(soa);
dex::StringIndex id_Main1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;");
ASSERT_LT(id_Main1.index_, primary_dex_file_->NumStringIds());
@@ -1442,7 +1441,7 @@ TEST_F(VerifierDepsTest, CompilerDriver) {
for (bool verify_failure : { false, true }) {
{
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa, "VerifierDeps", multi);
+ LoadDexFile(soa, "VerifierDeps", multi);
}
VerifyWithCompilerDriver(/* verifier_deps */ nullptr);
@@ -1451,7 +1450,7 @@ TEST_F(VerifierDepsTest, CompilerDriver) {
{
ScopedObjectAccess soa(Thread::Current());
- LoadDexFile(&soa, "VerifierDeps", multi);
+ LoadDexFile(soa, "VerifierDeps", multi);
}
verifier::VerifierDeps decoded_deps(dex_files_, ArrayRef<const uint8_t>(buffer));
if (verify_failure) {
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 2fe16f7cb7..96d7dba225 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1912,29 +1912,35 @@ TEST_F(Dex2oatTest, DontExtract) {
ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
}
+ auto generate_and_check = [&](CompilerFilter::Filter filter) {
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ filter,
+ { "--dump-timings",
+ "--dm-file=" + dm_file.GetFilename(),
+ // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
+ "--runtime-arg",
+ "-Xuse-stderr-logger" },
+ true, // expect_success
+ false, // use_fd
+ [](const OatFile& o) {
+ CHECK(o.ContainsDexCode());
+ });
+ // Check the output for "Fast verify", this is printed from --dump-timings.
+ std::istringstream iss(output_);
+ std::string line;
+ bool found_fast_verify = false;
+ const std::string kFastVerifyString = "Fast Verify";
+ while (std::getline(iss, line) && !found_fast_verify) {
+ found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
+ }
+ EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
+ };
+
// Generate a quickened dex by using the input dm file to verify.
- GenerateOdexForTest(dex_location,
- odex_location,
- CompilerFilter::Filter::kQuicken,
- { "--dump-timings",
- "--dm-file=" + dm_file.GetFilename(),
- // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
- "--runtime-arg",
- "-Xuse-stderr-logger" },
- true, // expect_success
- false, // use_fd
- [](const OatFile& o) {
- CHECK(o.ContainsDexCode());
- });
- // Check the output for "Fast verify", this is printed from --dump-timings.
- std::istringstream iss(output_);
- std::string line;
- bool found_fast_verify = false;
- const std::string kFastVerifyString = "Fast Verify";
- while (std::getline(iss, line) && !found_fast_verify) {
- found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
- }
- EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
+ generate_and_check(CompilerFilter::Filter::kQuicken);
+ // Use verify compiler filter to sanity check that FastVerify works for that filter too.
+ generate_and_check(CompilerFilter::Filter::kVerify);
}
// Test that dex files with quickened opcodes aren't dequickened.
diff --git a/dex2oat/linker/image_test.cc b/dex2oat/linker/image_test.cc
index ab6e7a875a..96c48b8798 100644
--- a/dex2oat/linker/image_test.cc
+++ b/dex2oat/linker/image_test.cc
@@ -111,18 +111,18 @@ TEST_F(ImageTest, TestDefaultMethods) {
// Test the pointer to quick code is the same in origin method
// and in the copied method form the same oat file.
- mirror::Class* iface_klass = class_linker_->LookupClass(
- self, "LIface;", ObjPtr<mirror::ClassLoader>());
+ ObjPtr<mirror::Class> iface_klass =
+ class_linker_->LookupClass(self, "LIface;", /* class_loader */ nullptr);
ASSERT_NE(nullptr, iface_klass);
ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
ASSERT_NE(nullptr, origin);
- ASSERT_TRUE(origin->GetDeclaringClass() == iface_klass);
+ ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iface_klass);
const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
// The origin method should have a pointer to quick code
ASSERT_NE(nullptr, code);
ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
- mirror::Class* impl_klass = class_linker_->LookupClass(
- self, "LImpl;", ObjPtr<mirror::ClassLoader>());
+ ObjPtr<mirror::Class> impl_klass =
+ class_linker_->LookupClass(self, "LImpl;", /* class_loader */ nullptr);
ASSERT_NE(nullptr, impl_klass);
ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
ASSERT_NE(nullptr, copied);
@@ -132,20 +132,20 @@ TEST_F(ImageTest, TestDefaultMethods) {
// Test the origin method has pointer to quick code
// but the copied method has pointer to interpreter
// because these methods are in different oat files.
- mirror::Class* iterable_klass = class_linker_->LookupClass(
- self, "Ljava/lang/Iterable;", ObjPtr<mirror::ClassLoader>());
+ ObjPtr<mirror::Class> iterable_klass =
+ class_linker_->LookupClass(self, "Ljava/lang/Iterable;", /* class_loader */ nullptr);
ASSERT_NE(nullptr, iterable_klass);
origin = iterable_klass->FindClassMethod(
"forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
ASSERT_NE(nullptr, origin);
ASSERT_FALSE(origin->IsDirect());
- ASSERT_TRUE(origin->GetDeclaringClass() == iterable_klass);
+ ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iterable_klass);
code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
// the origin method should have a pointer to quick code
ASSERT_NE(nullptr, code);
ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
- mirror::Class* iterablebase_klass = class_linker_->LookupClass(
- self, "LIterableBase;", ObjPtr<mirror::ClassLoader>());
+ ObjPtr<mirror::Class> iterablebase_klass =
+ class_linker_->LookupClass(self, "LIterableBase;", /* class_loader */ nullptr);
ASSERT_NE(nullptr, iterablebase_klass);
copied = FindCopiedMethod(origin, iterablebase_klass);
ASSERT_NE(nullptr, copied);
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 4b231ed35c..f0daf69850 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -97,7 +97,7 @@ class ImageTest : public CommonCompilerTest {
return new std::unordered_set<std::string>(image_classes_);
}
- ArtMethod* FindCopiedMethod(ArtMethod* origin, mirror::Class* klass)
+ ArtMethod* FindCopiedMethod(ArtMethod* origin, ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
PointerSize pointer_size = class_linker_->GetImagePointerSize();
for (ArtMethod& m : klass->GetCopiedMethods(pointer_size)) {
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 01726af1d6..028de34e96 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -33,6 +33,7 @@
#include "base/logging.h" // For VLOG.
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "compiled_method.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
@@ -618,8 +619,7 @@ void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) {
}
} else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
bin = Bin::kString; // Strings are almost always immutable (except for object header).
- } else if (object->GetClass<kVerifyNone>() ==
- Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangObject)) {
+ } else if (object->GetClass<kVerifyNone>() == GetClassRoot<mirror::Object>()) {
// Instance of java lang object, probably a lock object. This means it will be dirty when we
// synchronize on it.
bin = Bin::kMiscDirty;
@@ -778,8 +778,11 @@ class ImageWriter::PruneObjectReferenceVisitor {
return;
}
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
ObjPtr<mirror::Class> klass = ref->IsClass() ? ref->AsClass() : ref->GetClass();
- if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
+ if (klass == GetClassRoot<mirror::Method>(class_roots) ||
+ klass == GetClassRoot<mirror::Constructor>(class_roots)) {
// Prune all classes using reflection because the content they held will not be fixup.
*result_ = true;
}
@@ -2402,15 +2405,17 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) {
if (orig->IsClass()) {
FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
} else {
- if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
+ if (klass == GetClassRoot<mirror::Method>(class_roots) ||
+ klass == GetClassRoot<mirror::Constructor>(class_roots)) {
// Need to go update the ArtMethod.
auto* dest = down_cast<mirror::Executable*>(copy);
auto* src = down_cast<mirror::Executable*>(orig);
ArtMethod* src_method = src->GetArtMethod();
dest->SetArtMethod(GetImageMethodAddress(src_method));
} else if (!klass->IsArrayClass()) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) {
+ if (klass == GetClassRoot<mirror::DexCache>()) {
FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy));
} else if (klass->IsClassLoaderClass()) {
mirror::ClassLoader* copy_loader = down_cast<mirror::ClassLoader*>(copy);
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 0694c4ff9f..d0a6eb9ff2 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -545,8 +545,7 @@ TEST_F(OatTest, EmptyTextSection) {
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
for (const DexFile* dex_file : dex_files) {
ScopedObjectAccess soa(Thread::Current());
- class_linker->RegisterDexFile(*dex_file,
- soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+ class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
}
compiler_driver_->SetDexFilesForOatFile(dex_files);
compiler_driver_->CompileAll(class_loader, dex_files, &timings);
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index 2f0962c19a..ac9a9a2932 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -23,10 +23,6 @@ cc_defaults {
"dexdump.cc",
],
cflags: ["-Wall", "-Werror"],
- // TODO: fix b/72216369 and remove the need for this.
- include_dirs: [
- "art/runtime" // dex utils.
- ],
}
art_cc_binary {
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index f5a13f0920..85778b6411 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -1773,9 +1773,8 @@ static void dumpCallSite(const DexFile* pDexFile, u4 idx) {
case EncodedArrayValueIterator::ValueType::kType: {
type = "Class";
dex::TypeIndex type_idx = static_cast<dex::TypeIndex>(it.GetJavaValue().i);
- const DexFile::ClassDef* class_def = pDexFile->FindClassDef(type_idx);
- value = pDexFile->GetClassDescriptor(*class_def);
- value = descriptorClassToDot(value.c_str()).get();
+ const DexFile::TypeId& type_id = pDexFile->GetTypeId(type_idx);
+ value = pDexFile->GetTypeDescriptor(type_id);
break;
}
case EncodedArrayValueIterator::ValueType::kField:
diff --git a/libartbase/base/arena_allocator.cc b/libartbase/base/arena_allocator.cc
index 183e5c9f74..df3deba178 100644
--- a/libartbase/base/arena_allocator.cc
+++ b/libartbase/base/arena_allocator.cc
@@ -82,6 +82,7 @@ const char* const ArenaAllocatorStatsImpl<kCount>::kAllocNames[] = {
"RegAllocator ",
"RegAllocVldt ",
"StackMapStm ",
+ "BitTableBld ",
"VectorNode ",
"CodeGen ",
"Assembler ",
diff --git a/libartbase/base/arena_allocator.h b/libartbase/base/arena_allocator.h
index 211ff4f6ad..4dccd033d6 100644
--- a/libartbase/base/arena_allocator.h
+++ b/libartbase/base/arena_allocator.h
@@ -92,6 +92,7 @@ enum ArenaAllocKind {
kArenaAllocRegisterAllocator,
kArenaAllocRegisterAllocatorValidate,
kArenaAllocStackMapStream,
+ kArenaAllocBitTableBuilder,
kArenaAllocVectorNode,
kArenaAllocCodeGenerator,
kArenaAllocAssembler,
diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h
index 3f4d0ba55b..a3d3ee41d6 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -67,7 +67,7 @@ class BitMemoryRegion FINAL : public ValueObject {
return ((data_[index] >> shift) & 1) != 0;
}
- ALWAYS_INLINE void StoreBit(uintptr_t bit_offset, bool value) const {
+ ALWAYS_INLINE void StoreBit(uintptr_t bit_offset, bool value) {
DCHECK_LT(bit_offset, bit_size_);
uint8_t* data = reinterpret_cast<uint8_t*>(data_);
size_t index = (bit_start_ + bit_offset) / kBitsPerByte;
@@ -138,6 +138,19 @@ class BitMemoryRegion FINAL : public ValueObject {
*bit_offset += bit_length;
}
+ // Store bits from other bit region.
+ ALWAYS_INLINE void StoreBits(size_t bit_offset, const BitMemoryRegion& src, size_t bit_length) {
+ DCHECK_LE(bit_offset, bit_size_);
+ DCHECK_LE(bit_length, bit_size_ - bit_offset);
+ size_t bit = 0;
+ constexpr size_t kNumBits = BitSizeOf<uint32_t>();
+ for (; bit + kNumBits <= bit_length; bit += kNumBits) {
+ StoreBits(bit_offset + bit, src.LoadBits(bit, kNumBits), kNumBits);
+ }
+ size_t num_bits = bit_length - bit;
+ StoreBits(bit_offset + bit, src.LoadBits(bit, num_bits), num_bits);
+ }
+
ALWAYS_INLINE bool Equals(const BitMemoryRegion& other) const {
return data_ == other.data_ &&
bit_start_ == other.bit_start_ &&
diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h
index 24bdd13324..bf3d3b032c 100644
--- a/libartbase/base/bit_table.h
+++ b/libartbase/base/bit_table.h
@@ -17,11 +17,17 @@
#ifndef ART_LIBARTBASE_BASE_BIT_TABLE_H_
#define ART_LIBARTBASE_BASE_BIT_TABLE_H_
-#include <vector>
+#include <array>
+#include <numeric>
+#include <string.h>
+#include <type_traits>
+#include <unordered_map>
#include "base/bit_memory_region.h"
-#include "base/bit_utils.h"
+#include "base/casts.h"
#include "base/memory_region.h"
+#include "base/scoped_arena_containers.h"
+#include "base/stl_util.h"
namespace art {
@@ -104,8 +110,7 @@ class BitTable {
column_offset_[0] = 0;
for (uint32_t i = 0; i < kNumColumns; i++) {
size_t column_end = column_offset_[i] + DecodeVarintBits(region, bit_offset);
- column_offset_[i + 1] = column_end;
- DCHECK_EQ(column_offset_[i + 1], column_end) << "Overflow";
+ column_offset_[i + 1] = dchecked_integral_cast<uint16_t>(column_end);
}
}
@@ -121,6 +126,13 @@ class BitTable {
return table_data_.LoadBits(offset, NumColumnBits(column)) + kValueBias;
}
+ ALWAYS_INLINE BitMemoryRegion GetBitMemoryRegion(uint32_t row, uint32_t column = 0) const {
+ DCHECK_LT(row, num_rows_);
+ DCHECK_LT(column, kNumColumns);
+ size_t offset = row * NumRowBits() + column_offset_[column];
+ return table_data_.Subregion(offset, NumColumnBits(column));
+ }
+
size_t NumRows() const { return num_rows_; }
uint32_t NumRowBits() const { return column_offset_[kNumColumns]; }
@@ -146,73 +158,226 @@ constexpr uint32_t BitTable<kNumColumns>::Accessor::kNoValue;
template<uint32_t kNumColumns>
constexpr uint32_t BitTable<kNumColumns>::kValueBias;
-template<uint32_t kNumColumns, typename Alloc = std::allocator<uint32_t>>
+// Helper class for encoding BitTable. It can optionally de-duplicate the inputs.
+// Type 'T' must be POD type consisting of uint32_t fields (one for each column).
+template<typename T>
class BitTableBuilder {
public:
- explicit BitTableBuilder(Alloc alloc = Alloc()) : buffer_(alloc) {}
+ static_assert(std::is_pod<T>::value, "Type 'T' must be POD");
+ static constexpr size_t kNumColumns = sizeof(T) / sizeof(uint32_t);
+
+ explicit BitTableBuilder(ScopedArenaAllocator* allocator)
+ : rows_(allocator->Adapter(kArenaAllocBitTableBuilder)),
+ dedup_(8, allocator->Adapter(kArenaAllocBitTableBuilder)) {
+ }
+
+ T& operator[](size_t row) { return rows_[row]; }
+ const T& operator[](size_t row) const { return rows_[row]; }
+ size_t size() const { return rows_.size(); }
- template<typename ... T>
- uint32_t AddRow(T ... values) {
- constexpr size_t count = sizeof...(values);
- static_assert(count == kNumColumns, "Incorrect argument count");
- uint32_t data[count] = { values... };
- buffer_.insert(buffer_.end(), data, data + count);
- return num_rows_++;
+ // Append given value to the vector without de-duplication.
+ // This will not add the element to the dedup map to avoid its associated costs.
+ void Add(T value) {
+ rows_.push_back(value);
+ }
+
+ // Append given list of values and return the index of the first value.
+ // If the exact same set of values was already added, return the old index.
+ uint32_t Dedup(T* values, size_t count = 1) {
+ FNVHash<MemoryRegion> hasher;
+ uint32_t hash = hasher(MemoryRegion(values, sizeof(T) * count));
+
+ // Check if we have already added identical set of values.
+ auto range = dedup_.equal_range(hash);
+ for (auto it = range.first; it != range.second; ++it) {
+ uint32_t index = it->second;
+ if (count <= size() - index &&
+ std::equal(values,
+ values + count,
+ rows_.begin() + index,
+ [](const T& lhs, const T& rhs) {
+ return memcmp(&lhs, &rhs, sizeof(T)) == 0;
+ })) {
+ return index;
+ }
+ }
+
+ // Add the set of values and add the index to the dedup map.
+ uint32_t index = size();
+ rows_.insert(rows_.end(), values, values + count);
+ dedup_.emplace(hash, index);
+ return index;
+ }
+
+ // Check if the table already contains given values starting at the given index.
+ bool RangeEquals(uint32_t index, T* values, size_t count = 1) {
+ DCHECK_LE(index, size());
+ DCHECK_LE(count, size() - index);
+ for (uint32_t i = 0; i < count; i++) {
+ if (memcmp(&values[i], &rows_[index + i], sizeof(T)) != 0) {
+ return false;
+ }
+ }
+ return true;
}
ALWAYS_INLINE uint32_t Get(uint32_t row, uint32_t column) const {
- return buffer_[row * kNumColumns + column];
+ DCHECK_LT(row, size());
+ DCHECK_LT(column, kNumColumns);
+ const uint32_t* data = reinterpret_cast<const uint32_t*>(&rows_[row]);
+ return data[column];
}
- template<typename Vector>
- void Encode(Vector* out, size_t* bit_offset) {
- constexpr uint32_t bias = BitTable<kNumColumns>::kValueBias;
- size_t initial_bit_offset = *bit_offset;
- // Measure data size.
- uint32_t max_column_value[kNumColumns] = {};
- for (uint32_t r = 0; r < num_rows_; r++) {
+ // Calculate the column bit widths based on the current data.
+ void Measure(/*out*/ std::array<uint32_t, kNumColumns>* column_bits) const {
+ uint32_t max_column_value[kNumColumns];
+ std::fill_n(max_column_value, kNumColumns, 0);
+ for (uint32_t r = 0; r < size(); r++) {
for (uint32_t c = 0; c < kNumColumns; c++) {
- max_column_value[c] |= Get(r, c) - bias;
+ max_column_value[c] |= Get(r, c) - BitTable<kNumColumns>::kValueBias;
}
}
- // Write table header.
- uint32_t table_data_bits = 0;
- uint32_t column_bits[kNumColumns] = {};
- EncodeVarintBits(out, bit_offset, num_rows_);
- if (num_rows_ != 0) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ (*column_bits)[c] = MinimumBitsToStore(max_column_value[c]);
+ }
+ }
+
+ // Encode the stored data into a BitTable.
+ template<typename Vector>
+ void Encode(Vector* out, size_t* bit_offset) const {
+ constexpr uint32_t bias = BitTable<kNumColumns>::kValueBias;
+ size_t initial_bit_offset = *bit_offset;
+
+ std::array<uint32_t, kNumColumns> column_bits;
+ Measure(&column_bits);
+ EncodeVarintBits(out, bit_offset, size());
+ if (size() != 0) {
+ // Write table header.
for (uint32_t c = 0; c < kNumColumns; c++) {
- column_bits[c] = MinimumBitsToStore(max_column_value[c]);
EncodeVarintBits(out, bit_offset, column_bits[c]);
- table_data_bits += num_rows_ * column_bits[c];
}
- }
- // Write table data.
- out->resize(BitsToBytesRoundUp(*bit_offset + table_data_bits));
- BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
- for (uint32_t r = 0; r < num_rows_; r++) {
- for (uint32_t c = 0; c < kNumColumns; c++) {
- region.StoreBitsAndAdvance(bit_offset, Get(r, c) - bias, column_bits[c]);
+
+ // Write table data.
+ uint32_t row_bits = std::accumulate(column_bits.begin(), column_bits.end(), 0u);
+ out->resize(BitsToBytesRoundUp(*bit_offset + row_bits * size()));
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ for (uint32_t r = 0; r < size(); r++) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ region.StoreBitsAndAdvance(bit_offset, Get(r, c) - bias, column_bits[c]);
+ }
}
}
+
// Verify the written data.
if (kIsDebugBuild) {
BitTable<kNumColumns> table;
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
table.Decode(region, &initial_bit_offset);
- DCHECK_EQ(this->num_rows_, table.NumRows());
+ DCHECK_EQ(size(), table.NumRows());
for (uint32_t c = 0; c < kNumColumns; c++) {
DCHECK_EQ(column_bits[c], table.NumColumnBits(c));
}
- for (uint32_t r = 0; r < num_rows_; r++) {
+ for (uint32_t r = 0; r < size(); r++) {
for (uint32_t c = 0; c < kNumColumns; c++) {
- DCHECK_EQ(this->Get(r, c), table.Get(r, c)) << " (" << r << ", " << c << ")";
+ DCHECK_EQ(Get(r, c), table.Get(r, c)) << " (" << r << ", " << c << ")";
}
}
}
}
protected:
- std::vector<uint32_t, Alloc> buffer_;
- uint32_t num_rows_ = 0;
+ ScopedArenaDeque<T> rows_;
+ ScopedArenaUnorderedMultimap<uint32_t, uint32_t> dedup_; // Hash -> row index.
+};
+
+template<typename T>
+constexpr size_t BitTableBuilder<T>::kNumColumns;
+
+// Helper class for encoding single-column BitTable of bitmaps (allows more than 32 bits).
+class BitmapTableBuilder {
+ public:
+ explicit BitmapTableBuilder(ScopedArenaAllocator* const allocator)
+ : allocator_(allocator),
+ rows_(allocator->Adapter(kArenaAllocBitTableBuilder)),
+ dedup_(8, allocator_->Adapter(kArenaAllocBitTableBuilder)) {
+ }
+
+ MemoryRegion operator[](size_t row) { return rows_[row]; }
+ const MemoryRegion operator[](size_t row) const { return rows_[row]; }
+ size_t size() const { return rows_.size(); }
+
+ // Add the given bitmap to the table and return its index.
+ // If the bitmap was already added it will be deduplicated.
+ // The last bit must be set and any padding bits in the last byte must be zero.
+ uint32_t Dedup(const void* bitmap, size_t num_bits) {
+ MemoryRegion region(const_cast<void*>(bitmap), BitsToBytesRoundUp(num_bits));
+ DCHECK(num_bits == 0 || BitMemoryRegion(region).LoadBit(num_bits - 1) == 1);
+ DCHECK_EQ(BitMemoryRegion(region).LoadBits(num_bits, region.size_in_bits() - num_bits), 0u);
+ FNVHash<MemoryRegion> hasher;
+ uint32_t hash = hasher(region);
+
+ // Check if we have already added identical bitmap.
+ auto range = dedup_.equal_range(hash);
+ for (auto it = range.first; it != range.second; ++it) {
+ if (MemoryRegion::ContentEquals()(region, rows_[it->second])) {
+ return it->second;
+ }
+ }
+
+ // Add the bitmap and add the index to the dedup map.
+ uint32_t index = size();
+ void* copy = allocator_->Alloc(region.size(), kArenaAllocBitTableBuilder);
+ memcpy(copy, region.pointer(), region.size());
+ rows_.push_back(MemoryRegion(copy, region.size()));
+ dedup_.emplace(hash, index);
+ max_num_bits_ = std::max(max_num_bits_, num_bits);
+ return index;
+ }
+
+ // Encode the stored data into a BitTable.
+ template<typename Vector>
+ void Encode(Vector* out, size_t* bit_offset) const {
+ size_t initial_bit_offset = *bit_offset;
+
+ EncodeVarintBits(out, bit_offset, size());
+ if (size() != 0) {
+ EncodeVarintBits(out, bit_offset, max_num_bits_);
+
+ // Write table data.
+ out->resize(BitsToBytesRoundUp(*bit_offset + max_num_bits_ * size()));
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ for (MemoryRegion row : rows_) {
+ BitMemoryRegion src(row);
+ region.StoreBits(*bit_offset, src, std::min(max_num_bits_, src.size_in_bits()));
+ *bit_offset += max_num_bits_;
+ }
+ }
+
+ // Verify the written data.
+ if (kIsDebugBuild) {
+ BitTable<1> table;
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ table.Decode(region, &initial_bit_offset);
+ DCHECK_EQ(size(), table.NumRows());
+ DCHECK_EQ(max_num_bits_, table.NumColumnBits(0));
+ for (uint32_t r = 0; r < size(); r++) {
+ BitMemoryRegion expected(rows_[r]);
+ BitMemoryRegion seen = table.GetBitMemoryRegion(r);
+ size_t num_bits = std::max(expected.size_in_bits(), seen.size_in_bits());
+ for (size_t b = 0; b < num_bits; b++) {
+ bool e = b < expected.size_in_bits() && expected.LoadBit(b);
+ bool s = b < seen.size_in_bits() && seen.LoadBit(b);
+ DCHECK_EQ(e, s) << " (" << r << ")[" << b << "]";
+ }
+ }
+ }
+ }
+
+ private:
+ ScopedArenaAllocator* const allocator_;
+ ScopedArenaDeque<MemoryRegion> rows_;
+ ScopedArenaUnorderedMultimap<uint32_t, uint32_t> dedup_; // Hash -> row index.
+ size_t max_num_bits_ = 0u;
};
} // namespace art
diff --git a/libartbase/base/bit_table_test.cc b/libartbase/base/bit_table_test.cc
index 25bfcf095e..8abf0da9d9 100644
--- a/libartbase/base/bit_table_test.cc
+++ b/libartbase/base/bit_table_test.cc
@@ -16,8 +16,14 @@
#include "bit_table.h"
+#include <map>
+
#include "gtest/gtest.h"
+#include "base/arena_allocator.h"
+#include "base/bit_utils.h"
+#include "base/malloc_arena_pool.h"
+
namespace art {
TEST(BitTableTest, TestVarint) {
@@ -38,9 +44,13 @@ TEST(BitTableTest, TestVarint) {
}
TEST(BitTableTest, TestEmptyTable) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- BitTableBuilder<1> builder;
+ BitTableBuilder<uint32_t> builder(&allocator);
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -50,14 +60,18 @@ TEST(BitTableTest, TestEmptyTable) {
}
TEST(BitTableTest, TestSingleColumnTable) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
constexpr uint32_t kNoValue = -1;
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- BitTableBuilder<1> builder;
- builder.AddRow(42u);
- builder.AddRow(kNoValue);
- builder.AddRow(1000u);
- builder.AddRow(kNoValue);
+ BitTableBuilder<uint32_t> builder(&allocator);
+ builder.Add(42u);
+ builder.Add(kNoValue);
+ builder.Add(1000u);
+ builder.Add(kNoValue);
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -72,11 +86,15 @@ TEST(BitTableTest, TestSingleColumnTable) {
}
TEST(BitTableTest, TestUnalignedTable) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
std::vector<uint8_t> buffer;
size_t encode_bit_offset = start_bit_offset;
- BitTableBuilder<1> builder;
- builder.AddRow(42u);
+ BitTableBuilder<uint32_t> builder(&allocator);
+ builder.Add(42u);
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = start_bit_offset;
@@ -88,12 +106,22 @@ TEST(BitTableTest, TestUnalignedTable) {
}
TEST(BitTableTest, TestBigTable) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
constexpr uint32_t kNoValue = -1;
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- BitTableBuilder<4> builder;
- builder.AddRow(42u, kNoValue, 0u, static_cast<uint32_t>(-2));
- builder.AddRow(62u, kNoValue, 63u, static_cast<uint32_t>(-3));
+ struct RowData {
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+ };
+ BitTableBuilder<RowData> builder(&allocator);
+ builder.Add(RowData{42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
+ builder.Add(RowData{62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -114,4 +142,85 @@ TEST(BitTableTest, TestBigTable) {
EXPECT_EQ(32u, table.NumColumnBits(3));
}
+TEST(BitTableTest, TestDedup) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
+ struct RowData {
+ uint32_t a;
+ uint32_t b;
+ };
+ BitTableBuilder<RowData> builder(&allocator);
+ RowData value0{1, 2};
+ RowData value1{3, 4};
+ EXPECT_EQ(0u, builder.Dedup(&value0));
+ EXPECT_EQ(1u, builder.Dedup(&value1));
+ EXPECT_EQ(0u, builder.Dedup(&value0));
+ EXPECT_EQ(1u, builder.Dedup(&value1));
+ EXPECT_EQ(2u, builder.size());
+}
+
+TEST(BitTableTest, TestBitmapTable) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = 0;
+ const uint64_t value = 0xDEADBEEF0BADF00Dull;
+ BitmapTableBuilder builder(&allocator);
+ std::multimap<uint64_t, size_t> indicies; // bitmap -> row.
+ for (size_t bit_length = 0; bit_length <= BitSizeOf<uint64_t>(); ++bit_length) {
+ uint64_t bitmap = value & MaxInt<uint64_t>(bit_length);
+ indicies.emplace(bitmap, builder.Dedup(&bitmap, MinimumBitsToStore(bitmap)));
+ }
+ builder.Encode(&buffer, &encode_bit_offset);
+ EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size());
+
+ size_t decode_bit_offset = 0;
+ BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset);
+ for (auto it : indicies) {
+ uint64_t expected = it.first;
+ BitMemoryRegion actual = table.GetBitMemoryRegion(it.second);
+ EXPECT_GE(actual.size_in_bits(), MinimumBitsToStore(expected));
+ for (size_t b = 0; b < actual.size_in_bits(); b++, expected >>= 1) {
+ EXPECT_EQ(expected & 1, actual.LoadBit(b)) << "b=" << b;
+ }
+ }
+}
+
+TEST(BitTableTest, TestCollisions) {
+ MallocArenaPool pool;
+ ArenaStack arena_stack(&pool);
+ ScopedArenaAllocator allocator(&arena_stack);
+ FNVHash<MemoryRegion> hasher;
+
+ struct RowData {
+ uint32_t a;
+ uint32_t b;
+ };
+ RowData value0{56948505, 0};
+ RowData value1{67108869, 0};
+
+ BitTableBuilder<RowData> builder(&allocator);
+ EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(RowData))),
+ hasher(MemoryRegion(&value1, sizeof(RowData))));
+ EXPECT_EQ(0u, builder.Dedup(&value0));
+ EXPECT_EQ(1u, builder.Dedup(&value1));
+ EXPECT_EQ(0u, builder.Dedup(&value0));
+ EXPECT_EQ(1u, builder.Dedup(&value1));
+ EXPECT_EQ(2u, builder.size());
+
+ BitmapTableBuilder builder2(&allocator);
+ EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0.a)))),
+ hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1.a)))));
+ EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
+ EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
+ EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
+ EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
+ EXPECT_EQ(2u, builder2.size());
+}
+
} // namespace art
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index 0d798f37f7..67413eb85c 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -355,17 +355,18 @@ std::string CommonArtTestImpl::GetTestDexFileName(const char* name) const {
return filename;
}
-std::vector<std::unique_ptr<const DexFile>> CommonArtTestImpl::OpenTestDexFiles(const char* name) {
- std::string filename = GetTestDexFileName(name);
+std::vector<std::unique_ptr<const DexFile>> CommonArtTestImpl::OpenDexFiles(const char* filename) {
+ static constexpr bool kVerify = true;
static constexpr bool kVerifyChecksum = true;
std::string error_msg;
const ArtDexFileLoader dex_file_loader;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- bool success = dex_file_loader.Open(filename.c_str(),
- filename.c_str(),
- /* verify */ true,
+ bool success = dex_file_loader.Open(filename,
+ filename,
+ kVerify,
kVerifyChecksum,
- &error_msg, &dex_files);
+ &error_msg,
+ &dex_files);
CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
for (auto& dex_file : dex_files) {
CHECK_EQ(PROT_READ, dex_file->GetPermissions());
@@ -374,6 +375,11 @@ std::vector<std::unique_ptr<const DexFile>> CommonArtTestImpl::OpenTestDexFiles(
return dex_files;
}
+std::vector<std::unique_ptr<const DexFile>> CommonArtTestImpl::OpenTestDexFiles(
+ const char* name) {
+ return OpenDexFiles(GetTestDexFileName(name).c_str());
+}
+
std::unique_ptr<const DexFile> CommonArtTestImpl::OpenTestDexFile(const char* name) {
std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
EXPECT_EQ(1U, vector.size());
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index a4764c275d..3998be516d 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -148,6 +148,9 @@ class CommonArtTestImpl {
std::string GetTestAndroidRoot();
+ // Open a file (allows reading of framework jars).
+ std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
+ // Open a test file (art-gtest-*.jar).
std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name);
std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index e74dfe5e64..56d1c44fc0 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -20,11 +20,11 @@
#include <stdlib.h>
#include "base/stl_util.h"
-#include "common_runtime_test.h"
+#include "common_art_test.h"
namespace art {
-class FileUtilsTest : public CommonRuntimeTest {};
+class FileUtilsTest : public CommonArtTest {};
TEST_F(FileUtilsTest, GetDalvikCacheFilename) {
std::string name;
@@ -63,7 +63,7 @@ TEST_F(FileUtilsTest, GetAndroidRootSafe) {
// We don't expect null returns for most cases, so don't check and let std::string crash.
- // CommonRuntimeTest sets ANDROID_ROOT, so expect this to be the same.
+ // CommonArtTest sets ANDROID_ROOT, so expect this to be the same.
std::string android_root = GetAndroidRootSafe(&error_msg);
std::string android_root_env = getenv("ANDROID_ROOT");
EXPECT_EQ(android_root, android_root_env);
@@ -78,7 +78,7 @@ TEST_F(FileUtilsTest, GetAndroidRootSafe) {
// Set a bogus value for ANDROID_ROOT. This should be an error.
ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", 1 /* overwrite */));
- EXPECT_TRUE(GetAndroidRootSafe(&error_msg) == nullptr);
+ EXPECT_EQ(GetAndroidRootSafe(&error_msg), "");
// Unset ANDROID_ROOT and see that it still returns something (as libart code is running).
ASSERT_EQ(0, unsetenv("ANDROID_ROOT"));
diff --git a/libartbase/base/scoped_arena_containers.h b/libartbase/base/scoped_arena_containers.h
index 41939816f5..44d7ebbc96 100644
--- a/libartbase/base/scoped_arena_containers.h
+++ b/libartbase/base/scoped_arena_containers.h
@@ -86,6 +86,14 @@ template <typename K, typename V, class Hash = std::hash<K>, class KeyEqual = st
using ScopedArenaUnorderedMap =
std::unordered_map<K, V, Hash, KeyEqual, ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
+template <typename K, typename V, class Hash = std::hash<K>, class KeyEqual = std::equal_to<K>>
+using ScopedArenaUnorderedMultimap =
+ std::unordered_multimap<K,
+ V,
+ Hash,
+ KeyEqual,
+ ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
+
// Implementation details below.
template <>
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 3818624d7a..06fd19e2fe 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -112,6 +112,7 @@ art_cc_test {
],
srcs: [
"dex/art_dex_file_loader_test.cc",
+ "dex/class_accessor_test.cc",
"dex/code_item_accessors_test.cc",
"dex/compact_dex_file_test.cc",
"dex/compact_offset_table_test.cc",
diff --git a/libdexfile/dex/art_dex_file_loader_test.cc b/libdexfile/dex/art_dex_file_loader_test.cc
index d353c26b35..5f3fc0266f 100644
--- a/libdexfile/dex/art_dex_file_loader_test.cc
+++ b/libdexfile/dex/art_dex_file_loader_test.cc
@@ -14,26 +14,25 @@
* limitations under the License.
*/
+#include "art_dex_file_loader.h"
+
#include <sys/mman.h>
#include <fstream>
#include <memory>
-#include "art_dex_file_loader.h"
+#include "base/common_art_test.h"
#include "base/file_utils.h"
#include "base/mem_map.h"
#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
-#include "common_runtime_test.h"
#include "dex/base64_test_util.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
namespace art {
@@ -43,26 +42,35 @@ static void Copy(const std::string& src, const std::string& dst) {
dst_stream << src_stream.rdbuf();
}
-class ArtDexFileLoaderTest : public CommonRuntimeTest {};
+class ArtDexFileLoaderTest : public CommonArtTest {
+ void SetUp() OVERRIDE {
+ CommonArtTest::SetUp();
+ // Open a jar file from the boot classpath for use in basic tests of dex accessors.
+ std::vector<std::string> lib_core_dex_file_names = GetLibCoreDexFileNames();
+ CHECK_NE(lib_core_dex_file_names.size(), 0U);
+ dex_files_ = OpenDexFiles(lib_core_dex_file_names[0].c_str());
+ CHECK_NE(dex_files_.size(), 0U);
+ // Save a dex file for use by tests.
+ java_lang_dex_file_ = dex_files_[0].get();
+ }
-// TODO: Port OpenTestDexFile(s) need to be ported to use non-ART utilities, and
-// the tests that depend upon them should be moved to dex_file_loader_test.cc
+ protected:
+ std::vector<std::unique_ptr<const DexFile>> dex_files_;
+ const DexFile* java_lang_dex_file_;
+};
TEST_F(ArtDexFileLoaderTest, Open) {
- ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
ASSERT_TRUE(dex.get() != nullptr);
}
TEST_F(ArtDexFileLoaderTest, GetLocationChecksum) {
- ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
}
TEST_F(ArtDexFileLoaderTest, GetChecksum) {
std::vector<uint32_t> checksums;
- ScopedObjectAccess soa(Thread::Current());
std::string error_msg;
const ArtDexFileLoader dex_file_loader;
EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
@@ -94,7 +102,6 @@ TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) {
}
TEST_F(ArtDexFileLoaderTest, ClassDefs) {
- ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
ASSERT_TRUE(raw.get() != nullptr);
EXPECT_EQ(3U, raw->NumClassDefs());
@@ -110,7 +117,6 @@ TEST_F(ArtDexFileLoaderTest, ClassDefs) {
}
TEST_F(ArtDexFileLoaderTest, GetMethodSignature) {
- ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
ASSERT_TRUE(raw.get() != nullptr);
EXPECT_EQ(1U, raw->NumClassDefs());
@@ -215,7 +221,6 @@ TEST_F(ArtDexFileLoaderTest, GetMethodSignature) {
}
TEST_F(ArtDexFileLoaderTest, FindStringId) {
- ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
ASSERT_TRUE(raw.get() != nullptr);
EXPECT_EQ(1U, raw->NumClassDefs());
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index a082142366..3bb9e93e5a 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,17 +37,26 @@ inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::Clas
num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
-inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) {
- index_ += DecodeUnsignedLeb128(&ptr);
- access_flags_ = DecodeUnsignedLeb128(&ptr);
- code_off_ = DecodeUnsignedLeb128(&ptr);
- return ptr;
+inline void ClassAccessor::Method::Read() {
+ index_ += DecodeUnsignedLeb128(&ptr_pos_);
+ access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+ code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
}
-inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
- index_ += DecodeUnsignedLeb128(&ptr);
- access_flags_ = DecodeUnsignedLeb128(&ptr);
- return ptr;
+inline void ClassAccessor::Field::Read() {
+ index_ += DecodeUnsignedLeb128(&ptr_pos_);
+ access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+template <typename DataType, typename Visitor>
+inline void ClassAccessor::VisitMembers(size_t count,
+ const Visitor& visitor,
+ DataType* data) const {
+ DCHECK(data != nullptr);
+ for ( ; count != 0; --count) {
+ data->Read();
+ visitor(*data);
+ }
}
template <typename StaticFieldVisitor,
@@ -59,35 +68,15 @@ inline void ClassAccessor::VisitFieldsAndMethods(
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
- const uint8_t* ptr = ptr_pos_;
- {
- Field data;
- for (size_t i = 0; i < num_static_fields_; ++i) {
- ptr = data.Read(ptr);
- static_field_visitor(data);
- }
- }
- {
- Field data;
- for (size_t i = 0; i < num_instance_fields_; ++i) {
- ptr = data.Read(ptr);
- instance_field_visitor(data);
- }
- }
- {
- Method data(dex_file_, /*is_static_or_direct*/ true);
- for (size_t i = 0; i < num_direct_methods_; ++i) {
- ptr = data.Read(ptr);
- direct_method_visitor(data);
- }
- }
- {
- Method data(dex_file_, /*is_static_or_direct*/ false);
- for (size_t i = 0; i < num_virtual_methods_; ++i) {
- ptr = data.Read(ptr);
- virtual_method_visitor(data);
- }
- }
+ Field field(dex_file_, ptr_pos_);
+ VisitMembers(num_static_fields_, static_field_visitor, &field);
+ field.NextSection();
+ VisitMembers(num_instance_fields_, instance_field_visitor, &field);
+
+ Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
+ VisitMembers(num_direct_methods_, direct_method_visitor, &method);
+ method.NextSection();
+ VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
}
template <typename DirectMethodVisitor,
@@ -110,12 +99,6 @@ inline void ClassAccessor::VisitFields(const StaticFieldVisitor& static_field_vi
VoidFunctor());
}
-// Visit direct and virtual methods.
-template <typename MethodVisitor>
-inline void ClassAccessor::VisitMethods(const MethodVisitor& method_visitor) const {
- VisitMethods(method_visitor, method_visitor);
-}
-
inline const DexFile::CodeItem* ClassAccessor::GetCodeItem(const Method& method) const {
return dex_file_.GetCodeItem(method.GetCodeItemOffset());
}
@@ -132,6 +115,66 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const {
return dex_file_.GetCodeItem(code_off_);
}
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetFieldsInternal(size_t count) const {
+ return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_),
+ DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) };
+}
+
+// Return an iteration range for the first <count> methods.
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetMethodsInternal(size_t count) const {
+ // Skip over the fields.
+ Field field(dex_file_, ptr_pos_);
+ VisitMembers(NumFields(), VoidFunctor(), &field);
+ // Return the iterator pair.
+ return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_),
+ DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) };
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
+ const {
+ return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetStaticFields() const {
+ return GetFieldsInternal(num_static_fields_);
+}
+
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+ ClassAccessor::GetInstanceFields() const {
+ IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
+ // Skip the static fields.
+ return { std::next(fields.begin(), NumStaticFields()), fields.end() };
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetMethods() const {
+ return GetMethodsInternal(NumMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetDirectMethods() const {
+ return GetMethodsInternal(NumDirectMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetVirtualMethods() const {
+ IterationRange<DataIterator<Method>> methods = GetMethods();
+ // Skip the direct fields.
+ return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
+}
+
+inline void ClassAccessor::Field::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false);
+}
+
+inline void ClassAccessor::Method::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true);
+}
+
} // namespace art
#endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 72bc50b98c..4f0fd32e31 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,6 +20,7 @@
#include "base/utils.h"
#include "code_item_accessors.h"
#include "dex_file.h"
+#include "hidden_api_access_flags.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "modifiers.h"
@@ -33,19 +34,27 @@ class ClassAccessor {
private:
class BaseItem {
public:
+ explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {}
+
uint32_t GetIndex() const {
return index_;
}
uint32_t GetAccessFlags() const {
- return access_flags_;
+ return HiddenApiAccessFlags::RemoveFromDex(access_flags_);
+ }
+
+ HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
+ return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
}
bool IsFinal() const {
return (GetAccessFlags() & kAccFinal) != 0;
}
- public:
+ protected:
+ // Internal data pointer for reading.
+ const uint8_t* ptr_pos_ = nullptr;
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
};
@@ -72,12 +81,22 @@ class ClassAccessor {
const DexFile::CodeItem* GetCodeItem() const;
+ bool IsStaticOrDirect() const {
+ return is_static_or_direct_;
+ }
+
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
- explicit Method(const DexFile& dex_file, bool is_static_or_direct)
- : dex_file_(dex_file),
+ explicit Method(const DexFile& dex_file,
+ const uint8_t* ptr_pos,
+ bool is_static_or_direct = true)
+ : BaseItem(ptr_pos),
+ dex_file_(dex_file),
is_static_or_direct_(is_static_or_direct) {}
- const uint8_t* Read(const uint8_t* ptr);
+ void Read();
InvokeType GetDirectMethodInvokeType() const {
return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
@@ -94,8 +113,15 @@ class ClassAccessor {
}
}
+ // Move to virtual method section.
+ void NextSection() {
+ DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
+ is_static_or_direct_ = false;
+ index_ = 0u;
+ }
+
const DexFile& dex_file_;
- const bool is_static_or_direct_;
+ bool is_static_or_direct_ = true;
uint32_t code_off_ = 0u;
friend class ClassAccessor;
@@ -103,12 +129,120 @@ class ClassAccessor {
// A decoded version of the field of a class_data_item.
class Field : public BaseItem {
+ public:
+ explicit Field(const DexFile& dex_file,
+ const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {}
+
+ const DexFile& GetDexFile() const {
+ return dex_file_;
+ }
+
+ bool IsStatic() const {
+ return is_static_;
+ }
+
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
- const uint8_t* Read(const uint8_t* ptr);
+ void Read();
+ // Move to instance fields section.
+ void NextSection() {
+ index_ = 0u;
+ is_static_ = false;
+ }
+
+ const DexFile& dex_file_;
+ bool is_static_ = true;
friend class ClassAccessor;
};
+ template <typename DataType>
+ class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
+ public:
+ using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
+ using difference_type =
+ typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;
+
+ DataIterator(const DexFile& dex_file,
+ uint32_t position,
+ uint32_t partition_pos,
+ uint32_t iterator_end,
+ const uint8_t* ptr_pos)
+ : data_(dex_file, ptr_pos),
+ position_(position),
+ partition_pos_(partition_pos),
+ iterator_end_(iterator_end) {
+ ReadData();
+ }
+
+ bool IsValid() const {
+ return position_ < iterator_end_;
+ }
+
+ // Value after modification.
+ DataIterator& operator++() {
+ ++position_;
+ ReadData();
+ return *this;
+ }
+
+ const value_type& operator*() const {
+ return data_;
+ }
+
+ const value_type* operator->() const {
+ return &data_;
+ }
+
+ bool operator==(const DataIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return position_ == rhs.position_;
+ }
+
+ bool operator!=(const DataIterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(const DataIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return position_ < rhs.position_;
+ }
+
+ bool operator>(const DataIterator& rhs) const {
+ return rhs < *this;
+ }
+
+ bool operator<=(const DataIterator& rhs) const {
+ return !(rhs < *this);
+ }
+
+ bool operator>=(const DataIterator& rhs) const {
+ return !(*this < rhs);
+ }
+
+ private:
+ // Read data at current position.
+ void ReadData() {
+ if (IsValid()) {
+ // At the end of the first section, go to the next section.
+ if (position_ == partition_pos_) {
+ data_.NextSection();
+ }
+ data_.Read();
+ }
+ }
+
+ DataType data_;
+ // Iterator position.
+ uint32_t position_;
+ // At partition_pos_, we go to the next section.
+ const uint32_t partition_pos_;
+ // At iterator_end_, the iterator is no longer valid.
+ const uint32_t iterator_end_;
+ };
+
// Not explicit specifically for range-based loops.
ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);
@@ -118,7 +252,6 @@ class ClassAccessor {
const DexFile::CodeItem* GetCodeItem(const Method& method) const;
// Iterator data is not very iterator friendly, use visitors to get around this.
- // No thread safety analysis since the visitor may require capabilities.
template <typename StaticFieldVisitor,
typename InstanceFieldVisitor,
typename DirectMethodVisitor,
@@ -126,8 +259,7 @@ class ClassAccessor {
void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
- const VirtualMethodVisitor& virtual_method_visitor) const
- NO_THREAD_SAFETY_ANALYSIS;
+ const VirtualMethodVisitor& virtual_method_visitor) const;
template <typename DirectMethodVisitor,
typename VirtualMethodVisitor>
@@ -139,9 +271,23 @@ class ClassAccessor {
void VisitFields(const StaticFieldVisitor& static_field_visitor,
const InstanceFieldVisitor& instance_field_visitor) const;
- // Visit direct and virtual methods.
- template <typename MethodVisitor>
- void VisitMethods(const MethodVisitor& method_visitor) const;
+ // Return the iteration range for all the fields.
+ IterationRange<DataIterator<Field>> GetFields() const;
+
+ // Return the iteration range for all the static fields.
+ IterationRange<DataIterator<Field>> GetStaticFields() const;
+
+ // Return the iteration range for all the instance fields.
+ IterationRange<DataIterator<Field>> GetInstanceFields() const;
+
+ // Return the iteration range for all the methods.
+ IterationRange<DataIterator<Method>> GetMethods() const;
+
+ // Return the iteration range for the direct methods.
+ IterationRange<DataIterator<Method>> GetDirectMethods() const;
+
+ // Return the iteration range for the virtual methods.
+ IterationRange<DataIterator<Method>> GetVirtualMethods() const;
uint32_t NumStaticFields() const {
return num_static_fields_;
@@ -151,6 +297,10 @@ class ClassAccessor {
return num_instance_fields_;
}
+ uint32_t NumFields() const {
+ return NumStaticFields() + NumInstanceFields();
+ }
+
uint32_t NumDirectMethods() const {
return num_direct_methods_;
}
@@ -159,6 +309,10 @@ class ClassAccessor {
return num_virtual_methods_;
}
+ uint32_t NumMethods() const {
+ return NumDirectMethods() + NumVirtualMethods();
+ }
+
const char* GetDescriptor() const;
dex::TypeIndex GetClassIdx() const {
@@ -169,7 +323,23 @@ class ClassAccessor {
return dex_file_;
}
+ bool HasClassData() const {
+ return ptr_pos_ != nullptr;
+ }
+
protected:
+ // Template visitor to reduce copy paste for visiting elements.
+ // No thread safety analysis since the visitor may require capabilities.
+ template <typename DataType, typename Visitor>
+ void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
+ NO_THREAD_SAFETY_ANALYSIS;
+
+ // Return an iteration range for the first <count> fields.
+ IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
+
+ // Return an iteration range for the first <count> methods.
+ IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
+
const DexFile& dex_file_;
const dex::TypeIndex descriptor_index_ = {};
const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item.
diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc
new file mode 100644
index 0000000000..d0533c1811
--- /dev/null
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex/class_accessor-inl.h"
+
+#include "base/common_art_test.h"
+
+namespace art {
+
+class ClassAccessorTest : public CommonArtTest {};
+
+TEST_F(ClassAccessorTest, TestVisiting) {
+ std::vector<std::unique_ptr<const DexFile>> dex_files(
+ OpenDexFiles(GetLibCoreDexFileNames()[0].c_str()));
+ ASSERT_GT(dex_files.size(), 0u);
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ uint32_t class_def_idx = 0u;
+ ASSERT_GT(dex_file->NumClassDefs(), 0u);
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
+ EXPECT_EQ(accessor.GetDescriptor(), dex_file->StringByTypeIdx(class_def.class_idx_));
+ ++class_def_idx;
+ // Check iterators against visitors.
+ auto methods = accessor.GetMethods();
+ auto fields = accessor.GetFields();
+ auto method_it = methods.begin();
+ auto field_it = fields.begin();
+ auto instance_fields = accessor.GetInstanceFields();
+ auto instance_field_it = instance_fields.begin();
+ accessor.VisitFieldsAndMethods(
+ // Static fields.
+ [&](const ClassAccessor::Field& field) {
+ EXPECT_TRUE(field.IsStatic());
+ EXPECT_TRUE(field_it->IsStatic());
+ EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+ ++field_it;
+ },
+ // Instance fields.
+ [&](const ClassAccessor::Field& field) {
+ EXPECT_FALSE(field.IsStatic());
+ EXPECT_FALSE(field_it->IsStatic());
+ EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+ EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags());
+ ++field_it;
+ ++instance_field_it;
+ },
+ // Direct methods.
+ [&](const ClassAccessor::Method& method) {
+ EXPECT_TRUE(method.IsStaticOrDirect());
+ EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
+ EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
+ EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
+ EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
+ ++method_it;
+ },
+ // Virtual methods.
+ [&](const ClassAccessor::Method& method) {
+ EXPECT_FALSE(method.IsStaticOrDirect());
+ EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
+ EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
+ EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
+ EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
+ ++method_it;
+ });
+ ASSERT_TRUE(field_it == fields.end());
+ ASSERT_TRUE(method_it == methods.end());
+ ASSERT_TRUE(instance_field_it == instance_fields.end());
+ }
+ EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
+ }
+}
+
+} // namespace art
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 9de260c862..f570158dfb 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,19 +45,18 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
-void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
- uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
- uint32_t new_flag = class_it.GetMemberAccessFlags();
- bool is_method = class_it.IsAtMethod();
+void DexFile::UnHideAccessFlags(uint8_t* data_ptr,
+ uint32_t new_access_flags,
+ bool is_method) {
// Go back 1 uleb to start.
- data = ReverseSearchUnsignedLeb128(data);
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
if (is_method) {
// Methods have another uleb field before the access flags
- data = ReverseSearchUnsignedLeb128(data);
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
}
- DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
- new_flag);
- UpdateUnsignedLeb128(data, new_flag);
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
+ new_access_flags);
+ UpdateUnsignedLeb128(data_ptr, new_access_flags);
}
uint32_t DexFile::CalculateChecksum() const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index f1f8b505bd..ed219808d2 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@ class DexFile {
return container_.get();
}
- // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
- static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+ // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
+ static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method);
inline IterationRange<ClassIterator> GetClasses() const;
diff --git a/libprofile/profile/profile_compilation_info_test.cc b/libprofile/profile/profile_compilation_info_test.cc
index ead7cba60b..42c3320ea5 100644
--- a/libprofile/profile/profile_compilation_info_test.cc
+++ b/libprofile/profile/profile_compilation_info_test.cc
@@ -17,20 +17,14 @@
#include <gtest/gtest.h>
#include <stdio.h>
-#include "art_method-inl.h"
+#include "base/arena_allocator.h"
+#include "base/common_art_test.h"
#include "base/unix_file/fd_file.h"
-#include "class_linker-inl.h"
-#include "common_runtime_test.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
-#include "handle_scope-inl.h"
-#include "linear_alloc.h"
-#include "mirror/class-inl.h"
-#include "mirror/class_loader.h"
#include "profile/profile_compilation_info.h"
-#include "scoped_thread_state_change-inl.h"
#include "ziparchive/zip_writer.h"
namespace art {
@@ -39,31 +33,14 @@ using Hotness = ProfileCompilationInfo::MethodHotness;
static constexpr size_t kMaxMethodIds = 65535;
-class ProfileCompilationInfoTest : public CommonRuntimeTest {
+class ProfileCompilationInfoTest : public CommonArtTest {
public:
- void PostRuntimeCreate() OVERRIDE {
- allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
+ void SetUp() OVERRIDE {
+ CommonArtTest::SetUp();
+ allocator_.reset(new ArenaAllocator(&pool_));
}
protected:
- std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader,
- const std::string& clazz) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader()));
- ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
-
- const auto pointer_size = class_linker->GetImagePointerSize();
- std::vector<ArtMethod*> methods;
- for (auto& m : klass->GetVirtualMethods(pointer_size)) {
- methods.push_back(&m);
- }
- return methods;
- }
-
bool AddMethod(const std::string& dex_location,
uint32_t checksum,
uint16_t method_index,
@@ -97,89 +74,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
return static_cast<uint32_t>(file.GetFd());
}
- bool SaveProfilingInfo(
- const std::string& filename,
- const std::vector<ArtMethod*>& methods,
- const std::set<DexCacheResolvedClasses>& resolved_classes,
- Hotness::Flag flags) {
- ProfileCompilationInfo info;
- std::vector<ProfileMethodInfo> profile_methods;
- ScopedObjectAccess soa(Thread::Current());
- for (ArtMethod* method : methods) {
- profile_methods.emplace_back(
- MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
- }
- if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) {
- return false;
- }
- if (info.GetNumberOfMethods() != profile_methods.size()) {
- return false;
- }
- ProfileCompilationInfo file_profile;
- if (!file_profile.Load(filename, false)) {
- return false;
- }
- if (!info.MergeWith(file_profile)) {
- return false;
- }
-
- return info.Save(filename, nullptr);
- }
-
- // Saves the given art methods to a profile backed by 'filename' and adds
- // some fake inline caches to it. The added inline caches are returned in
- // the out map `profile_methods_map`.
- bool SaveProfilingInfoWithFakeInlineCaches(
- const std::string& filename,
- const std::vector<ArtMethod*>& methods,
- Hotness::Flag flags,
- /*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) {
- ProfileCompilationInfo info;
- std::vector<ProfileMethodInfo> profile_methods;
- ScopedObjectAccess soa(Thread::Current());
- for (ArtMethod* method : methods) {
- std::vector<ProfileMethodInfo::ProfileInlineCache> caches;
- // Monomorphic
- for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
- std::vector<TypeReference> classes;
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(0));
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Polymorphic
- for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
- std::vector<TypeReference> classes;
- for (uint16_t k = 0; k < InlineCache::kIndividualCacheSize / 2; k++) {
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
- }
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Megamorphic
- for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
- std::vector<TypeReference> classes;
- for (uint16_t k = 0; k < 2 * InlineCache::kIndividualCacheSize; k++) {
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
- }
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Missing types
- for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
- std::vector<TypeReference> classes;
- caches.emplace_back(dex_pc, /*is_missing_types*/true, classes);
- }
- ProfileMethodInfo pmi(MethodReference(method->GetDexFile(),
- method->GetDexMethodIndex()),
- caches);
- profile_methods.push_back(pmi);
- profile_methods_map->Put(method, pmi);
- }
-
- if (!info.AddMethods(profile_methods, flags)
- || info.GetNumberOfMethods() != profile_methods.size()) {
- return false;
- }
- return info.Save(filename, nullptr);
- }
-
// Creates an inline cache which will be destructed at the end of the test.
ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
@@ -187,35 +81,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
return used_inline_caches.back().get();
}
- ProfileCompilationInfo::OfflineProfileMethodInfo ConvertProfileMethodInfo(
- const ProfileMethodInfo& pmi) {
- ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
- ProfileCompilationInfo::OfflineProfileMethodInfo offline_pmi(ic_map);
- SafeMap<DexFile*, uint8_t> dex_map; // dex files to profile index
- for (const auto& inline_cache : pmi.inline_caches) {
- ProfileCompilationInfo::DexPcData& dex_pc_data =
- ic_map->FindOrAdd(
- inline_cache.dex_pc, ProfileCompilationInfo::DexPcData(allocator_.get()))->second;
- if (inline_cache.is_missing_types) {
- dex_pc_data.SetIsMissingTypes();
- }
- for (const auto& class_ref : inline_cache.classes) {
- uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file),
- static_cast<uint8_t>(dex_map.size()))->second;
- dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex());
- if (dex_profile_index >= offline_pmi.dex_references.size()) {
- // This is a new dex.
- const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey(
- class_ref.dex_file->GetLocation());
- offline_pmi.dex_references.emplace_back(dex_key,
- class_ref.dex_file->GetLocationChecksum(),
- class_ref.dex_file->NumMethodIds());
- }
- }
- }
- return offline_pmi;
- }
-
// Creates an offline profile used for testing inline caches.
ProfileCompilationInfo::OfflineProfileMethodInfo GetOfflineProfileMethodInfo() {
ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
@@ -261,7 +126,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
ProfileCompilationInfo::InlineCacheMap* ic_map =
const_cast<ProfileCompilationInfo::InlineCacheMap*>(pmi->inline_caches);
for (auto it : *ic_map) {
- for (uint16_t k = 0; k <= 2 * InlineCache::kIndividualCacheSize; k++) {
+ for (uint16_t k = 0; k <= 2 * ProfileCompilationInfo::kIndividualInlineCacheSize; k++) {
it.second.AddClass(0, dex::TypeIndex(k));
}
}
@@ -327,6 +192,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
static constexpr int kProfileMagicSize = 4;
static constexpr int kProfileVersionSize = 4;
+ MallocArenaPool pool_;
std::unique_ptr<ArenaAllocator> allocator_;
// Cache of inline caches generated during tests.
@@ -335,61 +201,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
};
-TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
- ScratchFile profile;
-
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Save virtual methods from Main.
- std::set<DexCacheResolvedClasses> resolved_classes;
- std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
- ASSERT_TRUE(SaveProfilingInfo(
- profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup));
-
- // Check that what we saved is in the profile.
- ProfileCompilationInfo info1;
- ASSERT_TRUE(info1.Load(GetFd(profile)));
- ASSERT_EQ(info1.GetNumberOfMethods(), main_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsPostStartup());
- }
- }
-
- // Save virtual methods from Second.
- std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
- ASSERT_TRUE(SaveProfilingInfo(
- profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup));
-
- // Check that what we saved is in the profile (methods form Main and Second).
- ProfileCompilationInfo info2;
- ASSERT_TRUE(profile.GetFile()->ResetOffset());
- ASSERT_TRUE(info2.Load(GetFd(profile)));
- ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsPostStartup());
- }
- for (ArtMethod* m : second_methods) {
- Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsStartup());
- }
- }
-}
-
TEST_F(ProfileCompilationInfoTest, SaveFd) {
ScratchFile profile;
@@ -722,48 +533,6 @@ TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCaches) {
ASSERT_TRUE(*loaded_pmi1 == pmi_extra);
}
-TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
- ScratchFile profile;
-
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Save virtual methods from Main.
- std::set<DexCacheResolvedClasses> resolved_classes;
- std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
-
- SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map;
- ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches(
- profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map));
-
- // Check that what we saved is in the profile.
- ProfileCompilationInfo info;
- ASSERT_TRUE(info.Load(GetFd(profile)));
- ASSERT_EQ(info.GetNumberOfMethods(), main_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsStartup());
- const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
- std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
- info.GetMethod(m->GetDexFile()->GetLocation(),
- m->GetDexFile()->GetLocationChecksum(),
- m->GetDexMethodIndex());
- ASSERT_TRUE(offline_pmi != nullptr);
- ProfileCompilationInfo::OfflineProfileMethodInfo converted_pmi =
- ConvertProfileMethodInfo(pmi);
- ASSERT_EQ(converted_pmi, *offline_pmi);
- }
- }
-}
-
TEST_F(ProfileCompilationInfoTest, InvalidChecksumInInlineCache) {
ScratchFile profile;
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 5c20efa3f7..7ac9e984ff 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -41,10 +41,12 @@
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "class_linker.h"
+#include "class_root.h"
#include "compiled_method.h"
#include "debug/debug_info.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
+#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
@@ -268,25 +270,18 @@ class OatSymbolizer FINAL {
void WalkOatClass(const OatFile::OatClass& oat_class,
const DexFile& dex_file,
uint32_t class_def_index) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- if (class_data == nullptr) { // empty class such as a marker interface?
- return;
- }
+ ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_index));
// Note: even if this is an interface or a native class, we still have to walk it, as there
// might be a static initializer.
- ClassDataItemIterator it(dex_file, class_data);
uint32_t class_method_idx = 0;
- it.SkipAllFields();
- for (; it.HasNextMethod(); it.Next()) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
WalkOatMethod(oat_class.GetOatMethod(class_method_idx++),
dex_file,
class_def_index,
- it.GetMemberIndex(),
- it.GetMethodCodeItem(),
- it.GetMethodAccessFlags());
+ method.GetIndex(),
+ method.GetCodeItem(),
+ method.GetAccessFlags());
}
- DCHECK(!it.HasNext());
}
void WalkOatMethod(const OatFile::OatMethod& oat_method,
@@ -527,7 +522,6 @@ class OatDumper {
}
// Dumping the dex file overview is compact enough to do even if header only.
- DexFileData cumulative;
for (size_t i = 0; i < oat_dex_files_.size(); i++) {
const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
CHECK(oat_dex_file != nullptr);
@@ -538,10 +532,7 @@ class OatDumper {
<< error_msg;
continue;
}
- DexFileData data(*dex_file);
- os << "Dex file data for " << dex_file->GetLocation() << "\n";
- data.Dump(os);
- os << "\n";
+
const DexLayoutSections* const layout_sections = oat_dex_file->GetDexLayoutSections();
if (layout_sections != nullptr) {
os << "Layout data\n";
@@ -549,8 +540,6 @@ class OatDumper {
os << "\n";
}
- cumulative.Add(data);
-
// Dump .bss entries.
DumpBssEntries(
os,
@@ -574,9 +563,6 @@ class OatDumper {
sizeof(GcRoot<mirror::Class>),
[=](uint32_t index) { return dex_file->StringDataByIdx(dex::StringIndex(index)); });
}
- os << "Cumulative dex file data\n";
- cumulative.Dump(os);
- os << "\n";
if (!options_.dump_header_only_) {
VariableIndentationOutputStream vios(&os);
@@ -752,6 +738,7 @@ class OatDumper {
kByteKindCode,
kByteKindQuickMethodHeader,
kByteKindCodeInfoLocationCatalog,
+ kByteKindCodeInfoDexRegisterMask,
kByteKindCodeInfoDexRegisterMap,
kByteKindCodeInfo,
kByteKindCodeInfoInvokeInfo,
@@ -765,7 +752,7 @@ class OatDumper {
kByteKindStackMapStackMaskIndex,
kByteKindInlineInfoMethodIndexIdx,
kByteKindInlineInfoDexPc,
- kByteKindInlineInfoExtraData,
+ kByteKindInlineInfoArtMethod,
kByteKindInlineInfoDexRegisterMap,
kByteKindInlineInfoIsLast,
kByteKindCount,
@@ -802,6 +789,7 @@ class OatDumper {
Dump(os, "QuickMethodHeader ", bits[kByteKindQuickMethodHeader], sum);
Dump(os, "CodeInfo ", bits[kByteKindCodeInfo], sum);
Dump(os, "CodeInfoLocationCatalog ", bits[kByteKindCodeInfoLocationCatalog], sum);
+ Dump(os, "CodeInfoDexRegisterMask ", bits[kByteKindCodeInfoDexRegisterMask], sum);
Dump(os, "CodeInfoDexRegisterMap ", bits[kByteKindCodeInfoDexRegisterMap], sum);
Dump(os, "CodeInfoStackMasks ", bits[kByteKindCodeInfoStackMasks], sum);
Dump(os, "CodeInfoRegisterMasks ", bits[kByteKindCodeInfoRegisterMasks], sum);
@@ -862,8 +850,8 @@ class OatDumper {
inline_info_bits,
"inline info");
Dump(os,
- "InlineInfoExtraData ",
- bits[kByteKindInlineInfoExtraData],
+ "InlineInfoArtMethod ",
+ bits[kByteKindInlineInfoArtMethod],
inline_info_bits,
"inline info");
Dump(os,
@@ -913,21 +901,15 @@ class OatDumper {
continue;
}
offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
- for (size_t class_def_index = 0;
- class_def_index < dex_file->NumClassDefs();
- class_def_index++) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+ uint32_t class_def_index = 0u;
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data != nullptr) {
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- uint32_t class_method_index = 0;
- while (it.HasNextMethod()) {
- AddOffsets(oat_class.GetOatMethod(class_method_index++));
- it.Next();
- }
+ for (uint32_t class_method_index = 0;
+ class_method_index < accessor.NumMethods();
+ ++class_method_index) {
+ AddOffsets(oat_class.GetOatMethod(class_method_index));
}
+ ++class_def_index;
}
}
@@ -950,120 +932,6 @@ class OatDumper {
offsets_.insert(oat_method.GetVmapTableOffset());
}
- // Dex file data, may be for multiple different dex files.
- class DexFileData {
- public:
- DexFileData() {}
-
- explicit DexFileData(const DexFile& dex_file)
- : num_string_ids_(dex_file.NumStringIds()),
- num_method_ids_(dex_file.NumMethodIds()),
- num_field_ids_(dex_file.NumFieldIds()),
- num_type_ids_(dex_file.NumTypeIds()),
- num_class_defs_(dex_file.NumClassDefs()) {
- for (size_t class_def_index = 0; class_def_index < num_class_defs_; ++class_def_index) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- WalkClass(dex_file, class_def);
- }
- }
-
- void Add(const DexFileData& other) {
- AddAll(unique_string_ids_from_code_, other.unique_string_ids_from_code_);
- num_string_ids_from_code_ += other.num_string_ids_from_code_;
- AddAll(dex_code_item_ptrs_, other.dex_code_item_ptrs_);
- dex_code_bytes_ += other.dex_code_bytes_;
- num_string_ids_ += other.num_string_ids_;
- num_method_ids_ += other.num_method_ids_;
- num_field_ids_ += other.num_field_ids_;
- num_type_ids_ += other.num_type_ids_;
- num_class_defs_ += other.num_class_defs_;
- }
-
- void Dump(std::ostream& os) {
- os << "Num string ids: " << num_string_ids_ << "\n";
- os << "Num method ids: " << num_method_ids_ << "\n";
- os << "Num field ids: " << num_field_ids_ << "\n";
- os << "Num type ids: " << num_type_ids_ << "\n";
- os << "Num class defs: " << num_class_defs_ << "\n";
- os << "Unique strings loaded from dex code: " << unique_string_ids_from_code_.size() << "\n";
- os << "Total strings loaded from dex code: " << num_string_ids_from_code_ << "\n";
- os << "Number of unique dex code items: " << dex_code_item_ptrs_.size() << "\n";
- os << "Total number of dex code bytes: " << dex_code_bytes_ << "\n";
- }
-
- private:
- // All of the elements from one container to another.
- template <typename Dest, typename Src>
- static void AddAll(Dest& dest, const Src& src) {
- dest.insert(src.begin(), src.end());
- }
-
- void WalkClass(const DexFile& dex_file, const DexFile::ClassDef& class_def) {
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- if (class_data == nullptr) { // empty class such as a marker interface?
- return;
- }
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
- while (it.HasNextMethod()) {
- WalkCodeItem(dex_file, it.GetMethodCodeItem());
- it.Next();
- }
- DCHECK(!it.HasNext());
- }
-
- void WalkCodeItem(const DexFile& dex_file, const DexFile::CodeItem* code_item) {
- if (code_item == nullptr) {
- return;
- }
- CodeItemInstructionAccessor instructions(dex_file, code_item);
-
- // If we inserted a new dex code item pointer, add to total code bytes.
- const uint16_t* code_ptr = instructions.Insns();
- if (dex_code_item_ptrs_.insert(code_ptr).second) {
- dex_code_bytes_ += instructions.InsnsSizeInCodeUnits() * sizeof(code_ptr[0]);
- }
-
- for (const DexInstructionPcPair& inst : instructions) {
- switch (inst->Opcode()) {
- case Instruction::CONST_STRING: {
- const dex::StringIndex string_index(inst->VRegB_21c());
- unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
- ++num_string_ids_from_code_;
- break;
- }
- case Instruction::CONST_STRING_JUMBO: {
- const dex::StringIndex string_index(inst->VRegB_31c());
- unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
- ++num_string_ids_from_code_;
- break;
- }
- default:
- break;
- }
- }
- }
-
- // Unique string ids loaded from dex code.
- std::set<StringReference> unique_string_ids_from_code_;
-
- // Total string ids loaded from dex code.
- size_t num_string_ids_from_code_ = 0;
-
- // Unique code pointers.
- std::set<const void*> dex_code_item_ptrs_;
-
- // Total "unique" dex code bytes.
- size_t dex_code_bytes_ = 0;
-
- // Other dex ids.
- size_t num_string_ids_ = 0;
- size_t num_method_ids_ = 0;
- size_t num_field_ids_ = 0;
- size_t num_type_ids_ = 0;
- size_t num_class_defs_ = 0;
- };
-
bool DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
bool success = true;
bool stop_analysis = false;
@@ -1834,13 +1702,13 @@ class OatDumper {
// Stack maps
stats_.AddBits(
Stats::kByteKindStackMapNativePc,
- stack_maps.NumColumnBits(StackMap::kNativePcOffset) * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kPackedNativePc) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapDexPc,
stack_maps.NumColumnBits(StackMap::kDexPc) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapDexRegisterMap,
- stack_maps.NumColumnBits(StackMap::kDexRegisterMapOffset) * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kDexRegisterMapIndex) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapInlineInfoIndex,
stack_maps.NumColumnBits(StackMap::kInlineInfoIndex) * num_stack_maps);
@@ -1854,7 +1722,7 @@ class OatDumper {
// Stack masks
stats_.AddBits(
Stats::kByteKindCodeInfoStackMasks,
- code_info.stack_masks_.size_in_bits());
+ code_info.stack_masks_.DataBitSize());
// Register masks
stats_.AddBits(
@@ -1867,16 +1735,12 @@ class OatDumper {
code_info.invoke_infos_.DataBitSize());
// Location catalog
- const size_t location_catalog_bytes =
- helper.GetCodeInfo().GetDexRegisterLocationCatalogSize();
stats_.AddBits(Stats::kByteKindCodeInfoLocationCatalog,
- kBitsPerByte * location_catalog_bytes);
- // Dex register bytes.
- const size_t dex_register_bytes =
- helper.GetCodeInfo().GetDexRegisterMapsSize(code_item_accessor.RegistersSize());
- stats_.AddBits(
- Stats::kByteKindCodeInfoDexRegisterMap,
- kBitsPerByte * dex_register_bytes);
+ code_info.dex_register_catalog_.DataBitSize());
+ stats_.AddBits(Stats::kByteKindCodeInfoDexRegisterMask,
+ code_info.dex_register_masks_.DataBitSize());
+ stats_.AddBits(Stats::kByteKindCodeInfoDexRegisterMap,
+ code_info.dex_register_maps_.DataBitSize());
// Inline infos.
const BitTable<InlineInfo::kCount>& inline_infos = code_info.inline_infos_;
@@ -1889,11 +1753,12 @@ class OatDumper {
Stats::kByteKindInlineInfoDexPc,
inline_infos.NumColumnBits(InlineInfo::kDexPc) * num_inline_infos);
stats_.AddBits(
- Stats::kByteKindInlineInfoExtraData,
- inline_infos.NumColumnBits(InlineInfo::kExtraData) * num_inline_infos);
+ Stats::kByteKindInlineInfoArtMethod,
+ inline_infos.NumColumnBits(InlineInfo::kArtMethodHi) * num_inline_infos +
+ inline_infos.NumColumnBits(InlineInfo::kArtMethodLo) * num_inline_infos);
stats_.AddBits(
Stats::kByteKindInlineInfoDexRegisterMap,
- inline_infos.NumColumnBits(InlineInfo::kDexRegisterMapOffset) * num_inline_infos);
+ inline_infos.NumColumnBits(InlineInfo::kDexRegisterMapIndex) * num_inline_infos);
stats_.AddBits(Stats::kByteKindInlineInfoIsLast, num_inline_infos);
}
}
@@ -3388,7 +3253,7 @@ class IMTDumper {
PrepareClass(runtime, klass, prepared);
}
- mirror::Class* object_class = mirror::Class::GetJavaLangClass()->GetSuperClass();
+ ObjPtr<mirror::Class> object_class = GetClassRoot<mirror::Object>();
DCHECK(object_class->IsObjectClass());
bool result = klass->GetImt(pointer_size) == object_class->GetImt(pointer_size);
@@ -3422,8 +3287,8 @@ class IMTDumper {
Handle<mirror::ClassLoader> h_loader,
const std::string& class_name,
const PointerSize pointer_size,
- mirror::Class** klass_out,
- std::unordered_set<std::string>* prepared)
+ /*out*/ ObjPtr<mirror::Class>* klass_out,
+ /*inout*/ std::unordered_set<std::string>* prepared)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (class_name.empty()) {
return nullptr;
@@ -3436,7 +3301,8 @@ class IMTDumper {
descriptor = DotToDescriptor(class_name.c_str());
}
- mirror::Class* klass = runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), h_loader);
+ ObjPtr<mirror::Class> klass =
+ runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), h_loader);
if (klass == nullptr) {
self->ClearException();
@@ -3456,7 +3322,7 @@ class IMTDumper {
static ImTable* PrepareAndGetImTable(Runtime* runtime,
Handle<mirror::Class> h_klass,
const PointerSize pointer_size,
- std::unordered_set<std::string>* prepared)
+ /*inout*/ std::unordered_set<std::string>* prepared)
REQUIRES_SHARED(Locks::mutator_lock_) {
PrepareClass(runtime, h_klass, prepared);
return h_klass->GetImt(pointer_size);
@@ -3468,7 +3334,7 @@ class IMTDumper {
std::unordered_set<std::string>* prepared)
REQUIRES_SHARED(Locks::mutator_lock_) {
const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
- mirror::Class* klass;
+ ObjPtr<mirror::Class> klass;
ImTable* imt = PrepareAndGetImTable(runtime,
Thread::Current(),
h_loader,
@@ -3524,10 +3390,10 @@ class IMTDumper {
const std::string& class_name,
const std::string& method,
Handle<mirror::ClassLoader> h_loader,
- std::unordered_set<std::string>* prepared)
+ /*inout*/ std::unordered_set<std::string>* prepared)
REQUIRES_SHARED(Locks::mutator_lock_) {
const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
- mirror::Class* klass;
+ ObjPtr<mirror::Class> klass;
ImTable* imt = PrepareAndGetImTable(runtime,
Thread::Current(),
h_loader,
@@ -3630,7 +3496,7 @@ class IMTDumper {
// and note in the given set that the work was done.
static void PrepareClass(Runtime* runtime,
Handle<mirror::Class> h_klass,
- std::unordered_set<std::string>* done)
+ /*inout*/ std::unordered_set<std::string>* done)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (!h_klass->ShouldHaveImt()) {
return;
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index bbe89ca33c..293acdc3a6 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -151,10 +151,6 @@ class OatDumpTest : public CommonRuntimeTest {
exec_argv.push_back("--symbolize=" + core_oat_location_);
exec_argv.push_back("--output=" + core_oat_location_ + ".symbolize");
} else {
- expected_prefixes.push_back("Dex file data for");
- expected_prefixes.push_back("Num string ids:");
- expected_prefixes.push_back("Num field ids:");
- expected_prefixes.push_back("Num method ids:");
expected_prefixes.push_back("LOCATION:");
expected_prefixes.push_back("MAGIC:");
expected_prefixes.push_back("DEX FILE COUNT:");
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index be1ab7812a..765225ae95 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -401,7 +401,7 @@ JNIEXPORT jboolean JVM_HoldsLock(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jo
art::ThrowNullPointerException("object == null");
return JNI_FALSE;
}
- return soa.Self()->HoldsLock(object.Ptr());
+ return soa.Self()->HoldsLock(object);
}
JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) {
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index fcbafe7e71..a660fb56c4 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -31,6 +31,7 @@
#include "base/leb128.h"
#include "fixed_up_dex_file.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_verifier.h"
@@ -51,14 +52,12 @@ static void RecomputeDexChecksum(art::DexFile* dex_file) {
}
static void UnhideApis(const art::DexFile& target_dex_file) {
- for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
- const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
- if (class_data != nullptr) {
- for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
- class_it.HasNext();
- class_it.Next()) {
- art::DexFile::UnHideAccessFlags(class_it);
- }
+ for (art::ClassAccessor accessor : target_dex_file.GetClasses()) {
+ for (const art::ClassAccessor::Field& field : accessor.GetFields()) {
+ field.UnHideAccessFlags();
+ }
+ for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
+ method.UnHideAccessFlags();
}
}
}
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
index c9d71b4857..9bea18a763 100644
--- a/openjdkjvmti/ti_class.cc
+++ b/openjdkjvmti/ti_class.cc
@@ -63,7 +63,7 @@
#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_reference.h"
-#include "mirror/reference.h"
+#include "mirror/reference-inl.h"
#include "nativehelper/scoped_local_ref.h"
#include "reflection.h"
#include "runtime.h"
@@ -71,9 +71,11 @@
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"
+#include "ti_class_definition.h"
#include "ti_class_loader-inl.h"
#include "ti_phase.h"
#include "ti_redefine.h"
+#include "transform.h"
#include "well_known_classes.h"
namespace openjdkjvmti {
@@ -713,7 +715,7 @@ jvmtiError ClassUtil::GetClassSignature(jvmtiEnv* env,
if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
art::StackHandleScope<1> hs(soa.Self());
art::Handle<art::mirror::Class> h_klass = hs.NewHandle(klass);
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForClass(h_klass);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc
index 1b641cd905..dce2733e7e 100644
--- a/openjdkjvmti/ti_class_definition.cc
+++ b/openjdkjvmti/ti_class_definition.cc
@@ -33,6 +33,7 @@
#include "base/array_slice.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "dex/dex_file.h"
#include "fixed_up_dex_file.h"
#include "handle.h"
@@ -162,8 +163,7 @@ static void GetDexDataForRetransformation(art::Handle<art::mirror::Class> klass,
<< "Expected java/lang/Long but found object of type "
<< orig_dex->GetClass()->PrettyClass();
art::ObjPtr<art::mirror::Class> prim_long_class(
- art::Runtime::Current()->GetClassLinker()->GetClassRoot(
- art::ClassLinker::kPrimitiveLong));
+ art::GetClassRoot(art::ClassRoot::kPrimitiveLong));
art::JValue val;
if (!art::UnboxPrimitiveForResult(orig_dex.Get(), prim_long_class, &val)) {
// This should never happen.
@@ -226,8 +226,7 @@ static const art::DexFile* GetQuickenedDexFile(art::Handle<art::mirror::Class> k
<< "Expected java/lang/Long but found object of type "
<< orig_dex->GetClass()->PrettyClass();
art::ObjPtr<art::mirror::Class> prim_long_class(
- art::Runtime::Current()->GetClassLinker()->GetClassRoot(
- art::ClassLinker::kPrimitiveLong));
+ art::GetClassRoot(art::ClassRoot::kPrimitiveLong));
art::JValue val;
if (!art::UnboxPrimitiveForResult(orig_dex.Ptr(), prim_long_class, &val)) {
LOG(FATAL) << "Unable to unwrap a long value!";
diff --git a/openjdkjvmti/ti_class_loader.h b/openjdkjvmti/ti_class_loader.h
index a3857e595a..577c28585e 100644
--- a/openjdkjvmti/ti_class_loader.h
+++ b/openjdkjvmti/ti_class_loader.h
@@ -36,32 +36,19 @@
#include <jni.h>
-#include "art_jvmti.h"
-#include "art_method.h"
-#include "base/array_slice.h"
#include "base/globals.h"
-#include "base/mem_map.h"
-#include "class_linker.h"
-#include "dex/dex_file.h"
-#include "dex/utf.h"
-#include "gc_root-inl.h"
-#include "jni/jni_env_ext-inl.h"
+#include "base/mutex.h"
#include "jvmti.h"
-#include "linear_alloc.h"
-#include "mirror/array-inl.h"
#include "mirror/array.h"
-#include "mirror/class-inl.h"
-#include "mirror/class.h"
-#include "mirror/class_loader-inl.h"
-#include "mirror/string-inl.h"
-#include "oat_file.h"
-#include "obj_ptr.h"
-#include "scoped_thread_state_change-inl.h"
-#include "stack.h"
-#include "thread_list.h"
-#include "ti_class_definition.h"
-#include "transform.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
+
+namespace art {
+
+class DexFile;
+template <class MirrorType> class Handle;
+template <class MirrorType> class ObjPtr;
+class Thread;
+
+} // namespace art
namespace openjdkjvmti {
diff --git a/openjdkjvmti/ti_field.cc b/openjdkjvmti/ti_field.cc
index 328e2a1e40..2a860d9f43 100644
--- a/openjdkjvmti/ti_field.cc
+++ b/openjdkjvmti/ti_field.cc
@@ -91,7 +91,7 @@ jvmtiError FieldUtil::GetFieldName(jvmtiEnv* env,
if (generic_ptr != nullptr) {
*generic_ptr = nullptr;
if (!art_field->GetDeclaringClass()->IsProxyClass()) {
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForField(art_field);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index c0c312c490..d0b7224f93 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -345,7 +345,7 @@ jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
if (generic_ptr != nullptr) {
*generic_ptr = nullptr;
if (!art_method->GetDeclaringClass()->IsProxyClass()) {
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForMethod(art_method);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 8a726bca14..50d8dfeb70 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -42,6 +42,7 @@
#include "base/array_ref.h"
#include "base/stringpiece.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "debugger.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file.h"
@@ -60,6 +61,7 @@
#include "jit/jit_code_cache.h"
#include "jni/jni_env_ext-inl.h"
#include "jvmti_allocator.h"
+#include "linear_alloc.h"
#include "mirror/class-inl.h"
#include "mirror/class_ext.h"
#include "mirror/object.h"
@@ -67,6 +69,8 @@
#include "non_debuggable_classes.h"
#include "object_lock.h"
#include "runtime.h"
+#include "stack.h"
+#include "thread_list.h"
#include "ti_breakpoint.h"
#include "ti_class_loader.h"
#include "transform.h"
@@ -485,7 +489,7 @@ art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
art::ObjPtr<art::mirror::DexCache>::DownCast(
- cl->GetClassRoot(art::ClassLinker::kJavaLangDexCache)->AllocObject(driver_->self_))));
+ art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_))));
if (cache.IsNull()) {
driver_->self_->AssertPendingOOMException();
return nullptr;
@@ -522,7 +526,7 @@ art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile(
return art::mirror::ByteArray::AllocateAndFill(
driver_->self_,
reinterpret_cast<const signed char*>(original_dex_file_.data()),
- original_dex_file_.size());
+ original_dex_file_.size()).Ptr();
}
// See if we already have one set.
@@ -859,12 +863,10 @@ class RedefinitionDataHolder {
art::Thread* self,
std::vector<Redefiner::ClassRedefinition>* redefinitions)
REQUIRES_SHARED(art::Locks::mutator_lock_) :
- arr_(
- hs->NewHandle(
- art::mirror::ObjectArray<art::mirror::Object>::Alloc(
- self,
- runtime->GetClassLinker()->GetClassRoot(art::ClassLinker::kObjectArrayClass),
- redefinitions->size() * kNumSlots))),
+ arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
+ self,
+ art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()),
+ redefinitions->size() * kNumSlots))),
redefinitions_(redefinitions) {}
bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h
index 227eacd180..e337491ae3 100644
--- a/openjdkjvmti/ti_redefine.h
+++ b/openjdkjvmti/ti_redefine.h
@@ -37,34 +37,18 @@
#include <jni.h>
#include "art_jvmti.h"
-#include "art_method.h"
#include "base/array_ref.h"
#include "base/globals.h"
-#include "base/mem_map.h"
-#include "class_linker.h"
#include "dex/dex_file.h"
-#include "dex/utf.h"
-#include "gc_root-inl.h"
#include "jni/jni_env_ext-inl.h"
#include "jvmti.h"
-#include "linear_alloc.h"
-#include "mirror/array-inl.h"
#include "mirror/array.h"
-#include "mirror/class-inl.h"
#include "mirror/class.h"
-#include "mirror/class_loader-inl.h"
-#include "mirror/string-inl.h"
-#include "oat_file.h"
#include "obj_ptr.h"
-#include "scoped_thread_state_change-inl.h"
-#include "stack.h"
-#include "thread_list.h"
-#include "ti_class_definition.h"
-#include "transform.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
namespace openjdkjvmti {
+class ArtClassDefinition;
class RedefinitionDataHolder;
class RedefinitionDataIter;
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
index eee8108b01..318d98d877 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -322,7 +322,9 @@ struct GetAllStackTracesVectorClosure : public art::Closure {
};
template <typename Data>
-static void RunCheckpointAndWait(Data* data, size_t max_frame_count) {
+static void RunCheckpointAndWait(Data* data, size_t max_frame_count)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ // Note: requires the mutator lock as the checkpoint requires the mutator lock.
GetAllStackTracesVectorClosure<Data> closure(max_frame_count, data);
size_t barrier_count = art::Runtime::Current()->GetThreadList()->RunCheckpoint(&closure, nullptr);
if (barrier_count == 0) {
@@ -380,9 +382,11 @@ jvmtiError StackUtil::GetAllStackTraces(jvmtiEnv* env,
};
AllStackTracesData data;
- RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
-
art::Thread* current = art::Thread::Current();
+ {
+ art::ScopedObjectAccess soa(current);
+ RunCheckpointAndWait(&data, static_cast<size_t>(max_frame_count));
+ }
// Convert the data into our output format.
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index dc9d990e29..a6d3903f19 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -43,6 +43,7 @@
#include "base/unix_file/fd_file.h"
#include "base/unix_file/random_access_file_utils.h"
#include "base/utils.h"
+#include "class_root.h"
#include "elf_file.h"
#include "elf_file_impl.h"
#include "elf_utils.h"
@@ -1053,8 +1054,8 @@ void PatchOat::VisitObject(mirror::Object* object) {
native_visitor);
}
}
- } else if (object->GetClass() == mirror::Method::StaticClass() ||
- object->GetClass() == mirror::Constructor::StaticClass()) {
+ } else if (object->GetClass() == GetClassRoot<mirror::Method>() ||
+ object->GetClass() == GetClassRoot<mirror::Constructor>()) {
// Need to go update the ArtMethod.
auto* dest = down_cast<mirror::Executable*>(copy);
auto* src = down_cast<mirror::Executable*>(object);
diff --git a/profman/boot_image_profile.cc b/profman/boot_image_profile.cc
index 89c9eb8b03..6715680361 100644
--- a/profman/boot_image_profile.cc
+++ b/profman/boot_image_profile.cc
@@ -18,6 +18,7 @@
#include <set>
#include "boot_image_profile.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
@@ -74,38 +75,31 @@ void GenerateBootImageProfile(
}
}
// Walk all of the classes and add them to the profile if they meet the requirements.
- for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
- TypeReference ref(dex_file.get(), class_def.class_idx_);
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ TypeReference ref(dex_file.get(), accessor.GetClassIdx());
bool is_clean = true;
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data != nullptr) {
- ClassDataItemIterator it(*dex_file, class_data);
- while (it.HasNextStaticField()) {
- const uint32_t flags = it.GetFieldAccessFlags();
- if ((flags & kAccFinal) == 0) {
- // Not final static field will probably dirty the class.
- is_clean = false;
- break;
- }
- it.Next();
+ auto method_visitor = [&](const ClassAccessor::Method& method) {
+ const uint32_t flags = method.GetAccessFlags();
+ if ((flags & kAccNative) != 0) {
+ // Native method will get dirtied.
+ is_clean = false;
}
- it.SkipInstanceFields();
- while (it.HasNextMethod()) {
- const uint32_t flags = it.GetMethodAccessFlags();
- if ((flags & kAccNative) != 0) {
- // Native method will get dirtied.
- is_clean = false;
- break;
- }
- if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) {
- // Class initializer, may get dirtied (not sure).
- is_clean = false;
- break;
- }
- it.Next();
+ if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) {
+ // Class initializer, may get dirtied (not sure).
+ is_clean = false;
}
- }
+ };
+ accessor.VisitFieldsAndMethods(
+ [&](const ClassAccessor::Field& field) {
+ if (!field.IsFinal()) {
+ // Not final static field will probably dirty the class.
+ is_clean = false;
+ }
+ },
+ /*instance_fields*/ VoidFunctor(),
+ method_visitor,
+ method_visitor);
+
++(is_clean ? clean_count : dirty_count);
// This counter is how many profiles contain the class.
size_t counter = 0;
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index bd44e491b0..370f59dc8a 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -22,6 +22,7 @@
#include "base/utils.h"
#include "common_runtime_test.h"
#include "dex/descriptors_names.h"
+#include "dex/type_reference.h"
#include "exec_utils.h"
#include "linear_alloc.h"
#include "mirror/class-inl.h"
@@ -33,6 +34,7 @@
namespace art {
using Hotness = ProfileCompilationInfo::MethodHotness;
+using TypeReferenceSet = std::set<TypeReference, TypeReferenceValueComparator>;
static constexpr size_t kMaxMethodIds = 65535;
@@ -308,25 +310,24 @@ class ProfileAssistantTest : public CommonRuntimeTest {
return true;
}
- mirror::Class* GetClass(jobject class_loader, const std::string& clazz) {
+ ObjPtr<mirror::Class> GetClass(ScopedObjectAccess& soa,
+ jobject class_loader,
+ const std::string& clazz) REQUIRES_SHARED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(ObjPtr<mirror::ClassLoader>::DownCast(self->DecodeJObject(class_loader))));
- return class_linker->FindClass(self, clazz.c_str(), h_loader);
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
+ ObjPtr<mirror::ClassLoader>::DownCast(soa.Self()->DecodeJObject(class_loader))));
+ return class_linker->FindClass(soa.Self(), clazz.c_str(), h_loader);
}
ArtMethod* GetVirtualMethod(jobject class_loader,
const std::string& clazz,
const std::string& name) {
- mirror::Class* klass = GetClass(class_loader, clazz);
+ ScopedObjectAccess soa(Thread::Current());
+ ObjPtr<mirror::Class> klass = GetClass(soa, class_loader, clazz);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const auto pointer_size = class_linker->GetImagePointerSize();
ArtMethod* method = nullptr;
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
for (auto& m : klass->GetVirtualMethods(pointer_size)) {
if (name == m.GetName()) {
EXPECT_TRUE(method == nullptr);
@@ -336,9 +337,14 @@ class ProfileAssistantTest : public CommonRuntimeTest {
return method;
}
+ static TypeReference MakeTypeReference(ObjPtr<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return TypeReference(&klass->GetDexFile(), klass->GetDexTypeIndex());
+ }
+
// Verify that given method has the expected inline caches and nothing else.
void AssertInlineCaches(ArtMethod* method,
- const std::set<mirror::Class*>& expected_clases,
+ const TypeReferenceSet& expected_clases,
const ProfileCompilationInfo& info,
bool is_megamorphic,
bool is_missing_types)
@@ -355,12 +361,11 @@ class ProfileAssistantTest : public CommonRuntimeTest {
ASSERT_EQ(dex_pc_data.is_missing_types, is_missing_types);
ASSERT_EQ(expected_clases.size(), dex_pc_data.classes.size());
size_t found = 0;
- for (mirror::Class* it : expected_clases) {
+ for (const TypeReference& type_ref : expected_clases) {
for (const auto& class_ref : dex_pc_data.classes) {
ProfileCompilationInfo::DexReference dex_ref =
pmi->dex_references[class_ref.dex_profile_index];
- if (dex_ref.MatchesDex(&(it->GetDexFile())) &&
- class_ref.type_index == it->GetDexTypeIndex()) {
+ if (dex_ref.MatchesDex(type_ref.dex_file) && class_ref.type_index == type_ref.TypeIndex()) {
found++;
}
}
@@ -715,7 +720,7 @@ TEST_F(ProfileAssistantTest, TestProfileCreationGenerateMethods) {
ASSERT_TRUE(info.Load(GetFd(profile_file)));
// Verify that the profile has matching methods.
ScopedObjectAccess soa(Thread::Current());
- ObjPtr<mirror::Class> klass = GetClass(nullptr, "Ljava/lang/Math;");
+ ObjPtr<mirror::Class> klass = GetClass(soa, /* class_loader */ nullptr, "Ljava/lang/Math;");
ASSERT_TRUE(klass != nullptr);
size_t method_count = 0;
for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
@@ -907,9 +912,10 @@ TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
jobject class_loader = LoadDex("ProfileTestMultiDex");
ASSERT_NE(class_loader, nullptr);
- mirror::Class* sub_a = GetClass(class_loader, "LSubA;");
- mirror::Class* sub_b = GetClass(class_loader, "LSubB;");
- mirror::Class* sub_c = GetClass(class_loader, "LSubC;");
+ StackHandleScope<3> hs(soa.Self());
+ Handle<mirror::Class> sub_a = hs.NewHandle(GetClass(soa, class_loader, "LSubA;"));
+ Handle<mirror::Class> sub_b = hs.NewHandle(GetClass(soa, class_loader, "LSubB;"));
+ Handle<mirror::Class> sub_c = hs.NewHandle(GetClass(soa, class_loader, "LSubC;"));
ASSERT_TRUE(sub_a != nullptr);
ASSERT_TRUE(sub_b != nullptr);
@@ -921,8 +927,8 @@ TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
"LTestInline;",
"inlineMonomorphic");
ASSERT_TRUE(inline_monomorphic != nullptr);
- std::set<mirror::Class*> expected_monomorphic;
- expected_monomorphic.insert(sub_a);
+ TypeReferenceSet expected_monomorphic;
+ expected_monomorphic.insert(MakeTypeReference(sub_a.Get()));
AssertInlineCaches(inline_monomorphic,
expected_monomorphic,
info,
@@ -936,10 +942,10 @@ TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
"LTestInline;",
"inlinePolymorphic");
ASSERT_TRUE(inline_polymorhic != nullptr);
- std::set<mirror::Class*> expected_polymorphic;
- expected_polymorphic.insert(sub_a);
- expected_polymorphic.insert(sub_b);
- expected_polymorphic.insert(sub_c);
+ TypeReferenceSet expected_polymorphic;
+ expected_polymorphic.insert(MakeTypeReference(sub_a.Get()));
+ expected_polymorphic.insert(MakeTypeReference(sub_b.Get()));
+ expected_polymorphic.insert(MakeTypeReference(sub_c.Get()));
AssertInlineCaches(inline_polymorhic,
expected_polymorphic,
info,
@@ -953,7 +959,7 @@ TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
"LTestInline;",
"inlineMegamorphic");
ASSERT_TRUE(inline_megamorphic != nullptr);
- std::set<mirror::Class*> expected_megamorphic;
+ TypeReferenceSet expected_megamorphic;
AssertInlineCaches(inline_megamorphic,
expected_megamorphic,
info,
@@ -967,7 +973,7 @@ TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
"LTestInline;",
"inlineMissingTypes");
ASSERT_TRUE(inline_missing_types != nullptr);
- std::set<mirror::Class*> expected_missing_Types;
+ TypeReferenceSet expected_missing_Types;
AssertInlineCaches(inline_missing_types,
expected_missing_Types,
info,
diff --git a/profman/profman.cc b/profman/profman.cc
index 1f7723946c..096e5dc3bd 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -43,6 +43,7 @@
#include "boot_image_profile.h"
#include "dex/art_dex_file_loader.h"
#include "dex/bytecode_utils.h"
+#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
@@ -929,19 +930,11 @@ class ProfMan FINAL {
dex_resolved_classes.first->AddClass(class_ref.TypeIndex());
std::vector<ProfileMethodInfo> methods;
if (method_str == kClassAllMethods) {
- // Add all of the methods.
- const DexFile::ClassDef* class_def = dex_file->FindClassDef(class_ref.TypeIndex());
- const uint8_t* class_data = dex_file->GetClassData(*class_def);
- if (class_data != nullptr) {
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- while (it.HasNextMethod()) {
- if (it.GetMethodCodeItemOffset() != 0) {
- // Add all of the methods that have code to the profile.
- const uint32_t method_idx = it.GetMemberIndex();
- methods.push_back(ProfileMethodInfo(MethodReference(dex_file, method_idx)));
- }
- it.Next();
+ ClassAccessor accessor(*dex_file, *dex_file->FindClassDef(class_ref.TypeIndex()));
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ if (method.GetCodeItemOffset() != 0) {
+ // Add all of the methods that have code to the profile.
+ methods.push_back(ProfileMethodInfo(method.GetReference()));
}
}
}
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 92607f51a0..777a1fc5ee 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -40,6 +40,7 @@ libart_cc_defaults {
"check_jni.cc",
"class_linker.cc",
"class_loader_context.cc",
+ "class_root.cc",
"class_table.cc",
"common_throws.cc",
"compiler_filter.cc",
@@ -129,7 +130,6 @@ libart_cc_defaults {
"mirror/method_handles_lookup.cc",
"mirror/method_type.cc",
"mirror/object.cc",
- "mirror/reference.cc",
"mirror/stack_trace_element.cc",
"mirror/string.cc",
"mirror/throwable.cc",
@@ -574,6 +574,7 @@ art_cc_test {
"interpreter/safe_math_test.cc",
"interpreter/unstarted_runtime_test.cc",
"jdwp/jdwp_options_test.cc",
+ "jit/profiling_info_test.cc",
"jni/java_vm_ext_test.cc",
"method_handles_test.cc",
"mirror/dex_cache_test.cc",
diff --git a/runtime/arch/code_offset.h b/runtime/arch/code_offset.h
deleted file mode 100644
index f0c6d22ef2..0000000000
--- a/runtime/arch/code_offset.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_ARCH_CODE_OFFSET_H_
-#define ART_RUNTIME_ARCH_CODE_OFFSET_H_
-
-#include <iosfwd>
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-#include "base/bit_utils.h"
-#include "base/macros.h"
-
-namespace art {
-
-// CodeOffset is a holder for compressed code offsets. Since some architectures have alignment
-// requirements it is possible to compress code offsets to reduce stack map sizes.
-class CodeOffset {
- public:
- ALWAYS_INLINE static CodeOffset FromOffset(uint32_t offset, InstructionSet isa = kRuntimeISA) {
- return CodeOffset(offset / GetInstructionSetInstructionAlignment(isa));
- }
-
- ALWAYS_INLINE static CodeOffset FromCompressedOffset(uint32_t offset) {
- return CodeOffset(offset);
- }
-
- ALWAYS_INLINE uint32_t Uint32Value(InstructionSet isa = kRuntimeISA) const {
- uint32_t decoded = value_ * GetInstructionSetInstructionAlignment(isa);
- DCHECK_GE(decoded, value_) << "Integer overflow";
- return decoded;
- }
-
- // Return compressed internal value.
- ALWAYS_INLINE uint32_t CompressedValue() const {
- return value_;
- }
-
- ALWAYS_INLINE CodeOffset() = default;
- ALWAYS_INLINE CodeOffset(const CodeOffset&) = default;
- ALWAYS_INLINE CodeOffset& operator=(const CodeOffset&) = default;
- ALWAYS_INLINE CodeOffset& operator=(CodeOffset&&) = default;
-
- private:
- ALWAYS_INLINE explicit CodeOffset(uint32_t value) : value_(value) {}
-
- uint32_t value_ = 0u;
-};
-
-inline bool operator==(const CodeOffset& a, const CodeOffset& b) {
- return a.CompressedValue() == b.CompressedValue();
-}
-
-inline bool operator!=(const CodeOffset& a, const CodeOffset& b) {
- return !(a == b);
-}
-
-inline bool operator<(const CodeOffset& a, const CodeOffset& b) {
- return a.CompressedValue() < b.CompressedValue();
-}
-
-inline bool operator<=(const CodeOffset& a, const CodeOffset& b) {
- return a.CompressedValue() <= b.CompressedValue();
-}
-
-inline bool operator>(const CodeOffset& a, const CodeOffset& b) {
- return a.CompressedValue() > b.CompressedValue();
-}
-
-inline bool operator>=(const CodeOffset& a, const CodeOffset& b) {
- return a.CompressedValue() >= b.CompressedValue();
-}
-
-inline std::ostream& operator<<(std::ostream& os, const CodeOffset& offset) {
- return os << offset.Uint32Value();
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_ARCH_CODE_OFFSET_H_
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 78516e3aeb..b0c0e43e35 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -21,6 +21,7 @@
#include "base/callee_save_type.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "imt_conflict_table.h"
@@ -2096,7 +2097,7 @@ TEST_F(StubTest, ReadBarrierForRoot) {
EXPECT_FALSE(self->IsExceptionPending());
- GcRoot<mirror::Class>& root = mirror::String::java_lang_String_;
+ GcRoot<mirror::Class> root(GetClassRoot<mirror::String>());
size_t result = Invoke3(reinterpret_cast<size_t>(&root), 0U, 0U, readBarrierForRootSlow, self);
EXPECT_FALSE(self->IsExceptionPending());
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 384581fc4f..c5fb7d5f40 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -21,7 +21,7 @@
#include <android-base/logging.h>
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/primitive.h"
#include "gc/accounting/card_table-inl.h"
@@ -34,12 +34,16 @@
namespace art {
+inline bool ArtField::IsProxyField() {
+ return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass<kVerifyNone>();
+}
+
template<ReadBarrierOption kReadBarrierOption>
inline ObjPtr<mirror::Class> ArtField::GetDeclaringClass() {
GcRootSource gc_root_source(this);
ObjPtr<mirror::Class> result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
DCHECK(result != nullptr);
- DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus();
+ DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << result->GetStatus();
return result;
}
@@ -302,25 +306,21 @@ inline bool ArtField::IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_) {
inline ObjPtr<mirror::Class> ArtField::LookupResolvedType() {
ScopedAssertNoThreadSuspension ants(__FUNCTION__);
- const uint32_t field_index = GetDexFieldIndex();
- ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
- if (UNLIKELY(declaring_class->IsProxyClass())) {
+ if (UNLIKELY(IsProxyField())) {
return ProxyFindSystemClass(GetTypeDescriptor());
}
ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->LookupResolvedType(
- declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class);
+ GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this);
DCHECK(!Thread::Current()->IsExceptionPending());
return type;
}
inline ObjPtr<mirror::Class> ArtField::ResolveType() {
- const uint32_t field_index = GetDexFieldIndex();
- ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
- if (UNLIKELY(declaring_class->IsProxyClass())) {
+ if (UNLIKELY(IsProxyField())) {
return ProxyFindSystemClass(GetTypeDescriptor());
}
ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(
- declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class);
+ GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this);
DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
return type;
}
@@ -329,24 +329,21 @@ inline size_t ArtField::FieldSize() REQUIRES_SHARED(Locks::mutator_lock_) {
return Primitive::ComponentSize(GetTypeAsPrimitiveType());
}
+template <ReadBarrierOption kReadBarrierOption>
inline ObjPtr<mirror::DexCache> ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetDeclaringClass()->GetDexCache();
+ ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
+ return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
}
inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetDexCache()->GetDexFile();
+ return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
}
-inline ObjPtr<mirror::String> ArtField::GetStringName(Thread* self, bool resolve) {
- auto dex_field_index = GetDexFieldIndex();
+inline ObjPtr<mirror::String> ArtField::ResolveNameString() {
+ uint32_t dex_field_index = GetDexFieldIndex();
CHECK_NE(dex_field_index, dex::kDexNoIndex);
- ObjPtr<mirror::DexCache> dex_cache = GetDexCache();
- const DexFile::FieldId& field_id = dex_cache->GetDexFile()->GetFieldId(dex_field_index);
- ObjPtr<mirror::String> name = dex_cache->GetResolvedString(field_id.name_idx_);
- if (resolve && name == nullptr) {
- name = ResolveGetStringName(self, field_id.name_idx_, dex_cache);
- }
- return name;
+ const DexFile::FieldId& field_id = GetDexFile()->GetFieldId(dex_field_index);
+ return Runtime::Current()->GetClassLinker()->ResolveString(field_id.name_idx_, this);
}
template <typename Visitor>
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index b867621f02..6cbd9e4cfc 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -52,13 +52,6 @@ ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(const char* descriptor) {
return klass;
}
-ObjPtr<mirror::String> ArtField::ResolveGetStringName(Thread* self,
- dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache) {
- StackHandleScope<1> hs(self);
- return Runtime::Current()->GetClassLinker()->ResolveString(string_idx, hs.NewHandle(dex_cache));
-}
-
std::string ArtField::PrettyField(ArtField* f, bool with_type) {
if (f == nullptr) {
return "null";
diff --git a/runtime/art_field.h b/runtime/art_field.h
index f39af3900c..123595c6fe 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -201,8 +201,7 @@ class ArtField FINAL {
const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_);
// Resolves / returns the name from the dex cache.
- ObjPtr<mirror::String> GetStringName(Thread* self, bool resolve)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -215,6 +214,7 @@ class ArtField FINAL {
size_t FieldSize() REQUIRES_SHARED(Locks::mutator_lock_);
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ObjPtr<mirror::DexCache> GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_);
const DexFile* GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -236,12 +236,10 @@ class ArtField FINAL {
REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ bool IsProxyField() REQUIRES_SHARED(Locks::mutator_lock_);
+
ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<mirror::String> ResolveGetStringName(Thread* self,
- dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache)
- REQUIRES_SHARED(Locks::mutator_lock_);
void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
void GetOffsetDCheck() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index c1fac364bb..18595cf17a 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -245,6 +245,12 @@ inline const char* ArtMethod::GetName() {
}
}
+inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
+ DCHECK(!IsProxyMethod());
+ const DexFile::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
+ return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
+}
+
inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
return GetDexFile()->GetCodeItem(GetCodeItemOffset());
}
@@ -324,7 +330,7 @@ inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
template <ReadBarrierOption kReadBarrierOption>
inline mirror::DexCache* ArtMethod::GetDexCache() {
if (LIKELY(!IsObsolete<kReadBarrierOption>())) {
- mirror::Class* klass = GetDeclaringClass<kReadBarrierOption>();
+ ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
} else {
DCHECK(!IsProxyMethod());
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 608e33cf65..45bf66446a 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -24,7 +24,9 @@
#include "art_method-inl.h"
#include "base/stringpiece.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -47,7 +49,6 @@
#include "runtime_callbacks.h"
#include "scoped_thread_state_change-inl.h"
#include "vdex_file.h"
-#include "well_known_classes.h"
namespace art {
@@ -68,7 +69,7 @@ ArtMethod* ArtMethod::GetCanonicalMethod(PointerSize pointer_size) {
if (LIKELY(!IsDefault())) {
return this;
} else {
- mirror::Class* declaring_class = GetDeclaringClass();
+ ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
DCHECK(declaring_class->IsInterface());
ArtMethod* ret = declaring_class->FindInterfaceMethod(declaring_class->GetDexCache(),
GetDexMethodIndex(),
@@ -142,16 +143,6 @@ uint16_t ArtMethod::FindObsoleteDexClassDefIndex() {
return dex_file->GetIndexForClassDef(*class_def);
}
-ObjPtr<mirror::String> ArtMethod::GetNameAsString(Thread* self) {
- CHECK(!IsProxyMethod());
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache()));
- auto* dex_file = dex_cache->GetDexFile();
- uint32_t dex_method_idx = GetDexMethodIndex();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
- return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, dex_cache);
-}
-
void ArtMethod::ThrowInvocationTimeError() {
DCHECK(!IsInvokable());
// NOTE: IsDefaultConflicting must be first since the actual method might or might not be abstract
@@ -213,8 +204,8 @@ ArtMethod* ArtMethod::FindOverriddenMethod(PointerSize pointer_size) {
if (IsStatic()) {
return nullptr;
}
- mirror::Class* declaring_class = GetDeclaringClass();
- mirror::Class* super_class = declaring_class->GetSuperClass();
+ ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
+ ObjPtr<mirror::Class> super_class = declaring_class->GetSuperClass();
uint16_t method_index = GetMethodIndex();
ArtMethod* result = nullptr;
// Did this method override a super class method? If so load the result from the super class'
@@ -229,7 +220,7 @@ ArtMethod* ArtMethod::FindOverriddenMethod(PointerSize pointer_size) {
} else {
mirror::IfTable* iftable = GetDeclaringClass()->GetIfTable();
for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) {
- mirror::Class* interface = iftable->GetInterface(i);
+ ObjPtr<mirror::Class> interface = iftable->GetInterface(i);
for (ArtMethod& interface_method : interface->GetVirtualMethods(pointer_size)) {
if (HasSameNameAndSignature(interface_method.GetInterfaceMethodIfProxy(pointer_size))) {
result = &interface_method;
@@ -424,36 +415,24 @@ bool ArtMethod::IsPolymorphicSignature() {
if (!IsNative() || !IsVarargs()) {
return false;
}
- mirror::Class* cls = GetDeclaringClass();
- return (cls == WellKnownClasses::ToClass(WellKnownClasses::java_lang_invoke_MethodHandle) ||
- cls == WellKnownClasses::ToClass(WellKnownClasses::java_lang_invoke_VarHandle));
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
+ ObjPtr<mirror::Class> cls = GetDeclaringClass();
+ return (cls == GetClassRoot<mirror::MethodHandle>(class_roots) ||
+ cls == GetClassRoot<mirror::VarHandle>(class_roots));
}
static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
uint16_t class_def_idx,
uint32_t method_idx) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- CHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
- // Process methods
- size_t class_def_method_index = 0;
- while (it.HasNextDirectMethod()) {
- if (it.GetMemberIndex() == method_idx) {
- return class_def_method_index;
- }
- class_def_method_index++;
- it.Next();
- }
- while (it.HasNextVirtualMethod()) {
- if (it.GetMemberIndex() == method_idx) {
+ ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_idx));
+ uint32_t class_def_method_index = 0u;
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ if (method.GetIndex() == method_idx) {
return class_def_method_index;
}
class_def_method_index++;
- it.Next();
}
- DCHECK(!it.HasNext());
LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
UNREACHABLE();
}
@@ -510,7 +489,7 @@ static const OatFile::OatMethod FindOatMethodFor(ArtMethod* method,
}
// Although we overwrite the trampoline of non-static methods, we may get here via the resolution
// method for direct methods (or virtual methods made direct).
- mirror::Class* declaring_class = method->GetDeclaringClass();
+ ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
size_t oat_method_index;
if (method->IsStatic() || method->IsDirect()) {
// Simple case where the oat method index was stashed at load time.
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 012d706756..09debb0c50 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -589,7 +589,7 @@ class ArtMethod FINAL {
ALWAYS_INLINE const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_);
- ObjPtr<mirror::String> GetNameAsString(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveNameString() REQUIRES_SHARED(Locks::mutator_lock_);
const DexFile::CodeItem* GetCodeItem() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index f8b977eea7..0ff55ae25b 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -31,6 +31,7 @@
#include "base/time_utils.h"
#include "class_linker-inl.h"
#include "class_linker.h"
+#include "class_root.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "gc/space/space.h"
@@ -638,8 +639,11 @@ class ScopedCheck {
AbortF("expected non-null method");
return false;
}
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
ObjPtr<mirror::Class> c = method->GetClass();
- if (mirror::Method::StaticClass() != c && mirror::Constructor::StaticClass() != c) {
+ if (c != GetClassRoot<mirror::Method>(class_roots) &&
+ c != GetClassRoot<mirror::Constructor>(class_roots)) {
AbortF("expected java.lang.reflect.Method or "
"java.lang.reflect.Constructor but got object of type %s: %p",
method->PrettyTypeOf().c_str(), jmethod);
@@ -669,7 +673,7 @@ class ScopedCheck {
return false;
}
ObjPtr<mirror::Class> c = field->GetClass();
- if (mirror::Field::StaticClass() != c) {
+ if (GetClassRoot<mirror::Field>() != c) {
AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
field->PrettyTypeOf().c_str(), jfield);
return false;
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 6917899bff..acdb235f8c 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -75,8 +75,7 @@ class CheckReferenceMapVisitor : public StackVisitor {
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
CHECK_LT(reg, accessor.RegistersSize());
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
- reg, number_of_dex_registers, code_info);
+ DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(reg);
switch (location.GetKind()) {
case DexRegisterLocation::Kind::kNone:
// Not set, should not be a reference.
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index ae06f8f9bc..2536b23416 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -17,7 +17,10 @@
#ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
#define ART_RUNTIME_CLASS_LINKER_INL_H_
-#include "art_field.h"
+#include <atomic>
+
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "class_linker.h"
#include "gc/heap-inl.h"
#include "gc_root-inl.h"
@@ -29,25 +32,22 @@
#include "obj_ptr-inl.h"
#include "scoped_thread_state_change-inl.h"
-#include <atomic>
-
namespace art {
-inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
- ObjPtr<mirror::Class>* element_class) {
+inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
+ ObjPtr<mirror::Class> element_class) {
for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
// Read the cached array class once to avoid races with other threads setting it.
ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
- if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
- return array_class.Ptr();
+ if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+ return array_class;
}
}
std::string descriptor = "[";
std::string temp;
- descriptor += (*element_class)->GetDescriptor(&temp);
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
- HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
+ descriptor += element_class->GetDescriptor(&temp);
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
if (array_class != nullptr) {
// Benign races in storing array class and incrementing index.
@@ -58,7 +58,55 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
// We should have a NoClassDefFoundError.
self->AssertPendingException();
}
- return array_class.Ptr();
+ return array_class;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ ArtField* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::String> resolved =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, referrer->GetDexCache());
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ ArtMethod* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::String> resolved =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, referrer->GetDexCache());
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoResolveString(string_idx, dex_cache);
+ }
+ return resolved;
+}
+
+inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
+ ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
+ if (resolved == nullptr) {
+ resolved = DoLookupString(string_idx, dex_cache);
+ }
+ return resolved;
}
inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
@@ -68,38 +116,41 @@ inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
Thread::Current()->PoisonObjectPointers();
}
- if (kIsDebugBuild) {
- Thread::Current()->AssertNoPendingException();
- }
+ DCHECK(!Thread::Current()->IsExceptionPending());
// We do not need the read barrier for getting the DexCache for the initial resolved type
// lookup as both from-space and to-space copies point to the same native resolved types array.
ObjPtr<mirror::Class> resolved_type =
referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (resolved_type == nullptr) {
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
- resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader);
+ resolved_type = DoResolveType(type_idx, referrer);
}
return resolved_type;
}
inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
- ArtMethod* referrer) {
+ ArtField* referrer) {
Thread::PoisonObjectPointersIfDebug();
- if (kIsDebugBuild) {
- Thread::Current()->AssertNoPendingException();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::Class> resolved_type =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
+ if (UNLIKELY(resolved_type == nullptr)) {
+ resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
}
+ return resolved_type;
+}
+
+inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
+ ArtMethod* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
// We do not need the read barrier for getting the DexCache for the initial resolved type
// lookup as both from-space and to-space copies point to the same native resolved types array.
ObjPtr<mirror::Class> resolved_type =
referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (UNLIKELY(resolved_type == nullptr)) {
- StackHandleScope<2> hs(Thread::Current());
- ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
- resolved_type = DoResolveType(type_idx, dex_cache, class_loader);
+ resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
}
return resolved_type;
}
@@ -123,7 +174,19 @@ inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type
ObjPtr<mirror::Class> type =
referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (type == nullptr) {
- type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+ type = DoLookupResolvedType(type_idx, referrer);
+ }
+ return type;
+}
+
+inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
+ ArtField* referrer) {
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::Class> type =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
+ if (type == nullptr) {
+ type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
}
return type;
}
@@ -135,7 +198,7 @@ inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type
ObjPtr<mirror::Class> type =
referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (type == nullptr) {
- type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+ type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
}
return type;
}
@@ -365,14 +428,6 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
return resolved_field;
}
-inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) {
- DCHECK(!class_roots_.IsNull());
- mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
- ObjPtr<mirror::Class> klass = class_roots->Get(class_root);
- DCHECK(klass != nullptr);
- return klass.Ptr();
-}
-
template <class Visitor>
inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
Thread* const self = Thread::Current();
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b88aa5e07a..fd10f3b5e6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -51,10 +51,12 @@
#include "cha.h"
#include "class_linker-inl.h"
#include "class_loader_utils.h"
+#include "class_root.h"
#include "class_table-inl.h"
#include "compiler_callbacks.h"
#include "debug_print.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -431,10 +433,10 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
heap->IncrementDisableMovingGC(self);
StackHandleScope<64> hs(self); // 64 is picked arbitrarily.
auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
- Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
- heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
+ Handle<mirror::Class> java_lang_Class(hs.NewHandle(ObjPtr<mirror::Class>::DownCast(MakeObjPtr(
+ heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor())))));
CHECK(java_lang_Class != nullptr);
- mirror::Class::SetClassClass(java_lang_Class.Get());
+ java_lang_Class->SetClassFlags(mirror::kClassFlagClass);
java_lang_Class->SetClass(java_lang_Class.Get());
if (kUseBakerReadBarrier) {
java_lang_Class->AssertReadBarrierState();
@@ -483,86 +485,66 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_))));
object_array_class->SetComponentType(java_lang_Object.Get());
- // Setup the char (primitive) class to be used for char[].
- Handle<mirror::Class> char_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(),
- mirror::Class::PrimitiveClassSize(image_pointer_size_))));
- // The primitive char class won't be initialized by
- // InitializePrimitiveClass until line 459, but strings (and
- // internal char arrays) will be allocated before that and the
- // component size, which is computed from the primitive type, needs
- // to be set here.
- char_class->SetPrimitiveType(Primitive::kPrimChar);
-
- // Setup the char[] class to be used for String.
- Handle<mirror::Class> char_array_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
- char_array_class->SetComponentType(char_class.Get());
- mirror::CharArray::SetArrayClass(char_array_class.Get());
-
// Setup String.
Handle<mirror::Class> java_lang_String(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_))));
java_lang_String->SetStringClass();
- mirror::String::SetClass(java_lang_String.Get());
mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self);
// Setup java.lang.ref.Reference.
Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize(image_pointer_size_))));
- mirror::Reference::SetClass(java_lang_ref_Reference.Get());
java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize());
mirror::Class::SetStatus(java_lang_ref_Reference, ClassStatus::kResolved, self);
// Create storage for root classes, save away our work so far (requires descriptors).
class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
- mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(),
- kClassRootsMax));
+ mirror::ObjectArray<mirror::Class>::Alloc(self,
+ object_array_class.Get(),
+ static_cast<int32_t>(ClassRoot::kMax)));
CHECK(!class_roots_.IsNull());
- SetClassRoot(kJavaLangClass, java_lang_Class.Get());
- SetClassRoot(kJavaLangObject, java_lang_Object.Get());
- SetClassRoot(kClassArrayClass, class_array_class.Get());
- SetClassRoot(kObjectArrayClass, object_array_class.Get());
- SetClassRoot(kCharArrayClass, char_array_class.Get());
- SetClassRoot(kJavaLangString, java_lang_String.Get());
- SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference.Get());
+ SetClassRoot(ClassRoot::kJavaLangClass, java_lang_Class.Get());
+ SetClassRoot(ClassRoot::kJavaLangObject, java_lang_Object.Get());
+ SetClassRoot(ClassRoot::kClassArrayClass, class_array_class.Get());
+ SetClassRoot(ClassRoot::kObjectArrayClass, object_array_class.Get());
+ SetClassRoot(ClassRoot::kJavaLangString, java_lang_String.Get());
+ SetClassRoot(ClassRoot::kJavaLangRefReference, java_lang_ref_Reference.Get());
// Fill in the empty iftable. Needs to be done after the kObjectArrayClass root is set.
java_lang_Object->SetIfTable(AllocIfTable(self, 0));
// Setup the primitive type classes.
- SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
- SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte));
- SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort));
- SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt));
- SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong));
- SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat));
- SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble));
- SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid));
+ SetClassRoot(ClassRoot::kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
+ SetClassRoot(ClassRoot::kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte));
+ SetClassRoot(ClassRoot::kPrimitiveChar, CreatePrimitiveClass(self, Primitive::kPrimChar));
+ SetClassRoot(ClassRoot::kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort));
+ SetClassRoot(ClassRoot::kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt));
+ SetClassRoot(ClassRoot::kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong));
+ SetClassRoot(ClassRoot::kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat));
+ SetClassRoot(ClassRoot::kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble));
+ SetClassRoot(ClassRoot::kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid));
// Create array interface entries to populate once we can load system classes.
array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2));
- // Create int array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create int array type for native pointer arrays (for example vtables) on 32-bit archs.
Handle<mirror::Class> int_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
- int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
- mirror::IntArray::SetArrayClass(int_array_class.Get());
- SetClassRoot(kIntArrayClass, int_array_class.Get());
+ int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this));
+ SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get());
- // Create long array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create long array type for native pointer arrays (for example vtables) on 64-bit archs.
Handle<mirror::Class> long_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
- long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong));
- mirror::LongArray::SetArrayClass(long_array_class.Get());
- SetClassRoot(kLongArrayClass, long_array_class.Get());
+ long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this));
+ SetClassRoot(ClassRoot::kLongArrayClass, long_array_class.Get());
// now that these are registered, we can use AllocClass() and AllocObjectArray
// Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache.
Handle<mirror::Class> java_lang_DexCache(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_))));
- SetClassRoot(kJavaLangDexCache, java_lang_DexCache.Get());
+ SetClassRoot(ClassRoot::kJavaLangDexCache, java_lang_DexCache.Get());
java_lang_DexCache->SetDexCacheClass();
java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize());
mirror::Class::SetStatus(java_lang_DexCache, ClassStatus::kResolved, self);
@@ -571,8 +553,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Setup dalvik.system.ClassExt
Handle<mirror::Class> dalvik_system_ClassExt(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::ClassExt::ClassSize(image_pointer_size_))));
- SetClassRoot(kDalvikSystemClassExt, dalvik_system_ClassExt.Get());
- mirror::ClassExt::SetClass(dalvik_system_ClassExt.Get());
+ SetClassRoot(ClassRoot::kDalvikSystemClassExt, dalvik_system_ClassExt.Get());
mirror::Class::SetStatus(dalvik_system_ClassExt, ClassStatus::kResolved, self);
// Set up array classes for string, field, method
@@ -580,7 +561,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
AllocClass(self, java_lang_Class.Get(),
mirror::ObjectArray<mirror::String>::ClassSize(image_pointer_size_))));
object_array_string->SetComponentType(java_lang_String.Get());
- SetClassRoot(kJavaLangStringArrayClass, object_array_string.Get());
+ SetClassRoot(ClassRoot::kJavaLangStringArrayClass, object_array_string.Get());
LinearAlloc* linear_alloc = runtime->GetLinearAlloc();
// Create runtime resolution and imt conflict methods.
@@ -606,10 +587,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// now we can use FindSystemClass
- // run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar);
- SetClassRoot(kPrimitiveChar, char_class.Get()); // needs descriptor
-
// Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
// we do not need friend classes or a publicly exposed setter.
quick_generic_jni_trampoline_ = GetQuickGenericJniStub();
@@ -634,25 +611,20 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
CHECK_EQ(dalvik_system_ClassExt->GetObjectSize(), mirror::ClassExt::InstanceSize());
// Setup the primitive array type classes - can't be done until Object has a vtable.
- SetClassRoot(kBooleanArrayClass, FindSystemClass(self, "[Z"));
- mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
+ SetClassRoot(ClassRoot::kBooleanArrayClass, FindSystemClass(self, "[Z"));
- SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B"));
- mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
+ SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B"));
- CheckSystemClass(self, char_array_class, "[C");
+ SetClassRoot(ClassRoot::kCharArrayClass, FindSystemClass(self, "[C"));
- SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S"));
- mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+ SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S"));
CheckSystemClass(self, int_array_class, "[I");
CheckSystemClass(self, long_array_class, "[J");
- SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F"));
- mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
+ SetClassRoot(ClassRoot::kFloatArrayClass, FindSystemClass(self, "[F"));
- SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D"));
- mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
+ SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D"));
// Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it
// in class_table_.
@@ -683,103 +655,89 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::Class::GetDirectInterface(self, object_array_class.Get(), 1));
CHECK_EQ(object_array_string.Get(),
- FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass)));
+ FindSystemClass(self, GetClassRootDescriptor(ClassRoot::kJavaLangStringArrayClass)));
// End of special init trickery, all subsequent classes may be loaded via FindSystemClass.
// Create java.lang.reflect.Proxy root.
- SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
+ SetClassRoot(ClassRoot::kJavaLangReflectProxy,
+ FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
// Create java.lang.reflect.Field.class root.
- auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+ ObjPtr<mirror::Class> class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectField, class_root);
- mirror::Field::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectField, class_root);
// Create java.lang.reflect.Field array root.
class_root = FindSystemClass(self, "[Ljava/lang/reflect/Field;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectFieldArrayClass, class_root);
- mirror::Field::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectFieldArrayClass, class_root);
// Create java.lang.reflect.Constructor.class root and array root.
class_root = FindSystemClass(self, "Ljava/lang/reflect/Constructor;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectConstructor, class_root);
- mirror::Constructor::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectConstructor, class_root);
class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root);
- mirror::Constructor::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectConstructorArrayClass, class_root);
// Create java.lang.reflect.Method.class root and array root.
class_root = FindSystemClass(self, "Ljava/lang/reflect/Method;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectMethod, class_root);
- mirror::Method::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectMethod, class_root);
class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectMethodArrayClass, class_root);
- mirror::Method::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectMethodArrayClass, class_root);
// Create java.lang.invoke.CallSite.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/CallSite;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeCallSite, class_root);
- mirror::CallSite::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeCallSite, class_root);
// Create java.lang.invoke.MethodType.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodType;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeMethodType, class_root);
- mirror::MethodType::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodType, class_root);
// Create java.lang.invoke.MethodHandleImpl.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandleImpl;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root);
- mirror::MethodHandleImpl::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandle, class_root->GetSuperClass());
// Create java.lang.invoke.MethodHandles.Lookup.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandles$Lookup;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeMethodHandlesLookup, class_root);
- mirror::MethodHandlesLookup::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, class_root);
// Create java.lang.invoke.VarHandle.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/VarHandle;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeVarHandle, class_root);
- mirror::VarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, class_root);
// Create java.lang.invoke.FieldVarHandle.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/FieldVarHandle;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeFieldVarHandle, class_root);
- mirror::FieldVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, class_root);
// Create java.lang.invoke.ArrayElementVarHandle.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/ArrayElementVarHandle;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeArrayElementVarHandle, class_root);
- mirror::ArrayElementVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, class_root);
// Create java.lang.invoke.ByteArrayViewVarHandle.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteArrayViewVarHandle;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeByteArrayViewVarHandle, class_root);
- mirror::ByteArrayViewVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, class_root);
// Create java.lang.invoke.ByteBufferViewVarHandle.class root
class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteBufferViewVarHandle;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangInvokeByteBufferViewVarHandle, class_root);
- mirror::ByteBufferViewVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, class_root);
class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
CHECK(class_root != nullptr);
- SetClassRoot(kDalvikSystemEmulatedStackFrame, class_root);
- mirror::EmulatedStackFrame::SetClass(class_root);
+ SetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, class_root);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
@@ -805,18 +763,17 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;");
class_root->SetClassLoaderClass();
CHECK_EQ(class_root->GetObjectSize(), mirror::ClassLoader::InstanceSize());
- SetClassRoot(kJavaLangClassLoader, class_root);
+ SetClassRoot(ClassRoot::kJavaLangClassLoader, class_root);
// Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
// java.lang.StackTraceElement as a convenience.
- SetClassRoot(kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;"));
- mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
- SetClassRoot(kJavaLangClassNotFoundException,
+ SetClassRoot(ClassRoot::kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;"));
+ SetClassRoot(ClassRoot::kJavaLangClassNotFoundException,
FindSystemClass(self, "Ljava/lang/ClassNotFoundException;"));
- SetClassRoot(kJavaLangStackTraceElement, FindSystemClass(self, "Ljava/lang/StackTraceElement;"));
- SetClassRoot(kJavaLangStackTraceElementArrayClass,
+ SetClassRoot(ClassRoot::kJavaLangStackTraceElement,
+ FindSystemClass(self, "Ljava/lang/StackTraceElement;"));
+ SetClassRoot(ClassRoot::kJavaLangStackTraceElementArrayClass,
FindSystemClass(self, "[Ljava/lang/StackTraceElement;"));
- mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
// Create conflict tables that depend on the class linker.
runtime->FixupConflictTables();
@@ -834,8 +791,7 @@ static void CreateStringInitBindings(Thread* self, ClassLinker* class_linker)
ObjPtr<mirror::Class> string_factory_class =
class_linker->FindSystemClass(self, "Ljava/lang/StringFactory;");
CHECK(string_factory_class != nullptr);
- ObjPtr<mirror::Class> string_class =
- class_linker->GetClassRoot(ClassLinker::ClassRoot::kJavaLangString);
+ ObjPtr<mirror::Class> string_class = GetClassRoot<mirror::String>(class_linker);
WellKnownClasses::InitStringInit(string_class, string_factory_class);
// Update the primordial thread.
self->InitStringEntryPoints();
@@ -851,7 +807,8 @@ void ClassLinker::FinishInit(Thread* self) {
// as the types of the field can't be resolved prior to the runtime being
// fully initialized
StackHandleScope<2> hs(self);
- Handle<mirror::Class> java_lang_ref_Reference = hs.NewHandle(GetClassRoot(kJavaLangRefReference));
+ Handle<mirror::Class> java_lang_ref_Reference =
+ hs.NewHandle(GetClassRoot<mirror::Reference>(this));
Handle<mirror::Class> java_lang_ref_FinalizerReference =
hs.NewHandle(FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"));
@@ -876,7 +833,7 @@ void ClassLinker::FinishInit(Thread* self) {
CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;");
// ensure all class_roots_ are initialized
- for (size_t i = 0; i < kClassRootsMax; i++) {
+ for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) {
ClassRoot class_root = static_cast<ClassRoot>(i);
ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
CHECK(klass != nullptr);
@@ -896,11 +853,11 @@ void ClassLinker::FinishInit(Thread* self) {
void ClassLinker::RunRootClinits() {
Thread* self = Thread::Current();
- for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
- ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i));
+ for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); ++i) {
+ ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i), this);
if (!c->IsArrayClass() && !c->IsPrimitive()) {
StackHandleScope<1> hs(self);
- Handle<mirror::Class> h_class(hs.NewHandle(GetClassRoot(ClassRoot(i))));
+ Handle<mirror::Class> h_class(hs.NewHandle(c));
EnsureInitialized(self, h_class, true, true);
self->AssertNoPendingException();
}
@@ -1032,15 +989,12 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
}
class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
- down_cast<mirror::ObjectArray<mirror::Class>*>(
- spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)));
- mirror::Class::SetClassClass(class_roots_.Read()->Get(kJavaLangClass));
+ ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(MakeObjPtr(
+ spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots))));
+ DCHECK_EQ(GetClassRoot(ClassRoot::kJavaLangClass, this)->GetClassFlags(),
+ mirror::kClassFlagClass);
- // Special case of setting up the String class early so that we can test arbitrary objects
- // as being Strings or not
- mirror::String::SetClass(GetClassRoot(kJavaLangString));
-
- ObjPtr<mirror::Class> java_lang_Object = GetClassRoot(kJavaLangObject);
+ ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this);
java_lang_Object->SetObjectSize(sizeof(mirror::Object));
// Allocate in non-movable so that it's possible to check if a JNI weak global ref has been
// cleared without triggering the read barrier and unintentionally mark the sentinel alive.
@@ -1048,37 +1002,9 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
self, java_lang_Object, java_lang_Object->GetObjectSize(), VoidFunctor()));
// reinit array_iftable_ from any array class instance, they should be ==
- array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable());
- DCHECK_EQ(array_iftable_.Read(), GetClassRoot(kBooleanArrayClass)->GetIfTable());
- // String class root was set above
- mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
- mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
- mirror::Constructor::SetClass(GetClassRoot(kJavaLangReflectConstructor));
- mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass));
- mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
- mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass));
- mirror::CallSite::SetClass(GetClassRoot(kJavaLangInvokeCallSite));
- mirror::MethodHandleImpl::SetClass(GetClassRoot(kJavaLangInvokeMethodHandleImpl));
- mirror::MethodHandlesLookup::SetClass(GetClassRoot(kJavaLangInvokeMethodHandlesLookup));
- mirror::MethodType::SetClass(GetClassRoot(kJavaLangInvokeMethodType));
- mirror::VarHandle::SetClass(GetClassRoot(kJavaLangInvokeVarHandle));
- mirror::FieldVarHandle::SetClass(GetClassRoot(kJavaLangInvokeFieldVarHandle));
- mirror::ArrayElementVarHandle::SetClass(GetClassRoot(kJavaLangInvokeArrayElementVarHandle));
- mirror::ByteArrayViewVarHandle::SetClass(GetClassRoot(kJavaLangInvokeByteArrayViewVarHandle));
- mirror::ByteBufferViewVarHandle::SetClass(GetClassRoot(kJavaLangInvokeByteBufferViewVarHandle));
- mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
- mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
- mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
- mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
- mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
- mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
- mirror::IntArray::SetArrayClass(GetClassRoot(kIntArrayClass));
- mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
- mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
- mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
- mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
- mirror::EmulatedStackFrame::SetClass(GetClassRoot(kDalvikSystemEmulatedStackFrame));
- mirror::ClassExt::SetClass(GetClassRoot(kDalvikSystemClassExt));
+ array_iftable_ =
+ GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable());
+ DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable());
for (gc::space::ImageSpace* image_space : spaces) {
// Boot class loader, use a null handle.
@@ -1169,7 +1095,7 @@ static bool FlattenPathClassLoader(ObjPtr<mirror::ClassLoader> class_loader,
return false; // Stop the visit.
}
if (name != nullptr) {
- out_dex_file_names->push_front(name.Ptr());
+ out_dex_file_names->push_front(name);
}
return true; // Continue with the next Element.
};
@@ -1695,15 +1621,16 @@ bool ClassLinker::AddImageSpace(
MutableHandle<mirror::ClassLoader> image_class_loader(hs.NewHandle(
app_image ? header.GetImageRoot(ImageHeader::kClassLoader)->AsClassLoader() : nullptr));
DCHECK(class_roots != nullptr);
- if (class_roots->GetLength() != static_cast<int32_t>(kClassRootsMax)) {
+ if (class_roots->GetLength() != static_cast<int32_t>(ClassRoot::kMax)) {
*error_msg = StringPrintf("Expected %d class roots but got %d",
class_roots->GetLength(),
- static_cast<int32_t>(kClassRootsMax));
+ static_cast<int32_t>(ClassRoot::kMax));
return false;
}
// Check against existing class roots to make sure they match the ones in the boot image.
- for (size_t i = 0; i < kClassRootsMax; i++) {
- if (class_roots->Get(i) != GetClassRoot(static_cast<ClassRoot>(i))) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> existing_class_roots = GetClassRoots();
+ for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) {
+ if (class_roots->Get(i) != GetClassRoot(static_cast<ClassRoot>(i), existing_class_roots)) {
*error_msg = "App image class roots must have pointer equality with runtime ones.";
return false;
}
@@ -2131,8 +2058,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
// Add 100 in case new classes get loaded when we are filling in the object array.
class_table_size = NumZygoteClasses() + NumNonZygoteClasses() + 100;
}
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
classes.Assign(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, class_table_size));
CHECK(classes != nullptr); // OOME.
@@ -2155,35 +2081,6 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
}
ClassLinker::~ClassLinker() {
- mirror::Class::ResetClass();
- mirror::Constructor::ResetClass();
- mirror::Field::ResetClass();
- mirror::Method::ResetClass();
- mirror::Reference::ResetClass();
- mirror::StackTraceElement::ResetClass();
- mirror::String::ResetClass();
- mirror::Throwable::ResetClass();
- mirror::BooleanArray::ResetArrayClass();
- mirror::ByteArray::ResetArrayClass();
- mirror::CharArray::ResetArrayClass();
- mirror::Constructor::ResetArrayClass();
- mirror::DoubleArray::ResetArrayClass();
- mirror::Field::ResetArrayClass();
- mirror::FloatArray::ResetArrayClass();
- mirror::Method::ResetArrayClass();
- mirror::IntArray::ResetArrayClass();
- mirror::LongArray::ResetArrayClass();
- mirror::ShortArray::ResetArrayClass();
- mirror::CallSite::ResetClass();
- mirror::MethodType::ResetClass();
- mirror::MethodHandleImpl::ResetClass();
- mirror::MethodHandlesLookup::ResetClass();
- mirror::VarHandle::ResetClass();
- mirror::FieldVarHandle::ResetClass();
- mirror::ArrayElementVarHandle::ResetClass();
- mirror::ByteArrayViewVarHandle::ResetClass();
- mirror::ByteBufferViewVarHandle::ResetClass();
- mirror::EmulatedStackFrame::ResetClass();
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
// CHA unloading analysis is not needed. No negative consequences are expected because
@@ -2218,20 +2115,20 @@ void ClassLinker::DeleteClassLoader(Thread* self, const ClassLoaderData& data, b
delete data.class_table;
}
-mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
- return down_cast<mirror::PointerArray*>(
+ObjPtr<mirror::PointerArray> ClassLinker::AllocPointerArray(Thread* self, size_t length) {
+ return ObjPtr<mirror::PointerArray>::DownCast(
image_pointer_size_ == PointerSize::k64
- ? static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length))
- : static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length)));
+ ? ObjPtr<mirror::Array>(mirror::LongArray::Alloc(self, length))
+ : ObjPtr<mirror::Array>(mirror::IntArray::Alloc(self, length)));
}
-mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_location,
- Thread* self,
- const DexFile& dex_file) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+ Thread* self,
+ const DexFile& dex_file) {
StackHandleScope<1> hs(self);
DCHECK(out_location != nullptr);
auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast(
- GetClassRoot(kJavaLangDexCache)->AllocObject(self))));
+ GetClassRoot<mirror::DexCache>(this)->AllocObject(self))));
if (dex_cache == nullptr) {
self->AssertPendingOOMException();
return nullptr;
@@ -2245,9 +2142,9 @@ mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_locatio
return dex_cache.Get();
}
-mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
- const DexFile& dex_file,
- LinearAlloc* linear_alloc) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self,
+ const DexFile& dex_file,
+ LinearAlloc* linear_alloc) {
ObjPtr<mirror::String> location = nullptr;
ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(&location, self, dex_file);
if (dex_cache != nullptr) {
@@ -2260,12 +2157,12 @@ mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
linear_alloc,
image_pointer_size_);
}
- return dex_cache.Ptr();
+ return dex_cache;
}
-mirror::Class* ClassLinker::AllocClass(Thread* self,
- ObjPtr<mirror::Class> java_lang_Class,
- uint32_t class_size) {
+ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self,
+ ObjPtr<mirror::Class> java_lang_Class,
+ uint32_t class_size) {
DCHECK_GE(class_size, sizeof(mirror::Class));
gc::Heap* heap = Runtime::Current()->GetHeap();
mirror::Class::InitializeClassVisitor visitor(class_size);
@@ -2279,20 +2176,20 @@ mirror::Class* ClassLinker::AllocClass(Thread* self,
return k->AsClass();
}
-mirror::Class* ClassLinker::AllocClass(Thread* self, uint32_t class_size) {
- return AllocClass(self, GetClassRoot(kJavaLangClass), class_size);
+ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, uint32_t class_size) {
+ return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size);
}
-mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(
+ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTraceElementArray(
Thread* self,
size_t length) {
return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(
- self, GetClassRoot(kJavaLangStackTraceElementArrayClass), length);
+ self, GetClassRoot<mirror::ObjectArray<mirror::StackTraceElement>>(this), length);
}
-mirror::Class* ClassLinker::EnsureResolved(Thread* self,
- const char* descriptor,
- ObjPtr<mirror::Class> klass) {
+ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::Class> klass) {
DCHECK(klass != nullptr);
if (kIsDebugBuild) {
StackHandleScope<1> hs(self);
@@ -2364,7 +2261,7 @@ mirror::Class* ClassLinker::EnsureResolved(Thread* self,
// Return the loaded class. No exceptions should be pending.
CHECK(klass->IsResolved()) << klass->PrettyClass();
self->AssertNoPendingException();
- return klass.Ptr();
+ return klass;
}
typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -2386,7 +2283,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
- ObjPtr<mirror::Class>* result) {
+ /*out*/ ObjPtr<mirror::Class>* result) {
// Termination case: boot class loader.
if (IsBootClassLoader(soa, class_loader.Get())) {
*result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
@@ -2500,9 +2397,9 @@ ObjPtr<mirror::Class> ClassLinker::FindClassInBaseDexClassLoaderClassPath(
return ret;
}
-mirror::Class* ClassLinker::FindClass(Thread* self,
- const char* descriptor,
- Handle<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self,
+ const char* descriptor,
+ Handle<mirror::ClassLoader> class_loader) {
DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
DCHECK(self != nullptr);
self->AssertNoPendingException();
@@ -2639,7 +2536,7 @@ mirror::Class* ClassLinker::FindClass(Thread* self,
if (old == nullptr) {
old = result_ptr; // For the comparison below, after releasing the lock.
if (descriptor_equals) {
- class_table->InsertWithHash(result_ptr.Ptr(), hash);
+ class_table->InsertWithHash(result_ptr, hash);
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
} // else throw below, after releasing the lock.
}
@@ -2667,16 +2564,16 @@ mirror::Class* ClassLinker::FindClass(Thread* self,
DescriptorToDot(descriptor).c_str());
return nullptr;
}
- // success, return mirror::Class*
- return result_ptr.Ptr();
+ // Success.
+ return result_ptr;
}
-mirror::Class* ClassLinker::DefineClass(Thread* self,
- const char* descriptor,
- size_t hash,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def) {
+ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def) {
StackHandleScope<3> hs(self);
auto klass = hs.NewHandle<mirror::Class>(nullptr);
@@ -2684,17 +2581,17 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
if (UNLIKELY(!init_done_)) {
// finish up init of hand crafted class_roots_
if (strcmp(descriptor, "Ljava/lang/Object;") == 0) {
- klass.Assign(GetClassRoot(kJavaLangObject));
+ klass.Assign(GetClassRoot<mirror::Object>(this));
} else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) {
- klass.Assign(GetClassRoot(kJavaLangClass));
+ klass.Assign(GetClassRoot<mirror::Class>(this));
} else if (strcmp(descriptor, "Ljava/lang/String;") == 0) {
- klass.Assign(GetClassRoot(kJavaLangString));
+ klass.Assign(GetClassRoot<mirror::String>(this));
} else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) {
- klass.Assign(GetClassRoot(kJavaLangRefReference));
+ klass.Assign(GetClassRoot<mirror::Reference>(this));
} else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) {
- klass.Assign(GetClassRoot(kJavaLangDexCache));
+ klass.Assign(GetClassRoot<mirror::DexCache>(this));
} else if (strcmp(descriptor, "Ldalvik/system/ClassExt;") == 0) {
- klass.Assign(GetClassRoot(kDalvikSystemClassExt));
+ klass.Assign(GetClassRoot<mirror::ClassExt>(this));
}
}
@@ -2744,7 +2641,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
ObjectLock<mirror::Class> lock(self, klass);
klass->SetClinitThreadId(self->GetTid());
// Make sure we have a valid empty iftable even if there are errors.
- klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
+ klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable());
// Add the newly loaded class to the loaded classes table.
ObjPtr<mirror::Class> existing = InsertClass(descriptor, klass.Get(), hash);
@@ -2834,52 +2731,50 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
size_t num_ref = 0;
size_t num_8 = 0;
size_t num_16 = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- if (class_data != nullptr) {
- // We allow duplicate definitions of the same field in a class_data_item
- // but ignore the repeated indexes here, b/21868015.
- uint32_t last_field_idx = dex::kDexNoIndex;
- for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- // Ordering enforced by DexFileVerifier.
- DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
- if (UNLIKELY(field_idx == last_field_idx)) {
- continue;
- }
- last_field_idx = field_idx;
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- char c = descriptor[0];
- switch (c) {
- case 'L':
- case '[':
- num_ref++;
- break;
- case 'J':
- case 'D':
- num_64++;
- break;
- case 'I':
- case 'F':
- num_32++;
- break;
- case 'S':
- case 'C':
- num_16++;
- break;
- case 'B':
- case 'Z':
- num_8++;
- break;
- default:
- LOG(FATAL) << "Unknown descriptor: " << c;
- UNREACHABLE();
- }
+ ClassAccessor accessor(dex_file, dex_class_def);
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = dex::kDexNoIndex;
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ uint32_t field_idx = field.GetIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+ char c = descriptor[0];
+ switch (c) {
+ case 'L':
+ case '[':
+ num_ref++;
+ break;
+ case 'J':
+ case 'D':
+ num_64++;
+ break;
+ case 'I':
+ case 'F':
+ num_32++;
+ break;
+ case 'S':
+ case 'C':
+ num_16++;
+ break;
+ case 'B':
+ case 'Z':
+ num_8++;
+ break;
+ default:
+ LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
}
}
return mirror::Class::ComputeClassSize(false,
@@ -2977,17 +2872,15 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+ ClassAccessor accessor(dex_file, *dex_class_def);
// There should always be class data if there were direct methods.
- CHECK(class_data != nullptr) << klass->PrettyDescriptor();
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
+ CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
bool has_oat_class;
OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
klass->GetDexClassDefIndex(),
&has_oat_class);
// Link the code of methods skipped by LinkCode.
- for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
+ for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
if (!method->IsStatic()) {
// Only update static methods.
@@ -3084,7 +2977,7 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
CHECK(descriptor != nullptr);
- klass->SetClass(GetClassRoot(kJavaLangClass));
+ klass->SetClass(GetClassRoot<mirror::Class>(this));
uint32_t access_flags = dex_class_def.GetJavaAccessFlags();
CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
klass->SetAccessFlags(access_flags);
@@ -3096,17 +2989,6 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}
-void ClassLinker::LoadClass(Thread* self,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- Handle<mirror::Class> klass) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
- if (class_data == nullptr) {
- return; // no fields or methods - for example a marker interface
- }
- LoadClassMembers(self, dex_file, class_data, klass);
-}
-
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length) {
@@ -3165,10 +3047,15 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas
return allocator;
}
-void ClassLinker::LoadClassMembers(Thread* self,
- const DexFile& dex_file,
- const uint8_t* class_data,
- Handle<mirror::Class> klass) {
+void ClassLinker::LoadClass(Thread* self,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def,
+ Handle<mirror::Class> klass) {
+ ClassAccessor accessor(dex_file, dex_class_def);
+ if (!accessor.HasClassData()) {
+ return;
+ }
+ Runtime* const runtime = Runtime::Current();
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3177,45 +3064,79 @@ void ClassLinker::LoadClassMembers(Thread* self,
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
- ClassDataItemIterator it(dex_file, class_data);
LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
allocator,
- it.NumStaticFields());
- size_t num_sfields = 0;
- uint32_t last_field_idx = 0u;
- for (; it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_sfields, it.NumStaticFields());
- LoadField(it, klass, &sfields->At(num_sfields));
- ++num_sfields;
- last_field_idx = field_idx;
- }
- }
-
- // Load instance fields.
+ accessor.NumStaticFields());
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
- it.NumInstanceFields());
+ accessor.NumInstanceFields());
+ size_t num_sfields = 0u;
size_t num_ifields = 0u;
- last_field_idx = 0u;
- for (; it.HasNextInstanceField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_ifields, it.NumInstanceFields());
- LoadField(it, klass, &ifields->At(num_ifields));
- ++num_ifields;
- last_field_idx = field_idx;
- }
- }
+ uint32_t last_static_field_idx = 0u;
+ uint32_t last_instance_field_idx = 0u;
- if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
- UNLIKELY(num_ifields != it.NumInstanceFields())) {
+ // Methods
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+ klass->SetMethodsPtr(
+ AllocArtMethodArray(self, allocator, accessor.NumMethods()),
+ accessor.NumDirectMethods(),
+ accessor.NumVirtualMethods());
+ size_t class_def_method_index = 0;
+ uint32_t last_dex_method_index = dex::kDexNoIndex;
+ size_t last_class_def_method_index = 0;
+
+ // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
+ // methods needs to decode all of the fields.
+ accessor.VisitFieldsAndMethods([&](
+ const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_static_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
+ LoadField(field, klass, &sfields->At(num_sfields));
+ ++num_sfields;
+ last_static_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_instance_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
+ LoadField(field, klass, &ifields->At(num_ifields));
+ ++num_ifields;
+ last_instance_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ uint32_t it_method_index = method.GetIndex();
+ if (last_dex_method_index == it_method_index) {
+ // duplicate case
+ art_method->SetMethodIndex(last_class_def_method_index);
+ } else {
+ art_method->SetMethodIndex(class_def_method_index);
+ last_dex_method_index = it_method_index;
+ last_class_def_method_index = class_def_method_index;
+ }
+ ++class_def_method_index;
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
+ class_def_method_index - accessor.NumDirectMethods(),
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ ++class_def_method_index;
+ });
+
+ if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
- << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
- << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
+ << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
+ << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
+ << ")";
// NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
if (sfields != nullptr) {
sfields->SetSize(num_sfields);
@@ -3229,87 +3150,49 @@ void ClassLinker::LoadClassMembers(Thread* self,
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
- // Load methods.
- bool has_oat_class = false;
- const OatFile::OatClass oat_class =
- (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
- ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
- : OatFile::OatClass::Invalid();
- const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
- it.NumDirectMethods(),
- it.NumVirtualMethods());
- size_t class_def_method_index = 0;
- uint32_t last_dex_method_index = dex::kDexNoIndex;
- size_t last_class_def_method_index = 0;
- // TODO These should really use the iterators.
- for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- uint32_t it_method_index = it.GetMemberIndex();
- if (last_dex_method_index == it_method_index) {
- // duplicate case
- method->SetMethodIndex(last_class_def_method_index);
- } else {
- method->SetMethodIndex(class_def_method_index);
- last_dex_method_index = it_method_index;
- last_class_def_method_index = class_def_method_index;
- }
- class_def_method_index++;
- }
- for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- class_def_method_index++;
- }
- DCHECK(!it.HasNext());
}
// Ensure that the card is marked so that remembered sets pick up native roots.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
self->AllowThreadSuspension();
}
-void ClassLinker::LoadField(const ClassDataItemIterator& it,
+void ClassLinker::LoadField(const ClassAccessor::Field& field,
Handle<mirror::Class> klass,
ArtField* dst) {
- const uint32_t field_idx = it.GetMemberIndex();
+ const uint32_t field_idx = field.GetIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.Get());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetFieldAccessFlags();
+ uint32_t access_flags = field.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
- const ClassDataItemIterator& it,
+ const ClassAccessor::Method& method,
Handle<mirror::Class> klass,
ArtMethod* dst) {
- uint32_t dex_method_idx = it.GetMemberIndex();
+ const uint32_t dex_method_idx = method.GetIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
- dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
+ dst->SetCodeItemOffset(method.GetCodeItemOffset());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetMethodAccessFlags();
+ uint32_t access_flags = method.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -3634,27 +3517,20 @@ ClassLinker::DexCacheData ClassLinker::FindDexCacheDataLocked(const DexFile& dex
return DexCacheData();
}
-mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
- ObjPtr<mirror::Class> klass =
+ObjPtr<mirror::Class> ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
+ ObjPtr<mirror::Class> primitive_class =
AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_));
- if (UNLIKELY(klass == nullptr)) {
+ if (UNLIKELY(primitive_class == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
}
- return InitializePrimitiveClass(klass, type);
-}
-
-mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
- Primitive::Type type) {
- CHECK(primitive_class != nullptr);
// Must hold lock on object when initializing.
- Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(primitive_class));
ObjectLock<mirror::Class> lock(self, h_class);
h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
h_class->SetPrimitiveType(type);
- h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
+ h_class->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable());
mirror::Class::SetStatus(h_class, ClassStatus::kInitialized, self);
const char* descriptor = Primitive::Descriptor(type);
ObjPtr<mirror::Class> existing = InsertClass(descriptor,
@@ -3677,8 +3553,10 @@ mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primi
// array class; that always comes from the base element class.
//
// Returns null with an exception raised on failure.
-mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descriptor, size_t hash,
- Handle<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader) {
// Identify the underlying component type
CHECK_EQ('[', descriptor[0]);
StackHandleScope<2> hs(self);
@@ -3721,7 +3599,7 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
ObjPtr<mirror::Class> new_class =
LookupClass(self, descriptor, hash, component_type->GetClassLoader());
if (new_class != nullptr) {
- return new_class.Ptr();
+ return new_class;
}
}
@@ -3737,17 +3615,15 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
if (UNLIKELY(!init_done_)) {
// Classes that were hand created, ie not by FindSystemClass
if (strcmp(descriptor, "[Ljava/lang/Class;") == 0) {
- new_class.Assign(GetClassRoot(kClassArrayClass));
+ new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Class>>(this));
} else if (strcmp(descriptor, "[Ljava/lang/Object;") == 0) {
- new_class.Assign(GetClassRoot(kObjectArrayClass));
- } else if (strcmp(descriptor, GetClassRootDescriptor(kJavaLangStringArrayClass)) == 0) {
- new_class.Assign(GetClassRoot(kJavaLangStringArrayClass));
- } else if (strcmp(descriptor, "[C") == 0) {
- new_class.Assign(GetClassRoot(kCharArrayClass));
+ new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Object>>(this));
+ } else if (strcmp(descriptor, "[Ljava/lang/String;") == 0) {
+ new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::String>>(this));
} else if (strcmp(descriptor, "[I") == 0) {
- new_class.Assign(GetClassRoot(kIntArrayClass));
+ new_class.Assign(GetClassRoot<mirror::IntArray>(this));
} else if (strcmp(descriptor, "[J") == 0) {
- new_class.Assign(GetClassRoot(kLongArrayClass));
+ new_class.Assign(GetClassRoot<mirror::LongArray>(this));
}
}
if (new_class == nullptr) {
@@ -3760,7 +3636,7 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
}
ObjectLock<mirror::Class> lock(self, new_class); // Must hold lock on object when initializing.
DCHECK(new_class->GetComponentType() != nullptr);
- ObjPtr<mirror::Class> java_lang_Object = GetClassRoot(kJavaLangObject);
+ ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this);
new_class->SetSuperClass(java_lang_Object);
new_class->SetVTable(java_lang_Object->GetVTable());
new_class->SetPrimitiveType(Primitive::kPrimNot);
@@ -3824,29 +3700,30 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
//
// (Yes, this happens.)
- return existing.Ptr();
+ return existing;
}
-mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
+ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassRoots();
switch (type) {
case 'B':
- return GetClassRoot(kPrimitiveByte);
+ return GetClassRoot(ClassRoot::kPrimitiveByte, class_roots);
case 'C':
- return GetClassRoot(kPrimitiveChar);
+ return GetClassRoot(ClassRoot::kPrimitiveChar, class_roots);
case 'D':
- return GetClassRoot(kPrimitiveDouble);
+ return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots);
case 'F':
- return GetClassRoot(kPrimitiveFloat);
+ return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots);
case 'I':
- return GetClassRoot(kPrimitiveInt);
+ return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots);
case 'J':
- return GetClassRoot(kPrimitiveLong);
+ return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots);
case 'S':
- return GetClassRoot(kPrimitiveShort);
+ return GetClassRoot(ClassRoot::kPrimitiveShort, class_roots);
case 'Z':
- return GetClassRoot(kPrimitiveBoolean);
+ return GetClassRoot(ClassRoot::kPrimitiveBoolean, class_roots);
case 'V':
- return GetClassRoot(kPrimitiveVoid);
+ return GetClassRoot(ClassRoot::kPrimitiveVoid, class_roots);
default:
break;
}
@@ -3855,7 +3732,9 @@ mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
return nullptr;
}
-mirror::Class* ClassLinker::InsertClass(const char* descriptor, ObjPtr<mirror::Class> klass, size_t hash) {
+ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor,
+ ObjPtr<mirror::Class> klass,
+ size_t hash) {
if (VLOG_IS_ON(class_linker)) {
ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
std::string source;
@@ -3871,7 +3750,7 @@ mirror::Class* ClassLinker::InsertClass(const char* descriptor, ObjPtr<mirror::C
ClassTable* const class_table = InsertClassTableForClassLoader(class_loader);
ObjPtr<mirror::Class> existing = class_table->Lookup(descriptor, hash);
if (existing != nullptr) {
- return existing.Ptr();
+ return existing;
}
VerifyObject(klass);
class_table->InsertWithHash(klass, hash);
@@ -3910,22 +3789,22 @@ void ClassLinker::UpdateClassMethods(ObjPtr<mirror::Class> klass,
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass);
}
-mirror::Class* ClassLinker::LookupClass(Thread* self,
- const char* descriptor,
- ObjPtr<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::ClassLoader> class_loader) {
return LookupClass(self, descriptor, ComputeModifiedUtf8Hash(descriptor), class_loader);
}
-mirror::Class* ClassLinker::LookupClass(Thread* self,
- const char* descriptor,
- size_t hash,
- ObjPtr<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ ObjPtr<mirror::ClassLoader> class_loader) {
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
ClassTable* const class_table = ClassTableForClassLoader(class_loader);
if (class_table != nullptr) {
ObjPtr<mirror::Class> result = class_table->Lookup(descriptor, hash);
if (result != nullptr) {
- return result.Ptr();
+ return result;
}
}
return nullptr;
@@ -4372,16 +4251,16 @@ void ClassLinker::ResolveMethodExceptionHandlerTypes(ArtMethod* method) {
}
}
-mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
- jstring name,
- jobjectArray interfaces,
- jobject loader,
- jobjectArray methods,
- jobjectArray throws) {
+ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
+ jstring name,
+ jobjectArray interfaces,
+ jobject loader,
+ jobjectArray methods,
+ jobjectArray throws) {
Thread* self = soa.Self();
StackHandleScope<10> hs(self);
MutableHandle<mirror::Class> temp_klass(hs.NewHandle(
- AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
+ AllocClass(self, GetClassRoot<mirror::Class>(this), sizeof(mirror::Class))));
if (temp_klass == nullptr) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
@@ -4394,9 +4273,9 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
temp_klass->SetClassLoader(soa.Decode<mirror::ClassLoader>(loader));
DCHECK_EQ(temp_klass->GetPrimitiveType(), Primitive::kPrimNot);
temp_klass->SetName(soa.Decode<mirror::String>(name));
- temp_klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
+ temp_klass->SetDexCache(GetClassRoot<mirror::Proxy>(this)->GetDexCache());
// Object has an empty iftable, copy it for that reason.
- temp_klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
+ temp_klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable());
mirror::Class::SetStatus(temp_klass, ClassStatus::kIdx, self);
std::string descriptor(GetDescriptorForProxy(temp_klass.Get()));
const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str());
@@ -4434,7 +4313,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
// They have as many virtual methods as the array
auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>>(methods));
- DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
+ DCHECK_EQ(h_methods->GetClass(), GetClassRoot<mirror::ObjectArray<mirror::Method>>())
<< mirror::Class::PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
@@ -4463,7 +4342,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
}
// The super class is java.lang.reflect.Proxy
- temp_klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy));
+ temp_klass->SetSuperClass(GetClassRoot<mirror::Proxy>(this));
// Now effectively in the loaded state.
mirror::Class::SetStatus(temp_klass, ClassStatus::kLoaded, self);
self->AssertNoPendingException();
@@ -4551,11 +4430,12 @@ std::string ClassLinker::GetDescriptorForProxy(ObjPtr<mirror::Class> proxy_class
void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) {
// Create constructor for Proxy that must initialize the method.
- CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 21u);
+ ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>(this);
+ CHECK_EQ(proxy_class->NumDirectMethods(), 21u);
// Find the <init>(InvocationHandler)V method. The exact method offset varies depending
// on which front-end compiler was used to build the libcore DEX files.
- ArtMethod* proxy_constructor = GetClassRoot(kJavaLangReflectProxy)->FindConstructor(
+ ArtMethod* proxy_constructor = proxy_class->FindConstructor(
"(Ljava/lang/reflect/InvocationHandler;)V", image_pointer_size_);
DCHECK(proxy_constructor != nullptr)
<< "Could not find <init> method in java.lang.reflect.Proxy";
@@ -4879,24 +4759,29 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
- ClassDataItemIterator field_it(dex_file, class_data);
+
if (value_it.HasNext()) {
- DCHECK(field_it.HasNextStaticField());
+ ClassAccessor accessor(dex_file, *dex_class_def);
CHECK(can_init_statics);
- for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
- ArtField* field = ResolveField(
- field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ if (!value_it.HasNext()) {
+ break;
+ }
+ ArtField* art_field = ResolveField(field.GetIndex(),
+ dex_cache,
+ class_loader,
+ /* is_static */ true);
if (Runtime::Current()->IsActiveTransaction()) {
- value_it.ReadValueToField<true>(field);
+ value_it.ReadValueToField<true>(art_field);
} else {
- value_it.ReadValueToField<false>(field);
+ value_it.ReadValueToField<false>(art_field);
}
if (self->IsExceptionPending()) {
break;
}
- DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
+ value_it.Next();
}
+ DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}
@@ -5553,7 +5438,8 @@ bool ClassLinker::LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexF
bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) {
CHECK(!klass->IsPrimitive());
ObjPtr<mirror::Class> super = klass->GetSuperClass();
- if (klass.Get() == GetClassRoot(kJavaLangObject)) {
+ ObjPtr<mirror::Class> object_class = GetClassRoot<mirror::Object>(this);
+ if (klass.Get() == object_class) {
if (super != nullptr) {
ThrowClassFormatError(klass.Get(), "java.lang.Object must not have a superclass");
return false;
@@ -5566,7 +5452,7 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) {
return false;
}
// Verify
- if (klass->IsInterface() && super != GetClassRoot(kJavaLangObject)) {
+ if (klass->IsInterface() && super != object_class) {
ThrowClassFormatError(klass.Get(), "Interfaces must have java.lang.Object as superclass");
return false;
}
@@ -5609,7 +5495,7 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) {
klass->SetClassFlags(klass->GetClassFlags() | reference_flags);
}
// Disallow custom direct subclasses of java.lang.ref.Reference.
- if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) {
+ if (init_done_ && super == GetClassRoot<mirror::Reference>(this)) {
ThrowLinkageError(klass.Get(),
"Class %s attempts to subclass java.lang.ref.Reference, which is not allowed",
klass->PrettyDescriptor().c_str());
@@ -5829,8 +5715,8 @@ bool ClassLinker::LinkVirtualMethods(
klass->SetVTable(super_vtable);
return true;
}
- vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
- super_vtable->CopyOf(self, max_count)));
+ vtable = hs.NewHandle(
+ ObjPtr<mirror::PointerArray>::DownCast(super_vtable->CopyOf(self, max_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5966,7 +5852,7 @@ bool ClassLinker::LinkVirtualMethods(
// Shrink vtable if possible
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
- vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
+ vtable.Assign(ObjPtr<mirror::PointerArray>::DownCast(vtable->CopyOf(self, actual_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5974,13 +5860,13 @@ bool ClassLinker::LinkVirtualMethods(
}
klass->SetVTable(vtable.Get());
} else {
- CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject));
+ CHECK_EQ(klass.Get(), GetClassRoot<mirror::Object>(this));
if (!IsUint<16>(num_virtual_methods)) {
ThrowClassFormatError(klass.Get(), "Too many methods: %d",
static_cast<int>(num_virtual_methods));
return false;
}
- auto* vtable = AllocPointerArray(self, num_virtual_methods);
+ ObjPtr<mirror::PointerArray> vtable = AllocPointerArray(self, num_virtual_methods);
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -6224,7 +6110,8 @@ bool ClassLinker::AllocateIfTableMethodArrays(Thread* self,
DCHECK(if_table != nullptr);
DCHECK(if_table->GetMethodArray(i) != nullptr);
// If we are working on a super interface, try extending the existing method array.
- method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self));
+ method_array = ObjPtr<mirror::PointerArray>::DownCast(MakeObjPtr(
+ if_table->GetMethodArray(i)->Clone(self)));
} else {
method_array = AllocPointerArray(self, num_methods);
}
@@ -6488,7 +6375,7 @@ static bool NotSubinterfaceOfAny(
// iftable must be large enough to hold all interfaces without changing its size.
static size_t FillIfTable(ObjPtr<mirror::IfTable> iftable,
size_t super_ifcount,
- std::vector<mirror::Class*> to_process)
+ std::vector<ObjPtr<mirror::Class>> to_process)
REQUIRES(Roles::uninterruptible_)
REQUIRES_SHARED(Locks::mutator_lock_) {
// This is the set of all class's already in the iftable. Used to make checking if a class has
@@ -6628,11 +6515,11 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
size_t new_ifcount;
{
ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
- std::vector<mirror::Class*> to_add;
+ std::vector<ObjPtr<mirror::Class>> to_add;
for (size_t i = 0; i < num_interfaces; i++) {
ObjPtr<mirror::Class> interface = have_interfaces ? interfaces->Get(i) :
mirror::Class::GetDirectInterface(self, klass.Get(), i);
- to_add.push_back(interface.Ptr());
+ to_add.push_back(interface);
}
new_ifcount = FillIfTable(iftable.Get(), super_ifcount, std::move(to_add));
@@ -6643,7 +6530,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
// Shrink iftable in case duplicates were found
if (new_ifcount < ifcount) {
DCHECK_NE(num_interfaces, 0U);
- iftable.Assign(down_cast<mirror::IfTable*>(
+ iftable.Assign(ObjPtr<mirror::IfTable>::DownCast(
iftable->CopyOf(self, new_ifcount * mirror::IfTable::kMax)));
if (UNLIKELY(iftable == nullptr)) {
self->AssertPendingOOMException();
@@ -7157,7 +7044,7 @@ ObjPtr<mirror::PointerArray> ClassLinker::LinkInterfaceMethodsHelper::UpdateVtab
default_conflict_methods_.size();
ObjPtr<mirror::PointerArray> vtable =
- down_cast<mirror::PointerArray*>(old_vtable->CopyOf(self_, new_vtable_count));
+ ObjPtr<mirror::PointerArray>::DownCast(old_vtable->CopyOf(self_, new_vtable_count));
if (UNLIKELY(vtable == nullptr)) {
self_->AssertPendingOOMException();
return nullptr;
@@ -7770,14 +7657,15 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
klass->SetReferenceInstanceOffsets(reference_offsets);
}
-ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
- Handle<mirror::DexCache> dex_cache) {
- DCHECK(dex_cache != nullptr);
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(dex_cache));
+ return DoResolveString(string_idx, h_dex_cache);
+}
+
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache) {
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
@@ -7788,13 +7676,9 @@ ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
return string;
}
-ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache) {
+ObjPtr<mirror::String> ClassLinker::DoLookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
DCHECK(dex_cache != nullptr);
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
@@ -7807,6 +7691,11 @@ ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
}
ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ return DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader) {
const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -7822,7 +7711,7 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
DCHECK(self != nullptr);
const size_t hash = ComputeModifiedUtf8Hash(descriptor);
// Find the class in the loaded classes table.
- type = LookupClass(self, descriptor, hash, class_loader.Ptr());
+ type = LookupClass(self, descriptor, hash, class_loader);
}
if (type != nullptr) {
if (type->IsResolved()) {
@@ -7835,6 +7724,14 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
}
ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
+ return DoResolveType(type_idx, dex_cache, class_loader);
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
Thread* self = Thread::Current();
@@ -7851,7 +7748,7 @@ ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
// Convert a ClassNotFoundException to a NoClassDefFoundError.
StackHandleScope<1> hs(self);
Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException()));
- if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
+ if (cause->InstanceOf(GetClassRoot(ClassRoot::kJavaLangClassNotFoundException, this))) {
DCHECK(resolved == nullptr); // No Handle needed to preserve resolved.
self->ClearException();
ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
@@ -8197,7 +8094,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
ObjPtr<mirror::MethodType> resolved = dex_cache->GetResolvedMethodType(proto_idx);
if (resolved != nullptr) {
- return resolved.Ptr();
+ return resolved;
}
StackHandleScope<4> hs(self);
@@ -8218,8 +8115,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
// other than by looking at the shorty ?
const size_t num_method_args = strlen(dex_file.StringDataByIdx(proto_id.shorty_idx_)) - 1;
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_method_args)));
if (method_params == nullptr) {
@@ -8325,11 +8221,10 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForField(
}
StackHandleScope<4> hs(self);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params)));
- if (UNLIKELY(method_params.Get() == nullptr)) {
+ if (UNLIKELY(method_params == nullptr)) {
DCHECK(self->IsExceptionPending());
return nullptr;
}
@@ -8504,8 +8399,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod(
int32_t num_params = static_cast<int32_t>(shorty_length + receiver_count - 1);
StackHandleScope<7> hs(self);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params)));
if (method_params.Get() == nullptr) {
@@ -8678,67 +8572,10 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass
mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
DCHECK(class_roots != nullptr);
- DCHECK(class_roots->Get(class_root) == nullptr);
- class_roots->Set<false>(class_root, klass);
-}
-
-const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) {
- static const char* class_roots_descriptors[] = {
- "Ljava/lang/Class;",
- "Ljava/lang/Object;",
- "[Ljava/lang/Class;",
- "[Ljava/lang/Object;",
- "Ljava/lang/String;",
- "Ljava/lang/DexCache;",
- "Ljava/lang/ref/Reference;",
- "Ljava/lang/reflect/Constructor;",
- "Ljava/lang/reflect/Field;",
- "Ljava/lang/reflect/Method;",
- "Ljava/lang/reflect/Proxy;",
- "[Ljava/lang/String;",
- "[Ljava/lang/reflect/Constructor;",
- "[Ljava/lang/reflect/Field;",
- "[Ljava/lang/reflect/Method;",
- "Ljava/lang/invoke/CallSite;",
- "Ljava/lang/invoke/MethodHandleImpl;",
- "Ljava/lang/invoke/MethodHandles$Lookup;",
- "Ljava/lang/invoke/MethodType;",
- "Ljava/lang/invoke/VarHandle;",
- "Ljava/lang/invoke/FieldVarHandle;",
- "Ljava/lang/invoke/ArrayElementVarHandle;",
- "Ljava/lang/invoke/ByteArrayViewVarHandle;",
- "Ljava/lang/invoke/ByteBufferViewVarHandle;",
- "Ljava/lang/ClassLoader;",
- "Ljava/lang/Throwable;",
- "Ljava/lang/ClassNotFoundException;",
- "Ljava/lang/StackTraceElement;",
- "Ldalvik/system/EmulatedStackFrame;",
- "Z",
- "B",
- "C",
- "D",
- "F",
- "I",
- "J",
- "S",
- "V",
- "[Z",
- "[B",
- "[C",
- "[D",
- "[F",
- "[I",
- "[J",
- "[S",
- "[Ljava/lang/StackTraceElement;",
- "Ldalvik/system/ClassExt;",
- };
- static_assert(arraysize(class_roots_descriptors) == size_t(kClassRootsMax),
- "Mismatch between class descriptors and class-root enum");
-
- const char* descriptor = class_roots_descriptors[class_root];
- CHECK(descriptor != nullptr);
- return descriptor;
+ DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
+ int32_t index = static_cast<int32_t>(class_root);
+ DCHECK(class_roots->Get(index) == nullptr);
+ class_roots->Set<false>(index, klass);
}
jobject ClassLinker::CreateWellKnownClassLoader(Thread* self,
@@ -8913,7 +8750,7 @@ void ClassLinker::InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file,
DCHECK(dex_file != nullptr);
Thread* const self = Thread::Current();
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ClassTable* const table = ClassTableForClassLoader(class_loader.Ptr());
+ ClassTable* const table = ClassTableForClassLoader(class_loader);
DCHECK(table != nullptr);
if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
// It was not already inserted, perform the write barrier to let the GC know the class loader's
@@ -9060,19 +8897,19 @@ class ClassLinker::FindVirtualMethodHolderVisitor : public ClassVisitor {
const PointerSize pointer_size_;
};
-mirror::Class* ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) {
+ObjPtr<mirror::Class> ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) {
ScopedTrace trace(__FUNCTION__); // Since this function is slow, have a trace to notify people.
CHECK(method->IsCopied());
FindVirtualMethodHolderVisitor visitor(method, image_pointer_size_);
VisitClasses(&visitor);
- return visitor.holder_.Ptr();
+ return visitor.holder_;
}
-mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
- return down_cast<mirror::IfTable*>(
+ObjPtr<mirror::IfTable> ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
+ return ObjPtr<mirror::IfTable>::DownCast(ObjPtr<mirror::ObjectArray<mirror::Object>>(
mirror::IfTable::Alloc(self,
- GetClassRoot(kObjectArrayClass),
- ifcount * mirror::IfTable::kMax));
+ GetClassRoot<mirror::ObjectArray<mirror::Object>>(this),
+ ifcount * mirror::IfTable::kMax)));
}
// Instantiate ResolveMethod.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 52ecf82c86..548bf915dd 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,6 +27,7 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "dex/class_accessor.h"
#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
@@ -67,7 +68,10 @@ using MethodDexCachePair = NativeDexCachePair<ArtMethod>;
using MethodDexCacheType = std::atomic<MethodDexCachePair>;
} // namespace mirror
+class ArtField;
+class ArtMethod;
class ClassHierarchyAnalysis;
+enum class ClassRoot : uint32_t;
class ClassTable;
template<class T> class Handle;
class ImtConflictTable;
@@ -107,59 +111,6 @@ class AllocatorVisitor {
class ClassLinker {
public:
- // Well known mirror::Class roots accessed via GetClassRoot.
- enum ClassRoot {
- kJavaLangClass,
- kJavaLangObject,
- kClassArrayClass,
- kObjectArrayClass,
- kJavaLangString,
- kJavaLangDexCache,
- kJavaLangRefReference,
- kJavaLangReflectConstructor,
- kJavaLangReflectField,
- kJavaLangReflectMethod,
- kJavaLangReflectProxy,
- kJavaLangStringArrayClass,
- kJavaLangReflectConstructorArrayClass,
- kJavaLangReflectFieldArrayClass,
- kJavaLangReflectMethodArrayClass,
- kJavaLangInvokeCallSite,
- kJavaLangInvokeMethodHandleImpl,
- kJavaLangInvokeMethodHandlesLookup,
- kJavaLangInvokeMethodType,
- kJavaLangInvokeVarHandle,
- kJavaLangInvokeFieldVarHandle,
- kJavaLangInvokeArrayElementVarHandle,
- kJavaLangInvokeByteArrayViewVarHandle,
- kJavaLangInvokeByteBufferViewVarHandle,
- kJavaLangClassLoader,
- kJavaLangThrowable,
- kJavaLangClassNotFoundException,
- kJavaLangStackTraceElement,
- kDalvikSystemEmulatedStackFrame,
- kPrimitiveBoolean,
- kPrimitiveByte,
- kPrimitiveChar,
- kPrimitiveDouble,
- kPrimitiveFloat,
- kPrimitiveInt,
- kPrimitiveLong,
- kPrimitiveShort,
- kPrimitiveVoid,
- kBooleanArrayClass,
- kByteArrayClass,
- kCharArrayClass,
- kDoubleArrayClass,
- kFloatArrayClass,
- kIntArrayClass,
- kLongArrayClass,
- kShortArrayClass,
- kJavaLangStackTraceElementArrayClass,
- kDalvikSystemClassExt,
- kClassRootsMax,
- };
-
static constexpr bool kAppImageMayContainStrings = false;
explicit ClassLinker(InternTable* intern_table);
@@ -198,22 +149,22 @@ class ClassLinker {
// Finds a class by its descriptor, loading it if necessary.
// If class_loader is null, searches boot_class_path_.
- mirror::Class* FindClass(Thread* self,
- const char* descriptor,
- Handle<mirror::ClassLoader> class_loader)
+ ObjPtr<mirror::Class> FindClass(Thread* self,
+ const char* descriptor,
+ Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
// Finds a class by its descriptor using the "system" class loader, ie by searching the
// boot_class_path_.
- mirror::Class* FindSystemClass(Thread* self, const char* descriptor)
+ ObjPtr<mirror::Class> FindSystemClass(Thread* self, const char* descriptor)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_) {
return FindClass(self, descriptor, ScopedNullHandle<mirror::ClassLoader>());
}
// Finds the array class given for the element class.
- mirror::Class* FindArrayClass(Thread* self, ObjPtr<mirror::Class>* element_class)
+ ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class> element_class)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -223,20 +174,20 @@ class ClassLinker {
}
// Define a new a class based on a ClassDef from a DexFile
- mirror::Class* DefineClass(Thread* self,
- const char* descriptor,
- size_t hash,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def)
+ ObjPtr<mirror::Class> DefineClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
// Finds a class by its descriptor, returning null if it isn't wasn't loaded
// by the given 'class_loader'.
- mirror::Class* LookupClass(Thread* self,
- const char* descriptor,
- ObjPtr<mirror::ClassLoader> class_loader)
+ ObjPtr<mirror::Class> LookupClass(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -245,7 +196,7 @@ class ClassLinker {
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* FindPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::Class> FindPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);
void DumpForSigQuit(std::ostream& os) REQUIRES(!Locks::classlinker_classes_lock_);
@@ -253,6 +204,16 @@ class ClassLinker {
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Resolve a String with the given index from the DexFile associated with the given `referrer`,
+ // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
+ // to use for resolution.
+ ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
+ ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
+ ArtMethod* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Resolve a String with the given index from the DexFile associated with the given DexCache,
// storing the result in the DexCache.
ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
@@ -271,10 +232,9 @@ class ClassLinker {
ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ObjPtr<mirror::Class> referrer)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
-
- // Resolve a type with the given index from the DexFile associated with the given `referrer`,
- // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
- // and ClassLoader to use for resolution.
+ ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
@@ -294,10 +254,8 @@ class ClassLinker {
ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::Class> referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Look up a resolved type with the given index from the DexFile associated with the given
- // `referrer`, storing the result in the DexCache. The `referrer` is used to identify the
- // target DexCache and ClassLoader to use for lookup.
+ ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -504,16 +462,16 @@ class ClassLinker {
LinearAlloc* allocator,
size_t length);
- mirror::PointerArray* AllocPointerArray(Thread* self, size_t length)
+ ObjPtr<mirror::PointerArray> AllocPointerArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::IfTable* AllocIfTable(Thread* self, size_t ifcount)
+ ObjPtr<mirror::IfTable> AllocIfTable(Thread* self, size_t ifcount)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self,
- size_t length)
+ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> AllocStackTraceElementArray(Thread* self,
+ size_t length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -535,12 +493,12 @@ class ClassLinker {
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
- mirror::Class* CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
- jstring name,
- jobjectArray interfaces,
- jobject loader,
- jobjectArray methods,
- jobjectArray throws)
+ ObjPtr<mirror::Class> CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
+ jstring name,
+ jobjectArray interfaces,
+ jobject loader,
+ jobjectArray methods,
+ jobjectArray throws)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string GetDescriptorForProxy(ObjPtr<mirror::Class> proxy_class)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -552,10 +510,6 @@ class ClassLinker {
pid_t GetClassesLockOwner(); // For SignalCatcher.
pid_t GetDexLockOwner(); // For SignalCatcher.
- mirror::Class* GetClassRoot(ClassRoot class_root) REQUIRES_SHARED(Locks::mutator_lock_);
-
- static const char* GetClassRootDescriptor(ClassRoot class_root);
-
// Is the given entry point quick code to run the resolution stub?
bool IsQuickResolutionStub(const void* entry_point) const;
@@ -587,7 +541,9 @@ class ClassLinker {
// Attempts to insert a class into a class table. Returns null if
// the class was inserted, otherwise returns an existing class with
// the same descriptor and ClassLoader.
- mirror::Class* InsertClass(const char* descriptor, ObjPtr<mirror::Class> klass, size_t hash)
+ ObjPtr<mirror::Class> InsertClass(const char* descriptor,
+ ObjPtr<mirror::Class> klass,
+ size_t hash)
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -597,8 +553,10 @@ class ClassLinker {
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Class>* GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ ObjPtr<mirror::ObjectArray<mirror::Class>> GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ class_roots_.Read<kReadBarrierOption>();
DCHECK(class_roots != nullptr);
return class_roots;
}
@@ -714,7 +672,7 @@ class ClassLinker {
REQUIRES(!Locks::dex_lock_);
// Get the actual holding class for a copied method. Pretty slow, don't call often.
- mirror::Class* GetHoldingClassOfCopiedMethod(ArtMethod* method)
+ ObjPtr<mirror::Class> GetHoldingClassOfCopiedMethod(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns null if not found.
@@ -818,45 +776,41 @@ class ClassLinker {
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
// For early bootstrapping by Init
- mirror::Class* AllocClass(Thread* self,
- ObjPtr<mirror::Class> java_lang_Class,
- uint32_t class_size)
+ ObjPtr<mirror::Class> AllocClass(Thread* self,
+ ObjPtr<mirror::Class> java_lang_Class,
+ uint32_t class_size)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- // Alloc* convenience functions to avoid needing to pass in mirror::Class*
- // values that are known to the ClassLinker such as
- // kObjectArrayClass and kJavaLangString etc.
- mirror::Class* AllocClass(Thread* self, uint32_t class_size)
+ // Alloc* convenience functions to avoid needing to pass in ObjPtr<mirror::Class>
+ // values that are known to the ClassLinker such as classes corresponding to
+ // ClassRoot::kObjectArrayClass and ClassRoot::kJavaLangString etc.
+ ObjPtr<mirror::Class> AllocClass(Thread* self, uint32_t class_size)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::DexCache* AllocDexCache(ObjPtr<mirror::String>* out_location,
- Thread* self,
- const DexFile& dex_file)
+ ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+ Thread* self,
+ const DexFile& dex_file)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
// Used for tests and AppendToBootClassPath.
- mirror::DexCache* AllocAndInitializeDexCache(Thread* self,
- const DexFile& dex_file,
- LinearAlloc* linear_alloc)
+ ObjPtr<mirror::DexCache> AllocAndInitializeDexCache(Thread* self,
+ const DexFile& dex_file,
+ LinearAlloc* linear_alloc)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::Class* CreatePrimitiveClass(Thread* self, Primitive::Type type)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
- mirror::Class* InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
- Primitive::Type type)
+ ObjPtr<mirror::Class> CreatePrimitiveClass(Thread* self, Primitive::Type type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::Class* CreateArrayClass(Thread* self,
- const char* descriptor,
- size_t hash,
- Handle<mirror::ClassLoader> class_loader)
+ ObjPtr<mirror::Class> CreateArrayClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
@@ -882,18 +836,14 @@ class ClassLinker {
const DexFile::ClassDef& dex_class_def,
Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadClassMembers(Thread* self,
- const DexFile& dex_file,
- const uint8_t* class_data,
- Handle<mirror::Class> klass)
- REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
+ void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void LoadMethod(const DexFile& dex_file,
- const ClassDataItemIterator& it,
- Handle<mirror::Class> klass, ArtMethod* dst)
+ const ClassAccessor::Method& method,
+ Handle<mirror::Class> klass,
+ ArtMethod* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -908,7 +858,7 @@ class ClassLinker {
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
- ObjPtr<mirror::Class>* result)
+ /*out*/ ObjPtr<mirror::Class>* result)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -935,12 +885,32 @@ class ClassLinker {
// Implementation of LookupResolvedType() called when the type was not found in the dex cache.
ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Implementation of ResolveString() called when the string was not found in the dex cache.
+ ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Implementation of LookupString() called when the string was not found in the dex cache.
+ ObjPtr<mirror::String> DoLookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Implementation of ResolveType() called when the type was not found in the dex cache.
ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
+ ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -948,10 +918,10 @@ class ClassLinker {
// Finds a class by its descriptor, returning NULL if it isn't wasn't loaded
// by the given 'class_loader'. Uses the provided hash for the descriptor.
- mirror::Class* LookupClass(Thread* self,
- const char* descriptor,
- size_t hash,
- ObjPtr<mirror::ClassLoader> class_loader)
+ ObjPtr<mirror::Class> LookupClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1222,7 +1192,9 @@ class ClassLinker {
// when resolution has occurred. This happens in mirror::Class::SetStatus. As resolution may
// retire a class, the version of the class in the table is returned and this may differ from
// the class passed in.
- mirror::Class* EnsureResolved(Thread* self, const char* descriptor, ObjPtr<mirror::Class> klass)
+ ObjPtr<mirror::Class> EnsureResolved(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::Class> klass)
WARN_UNUSED
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 6ed029ceb1..e40f1dbcdf 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -25,6 +25,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "dex/dex_file_types.h"
#include "dex/standard_dex_file.h"
@@ -197,7 +198,8 @@ class ClassLinkerTest : public CommonRuntimeTest {
ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor(&temp));
EXPECT_TRUE(array->GetSuperClass() != nullptr);
Thread* self = Thread::Current();
- EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"),
+ array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != nullptr);
ASSERT_GT(strlen(array->GetComponentType()->GetDescriptor(&temp)), 0U);
@@ -231,8 +233,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
ObjPtr<mirror::Class> direct_interface1 =
mirror::Class::GetDirectInterface(self, array.Get(), 1);
EXPECT_STREQ(direct_interface1->GetDescriptor(&temp), "Ljava/io/Serializable;");
- ObjPtr<mirror::Class> array_ptr = array->GetComponentType();
- EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
PointerSize pointer_size = class_linker_->GetImagePointerSize();
ObjPtr<mirror::Class> JavaLangObject =
@@ -1078,27 +1079,27 @@ TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<5> hs(soa.Self());
Handle<mirror::LongArray> long_array(hs.NewHandle(mirror::LongArray::Alloc(soa.Self(), 0)));
- EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[J"), long_array->GetClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "[J"), long_array->GetClass());
uintptr_t data_offset = reinterpret_cast<uintptr_t>(long_array->GetData());
EXPECT_TRUE(IsAligned<8>(data_offset)); // Longs require 8 byte alignment
Handle<mirror::DoubleArray> double_array(hs.NewHandle(mirror::DoubleArray::Alloc(soa.Self(), 0)));
- EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[D"), double_array->GetClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "[D"), double_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(double_array->GetData());
EXPECT_TRUE(IsAligned<8>(data_offset)); // Doubles require 8 byte alignment
Handle<mirror::IntArray> int_array(hs.NewHandle(mirror::IntArray::Alloc(soa.Self(), 0)));
- EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[I"), int_array->GetClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "[I"), int_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(int_array->GetData());
EXPECT_TRUE(IsAligned<4>(data_offset)); // Ints require 4 byte alignment
Handle<mirror::CharArray> char_array(hs.NewHandle(mirror::CharArray::Alloc(soa.Self(), 0)));
- EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[C"), char_array->GetClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "[C"), char_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(char_array->GetData());
EXPECT_TRUE(IsAligned<2>(data_offset)); // Chars require 2 byte alignment
Handle<mirror::ShortArray> short_array(hs.NewHandle(mirror::ShortArray::Alloc(soa.Self(), 0)));
- EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[S"), short_array->GetClass());
+ EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "[S"), short_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(short_array->GetData());
EXPECT_TRUE(IsAligned<2>(data_offset)); // Shorts require 2 byte alignment
@@ -1387,11 +1388,10 @@ TEST_F(ClassLinkerTest, FinalizableBit) {
TEST_F(ClassLinkerTest, ClassRootDescriptors) {
ScopedObjectAccess soa(Thread::Current());
std::string temp;
- for (int i = 0; i < ClassLinker::kClassRootsMax; i++) {
- ObjPtr<mirror::Class> klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
+ for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) {
+ ObjPtr<mirror::Class> klass = GetClassRoot(ClassRoot(i), class_linker_);
EXPECT_GT(strlen(klass->GetDescriptor(&temp)), 0U);
- EXPECT_STREQ(klass->GetDescriptor(&temp),
- class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
+ EXPECT_STREQ(klass->GetDescriptor(&temp), GetClassRootDescriptor(ClassRoot(i))) << " i = " << i;
}
}
diff --git a/runtime/class_root.cc b/runtime/class_root.cc
new file mode 100644
index 0000000000..08820b0c61
--- /dev/null
+++ b/runtime/class_root.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "class_root.h"
+
+namespace art {
+
+const char* GetClassRootDescriptor(ClassRoot class_root) {
+ static const char* class_roots_descriptors[] = {
+#define CLASS_ROOT_DESCRIPTOR(name, descriptor, mirror_type) descriptor,
+ CLASS_ROOT_LIST(CLASS_ROOT_DESCRIPTOR)
+#undef CLASS_ROOT_DESCRIPTOR
+ };
+ static_assert(arraysize(class_roots_descriptors) == static_cast<size_t>(ClassRoot::kMax),
+ "Mismatch between class descriptors and class-root enum");
+
+ DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
+ const char* descriptor = class_roots_descriptors[static_cast<size_t>(class_root)];
+ CHECK(descriptor != nullptr);
+ return descriptor;
+}
+
+} // namespace art
diff --git a/runtime/class_root.h b/runtime/class_root.h
new file mode 100644
index 0000000000..4aa9801ab4
--- /dev/null
+++ b/runtime/class_root.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_CLASS_ROOT_H_
+#define ART_RUNTIME_CLASS_ROOT_H_
+
+#include "class_linker.h"
+#include "mirror/class.h"
+#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
+#include "runtime.h"
+
+namespace art {
+
+namespace mirror {
+class ArrayElementVarHandle;
+class ByteArrayViewVarHandle;
+class ByteBufferViewVarHandle;
+class CallSite;
+class ClassExt;
+class ClassLoader;
+class Constructor;
+class DexCache;
+class EmulatedStackFrame;
+class Field;
+class FieldVarHandle;
+class Method;
+class MethodHandleImpl;
+class MethodHandlesLookup;
+class MethodType;
+class Object;
+class Proxy;
+template<typename T> class PrimitiveArray;
+class Reference;
+class StackTraceElement;
+class String;
+class Throwable;
+class VarHandle;
+} // namespace mirror
+
+#define CLASS_ROOT_LIST(M) \
+ M(kJavaLangClass, "Ljava/lang/Class;", mirror::Class) \
+ M(kJavaLangObject, "Ljava/lang/Object;", mirror::Object) \
+ M(kClassArrayClass, "[Ljava/lang/Class;", mirror::ObjectArray<mirror::Class>) \
+ M(kObjectArrayClass, "[Ljava/lang/Object;", mirror::ObjectArray<mirror::Object>) \
+ M(kJavaLangString, "Ljava/lang/String;", mirror::String) \
+ M(kJavaLangDexCache, "Ljava/lang/DexCache;", mirror::DexCache) \
+ M(kJavaLangRefReference, "Ljava/lang/ref/Reference;", mirror::Reference) \
+ M(kJavaLangReflectConstructor, "Ljava/lang/reflect/Constructor;", mirror::Constructor) \
+ M(kJavaLangReflectField, "Ljava/lang/reflect/Field;", mirror::Field) \
+ M(kJavaLangReflectMethod, "Ljava/lang/reflect/Method;", mirror::Method) \
+ M(kJavaLangReflectProxy, "Ljava/lang/reflect/Proxy;", mirror::Proxy) \
+ M(kJavaLangStringArrayClass, "[Ljava/lang/String;", mirror::ObjectArray<mirror::String>) \
+ M(kJavaLangReflectConstructorArrayClass, "[Ljava/lang/reflect/Constructor;", mirror::ObjectArray<mirror::Constructor>) \
+ M(kJavaLangReflectFieldArrayClass, "[Ljava/lang/reflect/Field;", mirror::ObjectArray<mirror::Field>) \
+ M(kJavaLangReflectMethodArrayClass, "[Ljava/lang/reflect/Method;", mirror::ObjectArray<mirror::Method>) \
+ M(kJavaLangInvokeCallSite, "Ljava/lang/invoke/CallSite;", mirror::CallSite) \
+ M(kJavaLangInvokeMethodHandle, "Ljava/lang/invoke/MethodHandle;", mirror::MethodHandle) \
+ M(kJavaLangInvokeMethodHandleImpl, "Ljava/lang/invoke/MethodHandleImpl;", mirror::MethodHandleImpl) \
+ M(kJavaLangInvokeMethodHandlesLookup, "Ljava/lang/invoke/MethodHandles$Lookup;", mirror::MethodHandlesLookup) \
+ M(kJavaLangInvokeMethodType, "Ljava/lang/invoke/MethodType;", mirror::MethodType) \
+ M(kJavaLangInvokeVarHandle, "Ljava/lang/invoke/VarHandle;", mirror::VarHandle) \
+ M(kJavaLangInvokeFieldVarHandle, "Ljava/lang/invoke/FieldVarHandle;", mirror::FieldVarHandle) \
+ M(kJavaLangInvokeArrayElementVarHandle, "Ljava/lang/invoke/ArrayElementVarHandle;", mirror::ArrayElementVarHandle) \
+ M(kJavaLangInvokeByteArrayViewVarHandle, "Ljava/lang/invoke/ByteArrayViewVarHandle;", mirror::ByteArrayViewVarHandle) \
+ M(kJavaLangInvokeByteBufferViewVarHandle, "Ljava/lang/invoke/ByteBufferViewVarHandle;", mirror::ByteBufferViewVarHandle) \
+ M(kJavaLangClassLoader, "Ljava/lang/ClassLoader;", mirror::ClassLoader) \
+ M(kJavaLangThrowable, "Ljava/lang/Throwable;", mirror::Throwable) \
+ M(kJavaLangClassNotFoundException, "Ljava/lang/ClassNotFoundException;", detail::NoMirrorType<detail::ClassNotFoundExceptionTag>) \
+ M(kJavaLangStackTraceElement, "Ljava/lang/StackTraceElement;", mirror::StackTraceElement) \
+ M(kDalvikSystemEmulatedStackFrame, "Ldalvik/system/EmulatedStackFrame;", mirror::EmulatedStackFrame) \
+ M(kPrimitiveBoolean, "Z", detail::NoMirrorType<uint8_t>) \
+ M(kPrimitiveByte, "B", detail::NoMirrorType<int8_t>) \
+ M(kPrimitiveChar, "C", detail::NoMirrorType<uint16_t>) \
+ M(kPrimitiveDouble, "D", detail::NoMirrorType<double>) \
+ M(kPrimitiveFloat, "F", detail::NoMirrorType<float>) \
+ M(kPrimitiveInt, "I", detail::NoMirrorType<int32_t>) \
+ M(kPrimitiveLong, "J", detail::NoMirrorType<int64_t>) \
+ M(kPrimitiveShort, "S", detail::NoMirrorType<int16_t>) \
+ M(kPrimitiveVoid, "V", detail::NoMirrorType<void>) \
+ M(kBooleanArrayClass, "[Z", mirror::PrimitiveArray<uint8_t>) \
+ M(kByteArrayClass, "[B", mirror::PrimitiveArray<int8_t>) \
+ M(kCharArrayClass, "[C", mirror::PrimitiveArray<uint16_t>) \
+ M(kDoubleArrayClass, "[D", mirror::PrimitiveArray<double>) \
+ M(kFloatArrayClass, "[F", mirror::PrimitiveArray<float>) \
+ M(kIntArrayClass, "[I", mirror::PrimitiveArray<int32_t>) \
+ M(kLongArrayClass, "[J", mirror::PrimitiveArray<int64_t>) \
+ M(kShortArrayClass, "[S", mirror::PrimitiveArray<int16_t>) \
+ M(kJavaLangStackTraceElementArrayClass, "[Ljava/lang/StackTraceElement;", mirror::ObjectArray<mirror::StackTraceElement>) \
+ M(kDalvikSystemClassExt, "Ldalvik/system/ClassExt;", mirror::ClassExt)
+
+// Well known mirror::Class roots accessed via ClassLinker::GetClassRoots().
+enum class ClassRoot : uint32_t {
+#define CLASS_ROOT_ENUMERATOR(name, descriptor, mirror_type) name,
+ CLASS_ROOT_LIST(CLASS_ROOT_ENUMERATOR)
+#undef CLASS_ROOT_ENUMERATOR
+ kMax,
+};
+
+const char* GetClassRootDescriptor(ClassRoot class_root);
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(
+ ClassRoot class_root,
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots) REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(class_roots != nullptr);
+ if (kReadBarrierOption == kWithReadBarrier) {
+ // With read barrier all references must point to the to-space.
+ // Without read barrier, this check could fail.
+ DCHECK_EQ(class_roots, Runtime::Current()->GetClassLinker()->GetClassRoots());
+ }
+ DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
+ int32_t index = static_cast<int32_t>(class_root);
+ ObjPtr<mirror::Class> klass =
+ class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
+ DCHECK(klass != nullptr);
+ return klass;
+}
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root, ClassLinker* linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kReadBarrierOption>(class_root, linker->GetClassRoots<kReadBarrierOption>());
+}
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kReadBarrierOption>(class_root, Runtime::Current()->GetClassLinker());
+}
+
+namespace detail {
+
+class ClassNotFoundExceptionTag;
+template <class Tag> struct NoMirrorType;
+
+template <class MirrorType>
+struct ClassRootSelector; // No definition for unspecialized ClassRoot selector.
+
+#define SPECIALIZE_CLASS_ROOT_SELECTOR(name, descriptor, mirror_type) \
+ template <> \
+ struct ClassRootSelector<mirror_type> { \
+ static constexpr ClassRoot value = ClassRoot::name; \
+ };
+
+CLASS_ROOT_LIST(SPECIALIZE_CLASS_ROOT_SELECTOR)
+
+#undef SPECIALIZE_CLASS_ROOT_SELECTOR
+
+} // namespace detail
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value, class_roots);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassLinker* linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value, linker);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value);
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_CLASS_ROOT_H_
diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h
index 5da5470c1a..6b6fe341e0 100644
--- a/runtime/class_table-inl.h
+++ b/runtime/class_table-inl.h
@@ -20,6 +20,7 @@
#include "class_table.h"
#include "gc_root-inl.h"
+#include "mirror/class.h"
#include "oat_file.h"
namespace art {
diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc
index c5bb4d57e6..cb334b569f 100644
--- a/runtime/debug_print.cc
+++ b/runtime/debug_print.cc
@@ -37,7 +37,7 @@ std::string DescribeSpace(ObjPtr<mirror::Class> klass) {
std::ostringstream oss;
gc::Heap* heap = Runtime::Current()->GetHeap();
gc::space::ContinuousSpace* cs =
- heap->FindContinuousSpaceFromObject(klass.Ptr(), /* fail_ok */ true);
+ heap->FindContinuousSpaceFromObject(klass, /* fail_ok */ true);
if (cs != nullptr) {
if (cs->IsImageSpace()) {
gc::space::ImageSpace* ispace = cs->AsImageSpace();
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 88628bbc50..f75f47c075 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1388,7 +1388,7 @@ JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_
*new_object_id = 0;
return JDWP::ERR_OUT_OF_MEMORY;
}
- *new_object_id = gRegistry->Add(new_object.Ptr());
+ *new_object_id = gRegistry->Add(new_object);
return JDWP::ERR_NONE;
}
@@ -1404,10 +1404,9 @@ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t
return error;
}
Thread* self = Thread::Current();
- gc::Heap* heap = Runtime::Current()->GetHeap();
- mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length,
- c->GetComponentSizeShift(),
- heap->GetCurrentAllocator());
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ ObjPtr<mirror::Array> new_array =
+ mirror::Array::Alloc<true>(self, c, length, c->GetComponentSizeShift(), allocator_type);
if (new_array == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
@@ -1849,7 +1848,7 @@ static JValue GetArtFieldValue(ArtField* f, mirror::Object* o)
return field_value;
case Primitive::kPrimNot:
- field_value.SetL(f->GetObject(o).Ptr());
+ field_value.SetL(f->GetObject(o));
return field_value;
case Primitive::kPrimVoid:
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 95b42d27d2..9358cbe5a9 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -23,6 +23,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "dex/dex_file-inl.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
@@ -358,7 +359,7 @@ ObjPtr<mirror::Object> ProcessEncodedAnnotation(const ClassData& klass, const ui
ObjPtr<mirror::Class> annotation_member_class =
soa.Decode<mirror::Class>(WellKnownClasses::libcore_reflect_AnnotationMember);
ObjPtr<mirror::Class> annotation_member_array_class =
- class_linker->FindArrayClass(self, &annotation_member_class);
+ class_linker->FindArrayClass(self, annotation_member_class);
if (annotation_member_array_class == nullptr) {
return nullptr;
}
@@ -848,7 +849,8 @@ ObjPtr<mirror::Object> GetAnnotationValue(const ClassData& klass,
return annotation_value.value_.GetL();
}
-mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass,
+static ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureValue(
+ const ClassData& klass,
const DexFile::AnnotationSetItem* annotation_set)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
@@ -859,12 +861,9 @@ mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass,
if (annotation_item == nullptr) {
return nullptr;
}
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- Handle<mirror::Class> string_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class)));
- if (string_array_class == nullptr) {
- return nullptr;
- }
+ Handle<mirror::Class> string_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>());
+ DCHECK(string_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(klass, annotation_item, "value", string_array_class,
DexFile::kDexAnnotationArray);
@@ -879,19 +878,16 @@ ObjPtr<mirror::ObjectArray<mirror::Class>> GetThrowsValue(
const DexFile::AnnotationSetItem* annotation_set)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
- StackHandleScope<1> hs(Thread::Current());
const DexFile::AnnotationItem* annotation_item =
SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Throws;",
DexFile::kDexVisibilitySystem);
if (annotation_item == nullptr) {
return nullptr;
}
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- Handle<mirror::Class> class_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class)));
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> class_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(klass, annotation_item, "value", class_array_class,
DexFile::kDexAnnotationArray);
@@ -971,7 +967,7 @@ ObjPtr<mirror::ObjectArray<mirror::Object>> ProcessAnnotationSetRefList(
ObjPtr<mirror::Class> annotation_array_class =
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::Class> annotation_array_array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, annotation_array_class);
if (annotation_array_array_class == nullptr) {
return nullptr;
}
@@ -1019,7 +1015,7 @@ ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* fie
return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime);
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field) {
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
if (annotation_set == nullptr) {
return nullptr;
@@ -1170,9 +1166,10 @@ ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
annotation_class);
}
-bool GetParametersMetadataForMethod(ArtMethod* method,
- MutableHandle<mirror::ObjectArray<mirror::String>>* names,
- MutableHandle<mirror::IntArray>* access_flags) {
+bool GetParametersMetadataForMethod(
+ ArtMethod* method,
+ /*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
+ /*out*/ MutableHandle<mirror::IntArray>* access_flags) {
const DexFile::AnnotationSetItem* annotation_set =
FindAnnotationSetForMethod(method);
if (annotation_set == nullptr) {
@@ -1192,12 +1189,10 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
StackHandleScope<4> hs(Thread::Current());
// Extract the parameters' names String[].
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- Handle<mirror::Class> string_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class)));
- if (UNLIKELY(string_array_class == nullptr)) {
- return false;
- }
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::Class> string_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>(class_linker));
+ DCHECK(string_array_class != nullptr);
ClassData data(method);
Handle<mirror::Object> names_obj =
@@ -1211,10 +1206,8 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
}
// Extract the parameters' access flags int[].
- Handle<mirror::Class> int_array_class(hs.NewHandle(mirror::IntArray::GetArrayClass()));
- if (UNLIKELY(int_array_class == nullptr)) {
- return false;
- }
+ Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>(class_linker)));
+ DCHECK(int_array_class != nullptr);
Handle<mirror::Object> access_flags_obj =
hs.NewHandle(GetAnnotationValue(data,
annotation_item,
@@ -1225,12 +1218,12 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
return false;
}
- names->Assign(names_obj.Get()->AsObjectArray<mirror::String>());
- access_flags->Assign(access_flags_obj.Get()->AsIntArray());
+ names->Assign(names_obj->AsObjectArray<mirror::String>());
+ access_flags->Assign(access_flags_obj->AsIntArray());
return true;
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method) {
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
if (annotation_set == nullptr) {
return nullptr;
@@ -1344,12 +1337,9 @@ ObjPtr<mirror::ObjectArray<mirror::Class>> GetDeclaredClasses(Handle<mirror::Cla
return nullptr;
}
StackHandleScope<1> hs(Thread::Current());
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- Handle<mirror::Class> class_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(hs.Self(), &class_class)));
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ Handle<mirror::Class> class_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(data, annotation_item, "value", class_array_class,
DexFile::kDexAnnotationArray);
@@ -1445,7 +1435,7 @@ ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass) {
DexFile::kDexAnnotationMethod);
}
-bool GetInnerClass(Handle<mirror::Class> klass, ObjPtr<mirror::String>* name) {
+bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name) {
ClassData data(klass);
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
if (annotation_set == nullptr) {
@@ -1512,7 +1502,8 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) {
return true;
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
+ Handle<mirror::Class> klass) {
ClassData data(klass);
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
if (annotation_set == nullptr) {
diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h
index 9645a7febd..bde7891091 100644
--- a/runtime/dex/dex_file_annotations.h
+++ b/runtime/dex/dex_file_annotations.h
@@ -41,7 +41,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_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field)
+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_);
@@ -64,11 +64,11 @@ ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
uint32_t parameter_idx,
Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool GetParametersMetadataForMethod(ArtMethod* method,
- MutableHandle<mirror::ObjectArray<mirror::String>>* names,
- MutableHandle<mirror::IntArray>* access_flags)
- REQUIRES_SHARED(Locks::mutator_lock_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method)
+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_);
// Check whether `method` is annotated with `annotation_class`.
// If `lookup_in_resolved_boot_classes` is true, look up any of the
@@ -101,12 +101,12 @@ ObjPtr<mirror::Class> GetEnclosingClass(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool GetInnerClass(Handle<mirror::Class> klass, ObjPtr<mirror::String>* name)
+bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name)
REQUIRES_SHARED(Locks::mutator_lock_);
bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags)
REQUIRES_SHARED(Locks::mutator_lock_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
+ Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetSourceDebugExtension(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsClassAnnotationPresent(Handle<mirror::Class> klass,
diff --git a/runtime/dex_register_location.h b/runtime/dex_register_location.h
new file mode 100644
index 0000000000..c6d4ad2feb
--- /dev/null
+++ b/runtime/dex_register_location.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_DEX_REGISTER_LOCATION_H_
+#define ART_RUNTIME_DEX_REGISTER_LOCATION_H_
+
+#include <array>
+#include <cstdint>
+
+#include "base/dchecked_vector.h"
+#include "base/memory_region.h"
+
+namespace art {
+
+// Dex register location container used by DexRegisterMap and StackMapStream.
+class DexRegisterLocation {
+ public:
+ enum class Kind : int32_t {
+ kNone = -1, // vreg has not been set.
+ kInStack, // vreg is on the stack, value holds the stack offset.
+ kConstant, // vreg is a constant value.
+ kInRegister, // vreg is in low 32 bits of a core physical register.
+ kInRegisterHigh, // vreg is in high 32 bits of a core physical register.
+ kInFpuRegister, // vreg is in low 32 bits of an FPU register.
+ kInFpuRegisterHigh, // vreg is in high 32 bits of an FPU register.
+ };
+
+ DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
+
+ static DexRegisterLocation None() {
+ return DexRegisterLocation(Kind::kNone, 0);
+ }
+
+ bool IsLive() const { return kind_ != Kind::kNone; }
+
+ Kind GetKind() const { return kind_; }
+
+ // TODO: Remove.
+ Kind GetInternalKind() const { return kind_; }
+
+ int32_t GetValue() const { return value_; }
+
+ bool operator==(DexRegisterLocation other) const {
+ return kind_ == other.kind_ && value_ == other.value_;
+ }
+
+ bool operator!=(DexRegisterLocation other) const {
+ return !(*this == other);
+ }
+
+ private:
+ DexRegisterLocation() {}
+
+ Kind kind_;
+ int32_t value_;
+
+ friend class DexRegisterMap; // Allow creation of uninitialized array of locations.
+};
+
+static inline std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
+ return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_DEX_REGISTER_LOCATION_H_
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index f6b1c73230..022857a4d5 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -268,14 +268,14 @@ inline mirror::Class* CheckArrayAlloc(dex::TypeIndex type_idx,
// check.
template <bool kAccessCheck, bool kInstrumented>
ALWAYS_INLINE
-inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
- int32_t component_count,
- ArtMethod* method,
- Thread* self,
- gc::AllocatorType allocator_type) {
+inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+ int32_t component_count,
+ ArtMethod* method,
+ Thread* self,
+ gc::AllocatorType allocator_type) {
bool slow_path = false;
- mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method,
- &slow_path);
+ ObjPtr<mirror::Class> klass =
+ CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method, &slow_path);
if (UNLIKELY(slow_path)) {
if (klass == nullptr) {
return nullptr;
@@ -306,7 +306,7 @@ inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass,
// No need to retry a slow-path allocation as the above code won't cause a GC or thread
// suspension.
return mirror::Array::Alloc<kInstrumented>(self, klass, component_count,
- klass->GetComponentSizeShift(), allocator_type);
+ klass->GetComponentSizeShift(), allocator_type).Ptr();
}
template<FindFieldType type, bool access_check>
@@ -743,33 +743,6 @@ inline ObjPtr<mirror::Class> ResolveVerifyAndClinit(dex::TypeIndex type_idx,
return h_class.Get();
}
-static inline ObjPtr<mirror::String> ResolveString(ClassLinker* class_linker,
- dex::StringIndex string_idx,
- ArtMethod* referrer)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- string = class_linker->ResolveString(string_idx, dex_cache);
- }
- return string;
-}
-
-inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer,
- dex::StringIndex string_idx) {
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> string = referrer->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- string = class_linker->ResolveString(string_idx, dex_cache);
- }
- return string;
-}
-
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) {
// Save any pending exception over monitor exit call.
mirror::Throwable* saved_exception = nullptr;
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index e33de9c45a..9d70b03dfa 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -87,11 +87,11 @@ ALWAYS_INLINE inline mirror::Class* CheckArrayAlloc(dex::TypeIndex type_idx,
// When verification/compiler hasn't been able to verify access, optionally perform an access
// check.
template <bool kAccessCheck, bool kInstrumented>
-ALWAYS_INLINE inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
- int32_t component_count,
- ArtMethod* method,
- Thread* self,
- gc::AllocatorType allocator_type)
+ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+ int32_t component_count,
+ ArtMethod* method,
+ Thread* self,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -162,11 +162,6 @@ ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, dex::P
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
-inline ObjPtr<mirror::String> ResolveStringFromCode(ArtMethod* referrer,
- dex::StringIndex string_idx)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
// TODO: annotalysis disabled as monitor semantics are maintained in Java code.
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self)
NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 6f1bbaa093..1e309071f6 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -68,7 +68,7 @@ class ScopedQuickEntrypointChecks {
bool exit_check_;
};
-namespace detail_ {
+namespace detail {
template <InstructionSet>
struct CSFSelector; // No definition for unspecialized callee save frame selector.
@@ -87,9 +87,9 @@ struct CSFSelector<InstructionSet::kX86> { using type = x86::X86CalleeSaveFrame;
template <>
struct CSFSelector<InstructionSet::kX86_64> { using type = x86_64::X86_64CalleeSaveFrame; };
-} // namespace detail_
+} // namespace detail
-using RuntimeCalleeSaveFrame = detail_::CSFSelector<kRuntimeISA>::type;
+using RuntimeCalleeSaveFrame = detail::CSFSelector<kRuntimeISA>::type;
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index ed5885f224..5f7594c68d 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -25,6 +25,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
namespace art {
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index fa536c77a9..62756123e1 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -210,7 +210,8 @@ extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread*
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
CalleeSaveType::kSaveEverything);
ArtMethod* caller = caller_and_outer.caller;
- ObjPtr<mirror::String> result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
+ ObjPtr<mirror::String> result =
+ Runtime::Current()->GetClassLinker()->ResolveString(dex::StringIndex(string_idx), caller);
if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
StoreStringInBss(caller_and_outer.outer_method, dex::StringIndex(string_idx), result);
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 0985bf216f..a59faeae9b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -19,6 +19,7 @@
#include "base/enums.h"
#include "callee_save_frame.h"
#include "common_throws.h"
+#include "class_root.h"
#include "debug_print.h"
#include "debugger.h"
#include "dex/dex_file-inl.h"
@@ -2810,7 +2811,7 @@ extern "C" uintptr_t artInvokePolymorphic(
RangeInstructionOperands operands(first_arg + 1, num_vregs - 1);
Intrinsics intrinsic = static_cast<Intrinsics>(resolved_method->GetIntrinsic());
bool success = false;
- if (resolved_method->GetDeclaringClass() == mirror::MethodHandle::StaticClass()) {
+ if (resolved_method->GetDeclaringClass() == GetClassRoot<mirror::MethodHandle>(linker)) {
Handle<mirror::MethodHandle> method_handle(hs.NewHandle(
ObjPtr<mirror::MethodHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
if (intrinsic == Intrinsics::kMethodHandleInvokeExact) {
@@ -2831,7 +2832,7 @@ extern "C" uintptr_t artInvokePolymorphic(
result);
}
} else {
- DCHECK_EQ(mirror::VarHandle::StaticClass(), resolved_method->GetDeclaringClass());
+ DCHECK_EQ(GetClassRoot<mirror::VarHandle>(linker), resolved_method->GetDeclaringClass());
Handle<mirror::VarHandle> var_handle(hs.NewHandle(
ObjPtr<mirror::VarHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
mirror::VarHandle::AccessMode access_mode =
diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc
index e5b8ea5609..d59ff71676 100644
--- a/runtime/gc/accounting/mod_union_table_test.cc
+++ b/runtime/gc/accounting/mod_union_table_test.cc
@@ -17,6 +17,7 @@
#include "mod_union_table-inl.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "gc/space/space-inl.h"
#include "mirror/array-inl.h"
@@ -70,8 +71,7 @@ class ModUnionTableTest : public CommonRuntimeTest {
mirror::Class* GetObjectArrayClass(Thread* self, space::ContinuousMemMapAllocSpace* space)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (java_lang_object_array_ == nullptr) {
- java_lang_object_array_ =
- Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kObjectArrayClass);
+ java_lang_object_array_ = GetClassRoot<mirror::ObjectArray<mirror::Object>>().Ptr();
// Since the test doesn't have an image, the class of the object array keeps cards live
// inside the card cache mod-union table and causes the check
// ASSERT_FALSE(table->ContainsCardFor(reinterpret_cast<uintptr_t>(obj3)));
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 0747c3c77b..2c2c437365 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -23,6 +23,7 @@
#include "base/quasi_atomic.h"
#include "base/stl_util.h"
#include "base/systrace.h"
+#include "class_root.h"
#include "debugger.h"
#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/heap_bitmap-inl.h"
@@ -2244,7 +2245,7 @@ void ConcurrentCopying::FillWithDummyObject(mirror::Object* dummy_obj, size_t by
// Avoid going through read barrier for since kDisallowReadBarrierDuringScan may be enabled.
// Explicitly mark to make sure to get an object in the to-space.
mirror::Class* int_array_class = down_cast<mirror::Class*>(
- Mark(mirror::IntArray::GetArrayClass<kWithoutReadBarrier>()));
+ Mark(GetClassRoot<mirror::IntArray, kWithoutReadBarrier>().Ptr()));
CHECK(int_array_class != nullptr);
if (ReadBarrier::kEnableToSpaceInvariantChecks) {
AssertToSpaceInvariant(nullptr, MemberOffset(0), int_array_class);
@@ -2324,7 +2325,7 @@ mirror::Object* ConcurrentCopying::AllocateInSkippedBlock(size_t alloc_size) {
CHECK_GE(byte_size - alloc_size, min_object_size);
// FillWithDummyObject may mark an object, avoid holding skipped_blocks_lock_ to prevent lock
// violation and possible deadlock. The deadlock case is a recursive case:
- // FillWithDummyObject -> IntArray::GetArrayClass -> Mark -> Copy -> AllocateInSkippedBlock.
+ // FillWithDummyObject -> Mark(IntArray.class) -> Copy -> AllocateInSkippedBlock.
FillWithDummyObject(reinterpret_cast<mirror::Object*>(addr + alloc_size),
byte_size - alloc_size);
CHECK(region_space_->IsInToSpace(reinterpret_cast<mirror::Object*>(addr + alloc_size)));
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b004566ed1..25ed652b41 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3913,9 +3913,9 @@ void Heap::BroadcastForNewAllocationRecords() const {
}
void Heap::CheckGcStressMode(Thread* self, ObjPtr<mirror::Object>* obj) {
+ DCHECK(gc_stress_mode_);
auto* const runtime = Runtime::Current();
- if (gc_stress_mode_ && runtime->GetClassLinker()->IsInitialized() &&
- !runtime->IsActiveTransaction() && mirror::Class::HasJavaLangClass()) {
+ if (runtime->GetClassLinker()->IsInitialized() && !runtime->IsActiveTransaction()) {
// Check if we should GC.
bool new_backtrace = false;
{
diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
index 40ee86ce79..38695332bb 100644
--- a/runtime/gc/heap_verification_test.cc
+++ b/runtime/gc/heap_verification_test.cc
@@ -18,6 +18,7 @@
#include "base/memory_tool.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "handle_scope-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
@@ -34,12 +35,11 @@ class VerificationTest : public CommonRuntimeTest {
VerificationTest() {}
template <class T>
- mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
return mirror::ObjectArray<T>::Alloc(
self,
- class_linker->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass),
+ GetClassRoot<mirror::ObjectArray<mirror::Object>>(),
length);
}
};
diff --git a/runtime/gc/reference_processor-inl.h b/runtime/gc/reference_processor-inl.h
deleted file mode 100644
index 0f47d3dc9f..0000000000
--- a/runtime/gc/reference_processor-inl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
-#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
-
-#include "reference_processor.h"
-
-#include "mirror/reference-inl.h"
-
-namespace art {
-namespace gc {
-
-inline bool ReferenceProcessor::SlowPathEnabled() {
- return mirror::Reference::GetJavaLangRefReference()->GetSlowPathEnabled();
-}
-
-} // namespace gc
-} // namespace art
-
-#endif // ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 5be7b325d0..fe4124d788 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -16,8 +16,10 @@
#include "reference_processor.h"
+#include "art_field-inl.h"
#include "base/time_utils.h"
#include "base/utils.h"
+#include "class_root.h"
#include "collector/garbage_collector.h"
#include "jni/java_vm_ext.h"
#include "mirror/class-inl.h"
@@ -25,7 +27,6 @@
#include "mirror/reference-inl.h"
#include "nativehelper/scoped_local_ref.h"
#include "object_callbacks.h"
-#include "reference_processor-inl.h"
#include "reflection.h"
#include "scoped_thread_state_change-inl.h"
#include "task_processor.h"
@@ -47,15 +48,37 @@ ReferenceProcessor::ReferenceProcessor()
cleared_references_(Locks::reference_queue_cleared_references_lock_) {
}
+static inline MemberOffset GetSlowPathFlagOffset(ObjPtr<mirror::Class> reference_class)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(reference_class == GetClassRoot<mirror::Reference>());
+ // Second static field
+ ArtField* field = reference_class->GetStaticField(1);
+ DCHECK_STREQ(field->GetName(), "slowPathEnabled");
+ return field->GetOffset();
+}
+
+static inline void SetSlowPathFlag(bool enabled) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
+ MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
+ reference_class->SetFieldBoolean</* kTransactionActive */ false, /* kCheckTransaction */ false>(
+ slow_path_offset, enabled ? 1 : 0);
+}
+
void ReferenceProcessor::EnableSlowPath() {
- mirror::Reference::GetJavaLangRefReference()->SetSlowPath(true);
+ SetSlowPathFlag(/* enabled */ true);
}
void ReferenceProcessor::DisableSlowPath(Thread* self) {
- mirror::Reference::GetJavaLangRefReference()->SetSlowPath(false);
+ SetSlowPathFlag(/* enabled */ false);
condition_.Broadcast(self);
}
+bool ReferenceProcessor::SlowPathEnabled() {
+ ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
+ MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
+ return reference_class->GetFieldBoolean(slow_path_offset);
+}
+
void ReferenceProcessor::BroadcastForSlowPath(Thread* self) {
MutexLock mu(self, *Locks::reference_processor_lock_);
condition_.Broadcast(self);
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index d5861ed5d8..c94b666695 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -53,13 +53,11 @@ class SpaceTest : public Super {
}
mirror::Class* GetByteArrayClass(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
- StackHandleScope<1> hs(self);
- auto null_loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
if (byte_array_class_ == nullptr) {
- mirror::Class* byte_array_class =
- Runtime::Current()->GetClassLinker()->FindClass(self, "[B", null_loader);
+ ObjPtr<mirror::Class> byte_array_class =
+ Runtime::Current()->GetClassLinker()->FindSystemClass(self, "[B");
EXPECT_TRUE(byte_array_class != nullptr);
- byte_array_class_ = self->GetJniEnv()->NewLocalRef(byte_array_class);
+ byte_array_class_ = self->GetJniEnv()->NewLocalRef(byte_array_class.Ptr());
EXPECT_TRUE(byte_array_class_ != nullptr);
}
return self->DecodeJObject(byte_array_class_)->AsClass();
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index ab0c2901ff..a41d28492d 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -325,8 +325,8 @@ TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) {
ASSERT_TRUE(h_iface != nullptr);
// Create the proxy class.
- std::vector<mirror::Class*> interfaces;
- interfaces.push_back(h_iface.Get());
+ std::vector<Handle<mirror::Class>> interfaces;
+ interfaces.push_back(h_iface);
Handle<mirror::Class> proxyClass = hs.NewHandle(proxy_test::GenerateProxyClass(
soa, jclass_loader_, runtime_->GetClassLinker(), "$Proxy1234", interfaces));
ASSERT_TRUE(proxyClass != nullptr);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 3b6487449b..7bd5a6a68a 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -50,6 +50,7 @@
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
+#include "class_root.h"
#include "common_throws.h"
#include "debugger.h"
#include "dex/dex_file-inl.h"
@@ -1418,8 +1419,7 @@ void Hprof::DumpFakeObjectArray(mirror::Object* obj, const std::set<mirror::Obje
__ AddObjectId(obj);
__ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
__ AddU4(elements.size());
- __ AddClassId(LookupClassId(
- Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kObjectArrayClass)));
+ __ AddClassId(LookupClassId(GetClassRoot<mirror::ObjectArray<mirror::Object>>().Ptr()));
for (mirror::Object* e : elements) {
__ AddObjectId(e);
}
diff --git a/runtime/image-inl.h b/runtime/image-inl.h
index 935a1b6705..3a66a34cb3 100644
--- a/runtime/image-inl.h
+++ b/runtime/image-inl.h
@@ -22,6 +22,7 @@
#include "art_method.h"
#include "imt_conflict_table.h"
#include "imtable.h"
+#include "mirror/object_array-inl.h"
#include "read_barrier-inl.h"
namespace art {
diff --git a/runtime/image.cc b/runtime/image.cc
index 316f7a5c63..7ad2e7bf95 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '9', '\0' }; // ReachabilityFence.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '0', '\0' }; // ClassRoot::MethodHandle.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 9673bd9728..2128f8cde8 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -111,12 +111,12 @@ inline void IrtEntry::Add(ObjPtr<mirror::Object> obj) {
if (serial_ == kIRTPrevCount) {
serial_ = 0;
}
- references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+ references_[serial_] = GcRoot<mirror::Object>(obj);
}
inline void IrtEntry::SetReference(ObjPtr<mirror::Object> obj) {
DCHECK_LT(serial_, kIRTPrevCount);
- references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+ references_[serial_] = GcRoot<mirror::Object>(obj);
}
} // namespace art
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 708a7884fa..27f761a144 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -19,6 +19,7 @@
#include <cmath>
#include "base/enums.h"
+#include "class_root.h"
#include "debugger.h"
#include "dex/dex_file_types.h"
#include "entrypoints/runtime_asm_entrypoints.h"
@@ -865,6 +866,7 @@ static JValue ConvertScalarBootstrapArgument(jvalue value) {
static ObjPtr<mirror::Class> GetClassForBootstrapArgument(EncodedArrayValueIterator::ValueType type)
REQUIRES_SHARED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = class_linker->GetClassRoots();
switch (type) {
case EncodedArrayValueIterator::ValueType::kBoolean:
case EncodedArrayValueIterator::ValueType::kByte:
@@ -874,21 +876,21 @@ static ObjPtr<mirror::Class> GetClassForBootstrapArgument(EncodedArrayValueItera
// will result in CCE's being raised if the BSM has one of these
// types.
case EncodedArrayValueIterator::ValueType::kInt:
- return class_linker->FindPrimitiveClass('I');
+ return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots);
case EncodedArrayValueIterator::ValueType::kLong:
- return class_linker->FindPrimitiveClass('J');
+ return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots);
case EncodedArrayValueIterator::ValueType::kFloat:
- return class_linker->FindPrimitiveClass('F');
+ return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots);
case EncodedArrayValueIterator::ValueType::kDouble:
- return class_linker->FindPrimitiveClass('D');
+ return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots);
case EncodedArrayValueIterator::ValueType::kMethodType:
- return mirror::MethodType::StaticClass();
+ return GetClassRoot<mirror::MethodType>(class_roots);
case EncodedArrayValueIterator::ValueType::kMethodHandle:
- return mirror::MethodHandle::StaticClass();
+ return GetClassRoot<mirror::MethodHandle>(class_roots);
case EncodedArrayValueIterator::ValueType::kString:
- return mirror::String::GetJavaLangString();
+ return GetClassRoot<mirror::String>();
case EncodedArrayValueIterator::ValueType::kType:
- return mirror::Class::GetJavaLangClass();
+ return GetClassRoot<mirror::Class>();
case EncodedArrayValueIterator::ValueType::kField:
case EncodedArrayValueIterator::ValueType::kMethod:
case EncodedArrayValueIterator::ValueType::kEnum:
@@ -943,11 +945,9 @@ static bool GetArgumentForBootstrapMethod(Thread* self,
return true;
}
case EncodedArrayValueIterator::ValueType::kString: {
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
dex::StringIndex index(static_cast<uint32_t>(encoded_value->GetI()));
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::String> o = cl->ResolveString(index, dex_cache);
+ ObjPtr<mirror::String> o = cl->ResolveString(index, referrer);
if (UNLIKELY(o.IsNull())) {
DCHECK(self->IsExceptionPending());
return false;
@@ -956,12 +956,9 @@ static bool GetArgumentForBootstrapMethod(Thread* self,
return true;
}
case EncodedArrayValueIterator::ValueType::kType: {
- StackHandleScope<2> hs(self);
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
dex::TypeIndex index(static_cast<uint32_t>(encoded_value->GetI()));
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> o = cl->ResolveType(index, dex_cache, class_loader);
+ ObjPtr<mirror::Class> o = cl->ResolveType(index, referrer);
if (UNLIKELY(o.IsNull())) {
DCHECK(self->IsExceptionPending());
return false;
@@ -1091,21 +1088,23 @@ static bool PackCollectorArrayForBootstrapMethod(Thread* self,
setter->SetReference(array.Get()); \
return true;
- if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('I')) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = class_linker->GetClassRoots();
+ ObjPtr<mirror::Class> component_type = array_type->GetComponentType();
+ if (component_type == GetClassRoot(ClassRoot::kPrimitiveInt, class_roots)) {
COLLECT_PRIMITIVE_ARRAY(I, Int);
- } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('J')) {
+ } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveLong, class_roots)) {
COLLECT_PRIMITIVE_ARRAY(J, Long);
- } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('F')) {
+ } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots)) {
COLLECT_PRIMITIVE_ARRAY(F, Float);
- } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('D')) {
+ } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots)) {
COLLECT_PRIMITIVE_ARRAY(D, Double);
- } else if (array_type->GetComponentType() == mirror::MethodType::StaticClass()) {
+ } else if (component_type == GetClassRoot<mirror::MethodType>()) {
COLLECT_REFERENCE_ARRAY(mirror::MethodType, MethodType);
- } else if (array_type->GetComponentType() == mirror::MethodHandle::StaticClass()) {
+ } else if (component_type == GetClassRoot<mirror::MethodHandle>()) {
COLLECT_REFERENCE_ARRAY(mirror::MethodHandle, MethodHandle);
- } else if (array_type->GetComponentType() == mirror::String::GetJavaLangString()) {
+ } else if (component_type == GetClassRoot<mirror::String>(class_roots)) {
COLLECT_REFERENCE_ARRAY(mirror::String, String);
- } else if (array_type->GetComponentType() == mirror::Class::GetJavaLangClass()) {
+ } else if (component_type == GetClassRoot<mirror::Class>()) {
COLLECT_REFERENCE_ARRAY(mirror::Class, Type);
} else {
UNREACHABLE();
@@ -1124,9 +1123,9 @@ static ObjPtr<mirror::MethodType> BuildCallSiteForBootstrapMethod(Thread* self,
StackHandleScope<2> hs(self);
// Create array for parameter types.
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- mirror::Class* class_array_type =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_type);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ObjPtr<mirror::Class> class_array_type =
+ GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker);
Handle<mirror::ObjectArray<mirror::Class>> ptypes = hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self,
class_array_type,
@@ -1138,7 +1137,7 @@ static ObjPtr<mirror::MethodType> BuildCallSiteForBootstrapMethod(Thread* self,
// Populate the first argument with an instance of j.l.i.MethodHandles.Lookup
// that the runtime will construct.
- ptypes->Set(0, mirror::MethodHandlesLookup::StaticClass());
+ ptypes->Set(0, GetClassRoot<mirror::MethodHandlesLookup>(class_linker));
it.Next();
// The remaining parameter types are derived from the types of
@@ -1157,7 +1156,7 @@ static ObjPtr<mirror::MethodType> BuildCallSiteForBootstrapMethod(Thread* self,
DCHECK_EQ(static_cast<size_t>(index), it.Size());
// By definition, the return type is always a j.l.i.CallSite.
- Handle<mirror::Class> rtype = hs.NewHandle(mirror::CallSite::StaticClass());
+ Handle<mirror::Class> rtype = hs.NewHandle(GetClassRoot<mirror::CallSite>());
return mirror::MethodType::Create(self, rtype, ptypes);
}
@@ -1352,8 +1351,9 @@ static ObjPtr<mirror::CallSite> InvokeBootstrapMethod(Thread* self,
}
// Check the result type is a subclass of j.l.i.CallSite.
- if (UNLIKELY(!object->InstanceOf(mirror::CallSite::StaticClass()))) {
- ThrowClassCastException(object->GetClass(), mirror::CallSite::StaticClass());
+ ObjPtr<mirror::Class> call_site_class = GetClassRoot<mirror::CallSite>(class_linker);
+ if (UNLIKELY(!object->InstanceOf(call_site_class))) {
+ ThrowClassCastException(object->GetClass(), call_site_class);
return nullptr;
}
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 37234e1462..60bf50546f 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -35,6 +35,7 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_dex_operations.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
@@ -328,7 +329,7 @@ static inline ObjPtr<mirror::String> ResolveString(Thread* self,
ShadowFrame& shadow_frame,
dex::StringIndex string_idx)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::Class> java_lang_string_class = mirror::String::GetJavaLangString();
+ ObjPtr<mirror::Class> java_lang_string_class = GetClassRoot<mirror::String>();
if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(self);
@@ -339,12 +340,8 @@ static inline ObjPtr<mirror::String> ResolveString(Thread* self,
}
}
ArtMethod* method = shadow_frame.GetMethod();
- ObjPtr<mirror::String> string_ptr = method->GetDexCache()->GetResolvedString(string_idx);
- if (UNLIKELY(string_ptr == nullptr)) {
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- string_ptr = Runtime::Current()->GetClassLinker()->ResolveString(string_idx, dex_cache);
- }
+ ObjPtr<mirror::String> string_ptr =
+ Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method);
return string_ptr;
}
diff --git a/runtime/interpreter/mterp/arm/instruction_end.S b/runtime/interpreter/mterp/arm/instruction_end.S
new file mode 100644
index 0000000000..32c725c7d9
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
diff --git a/runtime/interpreter/mterp/arm/instruction_end_alt.S b/runtime/interpreter/mterp/arm/instruction_end_alt.S
new file mode 100644
index 0000000000..f90916fc02
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
diff --git a/runtime/interpreter/mterp/arm/instruction_end_sister.S b/runtime/interpreter/mterp/arm/instruction_end_sister.S
new file mode 100644
index 0000000000..c5f4886697
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
diff --git a/runtime/interpreter/mterp/arm/instruction_start.S b/runtime/interpreter/mterp/arm/instruction_start.S
new file mode 100644
index 0000000000..8874c20540
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmInstructionStart
+artMterpAsmInstructionStart = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/arm/instruction_start_alt.S b/runtime/interpreter/mterp/arm/instruction_start_alt.S
new file mode 100644
index 0000000000..0c9ffdb7d6
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/arm/instruction_start_sister.S b/runtime/interpreter/mterp/arm/instruction_start_sister.S
new file mode 100644
index 0000000000..2ec51f7261
--- /dev/null
+++ b/runtime/interpreter/mterp/arm/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global artMterpAsmSisterStart
+ .text
+ .balign 4
+artMterpAsmSisterStart:
diff --git a/runtime/interpreter/mterp/arm64/header.S b/runtime/interpreter/mterp/arm64/header.S
index 7017dd149c..0722804265 100644
--- a/runtime/interpreter/mterp/arm64/header.S
+++ b/runtime/interpreter/mterp/arm64/header.S
@@ -339,6 +339,7 @@ codes.
*/
.macro ENTRY name
.type \name, #function
+ .hidden \name // Hide this as a global symbol, so we do not incur plt calls.
.global \name
/* Cache alignment for function entry */
.balign 16
diff --git a/runtime/interpreter/mterp/arm64/instruction_end.S b/runtime/interpreter/mterp/arm64/instruction_end.S
new file mode 100644
index 0000000000..32c725c7d9
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
diff --git a/runtime/interpreter/mterp/arm64/instruction_end_alt.S b/runtime/interpreter/mterp/arm64/instruction_end_alt.S
new file mode 100644
index 0000000000..f90916fc02
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
diff --git a/runtime/interpreter/mterp/arm64/instruction_end_sister.S b/runtime/interpreter/mterp/arm64/instruction_end_sister.S
new file mode 100644
index 0000000000..c5f4886697
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
diff --git a/runtime/interpreter/mterp/arm64/instruction_start.S b/runtime/interpreter/mterp/arm64/instruction_start.S
new file mode 100644
index 0000000000..8874c20540
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmInstructionStart
+artMterpAsmInstructionStart = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/arm64/instruction_start_alt.S b/runtime/interpreter/mterp/arm64/instruction_start_alt.S
new file mode 100644
index 0000000000..0c9ffdb7d6
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/arm64/instruction_start_sister.S b/runtime/interpreter/mterp/arm64/instruction_start_sister.S
new file mode 100644
index 0000000000..2ec51f7261
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global artMterpAsmSisterStart
+ .text
+ .balign 4
+artMterpAsmSisterStart:
diff --git a/runtime/interpreter/mterp/gen_mterp.py b/runtime/interpreter/mterp/gen_mterp.py
index 64114d747a..75c5174bcb 100755
--- a/runtime/interpreter/mterp/gen_mterp.py
+++ b/runtime/interpreter/mterp/gen_mterp.py
@@ -279,13 +279,8 @@ def loadAndEmitOpcodes():
sister_list = []
assert len(opcodes) == kNumPackedOpcodes
need_dummy_start = False
- start_label = global_name_format % "artMterpAsmInstructionStart"
- end_label = global_name_format % "artMterpAsmInstructionEnd"
- # point MterpAsmInstructionStart at the first handler or stub
- asm_fp.write("\n .global %s\n" % start_label)
- asm_fp.write("%s = " % start_label + label_prefix + "_op_nop\n")
- asm_fp.write(" .text\n\n")
+ loadAndEmitGenericAsm("instruction_start")
for i in xrange(kNumPackedOpcodes):
op = opcodes[i]
@@ -309,20 +304,14 @@ def loadAndEmitOpcodes():
asm_fp.write(label_prefix + "_op_nop: /* dummy */\n");
emitAlign()
- asm_fp.write(" .global %s\n" % end_label)
- asm_fp.write("%s:\n" % end_label)
+
+ loadAndEmitGenericAsm("instruction_end")
if style == "computed-goto":
- start_sister_label = global_name_format % "artMterpAsmSisterStart"
- end_sister_label = global_name_format % "artMterpAsmSisterEnd"
emitSectionComment("Sister implementations", asm_fp)
- asm_fp.write(" .global %s\n" % start_sister_label)
- asm_fp.write(" .text\n")
- asm_fp.write(" .balign 4\n")
- asm_fp.write("%s:\n" % start_sister_label)
+ loadAndEmitGenericAsm("instruction_start_sister")
asm_fp.writelines(sister_list)
- asm_fp.write(" .global %s\n" % end_sister_label)
- asm_fp.write("%s:\n\n" % end_sister_label)
+ loadAndEmitGenericAsm("instruction_end_sister")
#
# Load an alternate entry stub
@@ -345,10 +334,7 @@ def loadAndEmitAltOpcodes():
start_label = global_name_format % "artMterpAsmAltInstructionStart"
end_label = global_name_format % "artMterpAsmAltInstructionEnd"
- # point MterpAsmInstructionStart at the first handler or stub
- asm_fp.write("\n .global %s\n" % start_label)
- asm_fp.write(" .text\n\n")
- asm_fp.write("%s = " % start_label + label_prefix + "_ALT_op_nop\n")
+ loadAndEmitGenericAsm("instruction_start_alt")
for i in xrange(kNumPackedOpcodes):
op = opcodes[i]
@@ -359,8 +345,8 @@ def loadAndEmitAltOpcodes():
loadAndEmitAltStub(source, i)
emitAlign()
- asm_fp.write(" .global %s\n" % end_label)
- asm_fp.write("%s:\n" % end_label)
+
+ loadAndEmitGenericAsm("instruction_end_alt")
#
# Load an assembly fragment and emit it.
@@ -377,6 +363,14 @@ def loadAndEmitAsm(location, opindex, sister_list):
appendSourceFile(source, dict, asm_fp, sister_list)
#
+# Load a non-handler assembly fragment and emit it.
+#
+def loadAndEmitGenericAsm(name):
+ source = "%s/%s.S" % (default_op_dir, name)
+ dict = getGlobalSubDict()
+ appendSourceFile(source, dict, asm_fp, None)
+
+#
# Emit fallback fragment
#
def emitFallback(opindex):
diff --git a/runtime/interpreter/mterp/mips/instruction_end.S b/runtime/interpreter/mterp/mips/instruction_end.S
new file mode 100644
index 0000000000..32c725c7d9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
diff --git a/runtime/interpreter/mterp/mips/instruction_end_alt.S b/runtime/interpreter/mterp/mips/instruction_end_alt.S
new file mode 100644
index 0000000000..f90916fc02
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
diff --git a/runtime/interpreter/mterp/mips/instruction_end_sister.S b/runtime/interpreter/mterp/mips/instruction_end_sister.S
new file mode 100644
index 0000000000..c5f4886697
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
diff --git a/runtime/interpreter/mterp/mips/instruction_start.S b/runtime/interpreter/mterp/mips/instruction_start.S
new file mode 100644
index 0000000000..8874c20540
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmInstructionStart
+artMterpAsmInstructionStart = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/mips/instruction_start_alt.S b/runtime/interpreter/mterp/mips/instruction_start_alt.S
new file mode 100644
index 0000000000..0c9ffdb7d6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/mips/instruction_start_sister.S b/runtime/interpreter/mterp/mips/instruction_start_sister.S
new file mode 100644
index 0000000000..2ec51f7261
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global artMterpAsmSisterStart
+ .text
+ .balign 4
+artMterpAsmSisterStart:
diff --git a/runtime/interpreter/mterp/mips64/instruction_end.S b/runtime/interpreter/mterp/mips64/instruction_end.S
new file mode 100644
index 0000000000..32c725c7d9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
diff --git a/runtime/interpreter/mterp/mips64/instruction_end_alt.S b/runtime/interpreter/mterp/mips64/instruction_end_alt.S
new file mode 100644
index 0000000000..f90916fc02
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
diff --git a/runtime/interpreter/mterp/mips64/instruction_end_sister.S b/runtime/interpreter/mterp/mips64/instruction_end_sister.S
new file mode 100644
index 0000000000..c5f4886697
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
diff --git a/runtime/interpreter/mterp/mips64/instruction_start.S b/runtime/interpreter/mterp/mips64/instruction_start.S
new file mode 100644
index 0000000000..8874c20540
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmInstructionStart
+artMterpAsmInstructionStart = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/mips64/instruction_start_alt.S b/runtime/interpreter/mterp/mips64/instruction_start_alt.S
new file mode 100644
index 0000000000..0c9ffdb7d6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/mips64/instruction_start_sister.S b/runtime/interpreter/mterp/mips64/instruction_start_sister.S
new file mode 100644
index 0000000000..2ec51f7261
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global artMterpAsmSisterStart
+ .text
+ .balign 4
+artMterpAsmSisterStart:
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index d62f511ad5..e4cc6d3f9f 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -559,7 +559,7 @@ extern "C" size_t MterpNewArray(ShadowFrame* shadow_frame,
REQUIRES_SHARED(Locks::mutator_lock_) {
const Instruction* inst = Instruction::At(dex_pc_ptr);
int32_t length = shadow_frame->GetVReg(inst->VRegB_22c(inst_data));
- mirror::Object* obj = AllocArrayFromCode<false, true>(
+ ObjPtr<mirror::Object> obj = AllocArrayFromCode<false, true>(
dex::TypeIndex(inst->VRegC_22c()), length, shadow_frame->GetMethod(), self,
Runtime::Current()->GetHeap()->GetCurrentAllocator());
if (UNLIKELY(obj == nullptr)) {
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 7ea79821b4..b2702a9ffc 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -396,6 +396,7 @@ ENTRY ExecuteMterpImpl
GOTO_OPCODE ip @ jump to next instruction
/* NOTE: no fallthrough */
+/* File: arm/instruction_start.S */
.global artMterpAsmInstructionStart
artMterpAsmInstructionStart = .L_op_nop
@@ -7509,19 +7510,25 @@ constvalop_long_to_double:
.balign 128
+/* File: arm/instruction_end.S */
+
.global artMterpAsmInstructionEnd
artMterpAsmInstructionEnd:
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: arm/instruction_start_sister.S */
+
.global artMterpAsmSisterStart
.text
.balign 4
artMterpAsmSisterStart:
+
/* continuation for op_float_to_long */
/*
* Convert the float in r0 to a long in r0/r1.
@@ -7583,14 +7590,17 @@ d2l_maybeNaN:
mov r0, #0
mov r1, #0
bx lr @ return 0 for NaN
+/* File: arm/instruction_end_sister.S */
+
.global artMterpAsmSisterEnd
artMterpAsmSisterEnd:
+/* File: arm/instruction_start_alt.S */
.global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
.text
-artMterpAsmAltInstructionStart = .L_ALT_op_nop
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -11944,8 +11954,11 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop
b MterpCheckBefore @ (self, shadow_frame, dex_pc_ptr) @ Tail call.
.balign 128
+/* File: arm/instruction_end_alt.S */
+
.global artMterpAsmAltInstructionEnd
artMterpAsmAltInstructionEnd:
+
/* File: arm/footer.S */
/*
* ===========================================================================
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index d5374d2a8a..2a0c4df3e2 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -346,6 +346,7 @@ codes.
*/
.macro ENTRY name
.type \name, #function
+ .hidden \name // Hide this as a global symbol, so we do not incur plt calls.
.global \name
/* Cache alignment for function entry */
.balign 16
@@ -426,6 +427,7 @@ ENTRY ExecuteMterpImpl
GOTO_OPCODE ip // jump to next instruction
/* NOTE: no fallthrough */
+/* File: arm64/instruction_start.S */
.global artMterpAsmInstructionStart
artMterpAsmInstructionStart = .L_op_nop
@@ -7074,18 +7076,26 @@ artMterpAsmInstructionStart = .L_op_nop
.balign 128
+/* File: arm64/instruction_end.S */
+
.global artMterpAsmInstructionEnd
artMterpAsmInstructionEnd:
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: arm64/instruction_start_sister.S */
+
.global artMterpAsmSisterStart
.text
.balign 4
artMterpAsmSisterStart:
+
+/* File: arm64/instruction_end_sister.S */
+
.global artMterpAsmSisterEnd
artMterpAsmSisterEnd:
@@ -7397,11 +7407,12 @@ MterpProfileActive:
ret
+/* File: arm64/instruction_start_alt.S */
.global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
.text
-artMterpAsmAltInstructionStart = .L_ALT_op_nop
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -11755,8 +11766,11 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop
b MterpCheckBefore // (self, shadow_frame, dex_pc_ptr) Note: tail call.
.balign 128
+/* File: arm64/instruction_end_alt.S */
+
.global artMterpAsmAltInstructionEnd
artMterpAsmAltInstructionEnd:
+
/* File: arm64/close_cfi.S */
// Close out the cfi info. We're treating mterp as a single function.
diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S
index 69568eaf44..3b86279b47 100644
--- a/runtime/interpreter/mterp/out/mterp_mips.S
+++ b/runtime/interpreter/mterp/out/mterp_mips.S
@@ -810,6 +810,7 @@ ExecuteMterpImpl:
GOTO_OPCODE(t0) # jump to next instruction
/* NOTE: no fallthrough */
+/* File: mips/instruction_start.S */
.global artMterpAsmInstructionStart
artMterpAsmInstructionStart = .L_op_nop
@@ -7873,19 +7874,25 @@ artMterpAsmInstructionStart = .L_op_nop
.balign 128
+/* File: mips/instruction_end.S */
+
.global artMterpAsmInstructionEnd
artMterpAsmInstructionEnd:
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: mips/instruction_start_sister.S */
+
.global artMterpAsmSisterStart
.text
.balign 4
artMterpAsmSisterStart:
+
/* continuation for op_float_to_long */
#ifndef MIPS32REVGE6
@@ -7941,14 +7948,17 @@ artMterpAsmSisterStart:
.Lop_ushr_long_2addr_finish:
SET_VREG64_GOTO(v1, zero, t3, t0) # vA/vA+1 <- rlo/rhi
+/* File: mips/instruction_end_sister.S */
+
.global artMterpAsmSisterEnd
artMterpAsmSisterEnd:
+/* File: mips/instruction_start_alt.S */
.global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
.text
-artMterpAsmAltInstructionStart = .L_ALT_op_nop
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -12558,8 +12568,11 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop
jalr zero, t9 # Tail call to Mterp(self, shadow_frame, dex_pc_ptr)
.balign 128
+/* File: mips/instruction_end_alt.S */
+
.global artMterpAsmAltInstructionEnd
artMterpAsmAltInstructionEnd:
+
/* File: mips/footer.S */
/*
* ===========================================================================
diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S
index 83a6613e37..58f98dfabb 100644
--- a/runtime/interpreter/mterp/out/mterp_mips64.S
+++ b/runtime/interpreter/mterp/out/mterp_mips64.S
@@ -430,6 +430,7 @@ ExecuteMterpImpl:
/* NOTE: no fallthrough */
+/* File: mips64/instruction_start.S */
.global artMterpAsmInstructionStart
artMterpAsmInstructionStart = .L_op_nop
@@ -7299,26 +7300,35 @@ artMterpAsmInstructionStart = .L_op_nop
.balign 128
+/* File: mips64/instruction_end.S */
+
.global artMterpAsmInstructionEnd
artMterpAsmInstructionEnd:
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: mips64/instruction_start_sister.S */
+
.global artMterpAsmSisterStart
.text
.balign 4
artMterpAsmSisterStart:
+
+/* File: mips64/instruction_end_sister.S */
+
.global artMterpAsmSisterEnd
artMterpAsmSisterEnd:
+/* File: mips64/instruction_start_alt.S */
.global artMterpAsmAltInstructionStart
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
.text
-artMterpAsmAltInstructionStart = .L_ALT_op_nop
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -12184,8 +12194,11 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop
jalr zero, t9 # (self, shadow_frame, dex_pc_ptr) Note: tail call.
.balign 128
+/* File: mips64/instruction_end_alt.S */
+
.global artMterpAsmAltInstructionEnd
artMterpAsmAltInstructionEnd:
+
/* File: mips64/footer.S */
/*
* We've detected a condition that will result in an exception, but the exception
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 6f4752f312..6be70cce4c 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -106,11 +106,13 @@ unspecified registers or condition codes.
#define SIZE(start,end)
// Mac OS' symbols have an _ prefix.
#define SYMBOL(name) _ ## name
+ #define ASM_HIDDEN .private_extern
#else
#define MACRO_LITERAL(value) $value
#define FUNCTION_TYPE(name) .type name, @function
#define SIZE(start,end) .size start, .-end
#define SYMBOL(name) name
+ #define ASM_HIDDEN .hidden
#endif
.macro PUSH _reg
@@ -339,6 +341,7 @@ unspecified registers or condition codes.
*/
.text
+ ASM_HIDDEN SYMBOL(ExecuteMterpImpl)
.global SYMBOL(ExecuteMterpImpl)
FUNCTION_TYPE(ExecuteMterpImpl)
@@ -402,6 +405,7 @@ SYMBOL(ExecuteMterpImpl):
GOTO_NEXT
/* NOTE: no fallthrough */
+/* File: x86/instruction_start.S */
.global SYMBOL(artMterpAsmInstructionStart)
SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
@@ -6467,26 +6471,35 @@ SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
.balign 128
+/* File: x86/instruction_end.S */
+
.global SYMBOL(artMterpAsmInstructionEnd)
SYMBOL(artMterpAsmInstructionEnd):
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: x86/instruction_start_sister.S */
+
.global SYMBOL(artMterpAsmSisterStart)
.text
.balign 4
SYMBOL(artMterpAsmSisterStart):
+
+/* File: x86/instruction_end_sister.S */
+
.global SYMBOL(artMterpAsmSisterEnd)
SYMBOL(artMterpAsmSisterEnd):
+/* File: x86/instruction_start_alt.S */
.global SYMBOL(artMterpAsmAltInstructionStart)
.text
-
SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
+
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -12632,8 +12645,11 @@ SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
jmp .L_op_nop+(255*128)
.balign 128
+/* File: x86/instruction_end_alt.S */
+
.global SYMBOL(artMterpAsmAltInstructionEnd)
SYMBOL(artMterpAsmAltInstructionEnd):
+
/* File: x86/footer.S */
/*
* ===========================================================================
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
index fca2515698..562cf7ceb6 100644
--- a/runtime/interpreter/mterp/out/mterp_x86_64.S
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -102,11 +102,13 @@ unspecified registers or condition codes.
#define SIZE(start,end)
// Mac OS' symbols have an _ prefix.
#define SYMBOL(name) _ ## name
+ #define ASM_HIDDEN .private_extern
#else
#define MACRO_LITERAL(value) $value
#define FUNCTION_TYPE(name) .type name, @function
#define SIZE(start,end) .size start, .-end
#define SYMBOL(name) name
+ #define ASM_HIDDEN .hidden
#endif
.macro PUSH _reg
@@ -325,6 +327,7 @@ unspecified registers or condition codes.
*/
.text
+ ASM_HIDDEN SYMBOL(ExecuteMterpImpl)
.global SYMBOL(ExecuteMterpImpl)
FUNCTION_TYPE(ExecuteMterpImpl)
@@ -384,6 +387,7 @@ SYMBOL(ExecuteMterpImpl):
GOTO_NEXT
/* NOTE: no fallthrough */
+/* File: x86_64/instruction_start.S */
.global SYMBOL(artMterpAsmInstructionStart)
SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
@@ -6214,26 +6218,35 @@ movswl %ax, %eax
.balign 128
+/* File: x86_64/instruction_end.S */
+
.global SYMBOL(artMterpAsmInstructionEnd)
SYMBOL(artMterpAsmInstructionEnd):
+
/*
* ===========================================================================
* Sister implementations
* ===========================================================================
*/
+/* File: x86_64/instruction_start_sister.S */
+
.global SYMBOL(artMterpAsmSisterStart)
.text
.balign 4
SYMBOL(artMterpAsmSisterStart):
+
+/* File: x86_64/instruction_end_sister.S */
+
.global SYMBOL(artMterpAsmSisterEnd)
SYMBOL(artMterpAsmSisterEnd):
+/* File: x86_64/instruction_start_alt.S */
.global SYMBOL(artMterpAsmAltInstructionStart)
.text
-
SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
+
/* ------------------------------ */
.balign 128
.L_ALT_op_nop: /* 0x00 */
@@ -11867,8 +11880,11 @@ SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
jmp .L_op_nop+(255*128)
.balign 128
+/* File: x86_64/instruction_end_alt.S */
+
.global SYMBOL(artMterpAsmAltInstructionEnd)
SYMBOL(artMterpAsmAltInstructionEnd):
+
/* File: x86_64/footer.S */
/*
* ===========================================================================
diff --git a/runtime/interpreter/mterp/x86/entry.S b/runtime/interpreter/mterp/x86/entry.S
index 324637bf9a..939dc61d95 100644
--- a/runtime/interpreter/mterp/x86/entry.S
+++ b/runtime/interpreter/mterp/x86/entry.S
@@ -18,6 +18,7 @@
*/
.text
+ ASM_HIDDEN SYMBOL(ExecuteMterpImpl)
.global SYMBOL(ExecuteMterpImpl)
FUNCTION_TYPE(ExecuteMterpImpl)
diff --git a/runtime/interpreter/mterp/x86/header.S b/runtime/interpreter/mterp/x86/header.S
index 9d826c2ce2..6f31228005 100644
--- a/runtime/interpreter/mterp/x86/header.S
+++ b/runtime/interpreter/mterp/x86/header.S
@@ -99,11 +99,13 @@ unspecified registers or condition codes.
#define SIZE(start,end)
// Mac OS' symbols have an _ prefix.
#define SYMBOL(name) _ ## name
+ #define ASM_HIDDEN .private_extern
#else
#define MACRO_LITERAL(value) $$value
#define FUNCTION_TYPE(name) .type name, @function
#define SIZE(start,end) .size start, .-end
#define SYMBOL(name) name
+ #define ASM_HIDDEN .hidden
#endif
.macro PUSH _reg
diff --git a/runtime/interpreter/mterp/x86/instruction_end.S b/runtime/interpreter/mterp/x86/instruction_end.S
new file mode 100644
index 0000000000..3a02a212e6
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmInstructionEnd)
+SYMBOL(artMterpAsmInstructionEnd):
diff --git a/runtime/interpreter/mterp/x86/instruction_end_alt.S b/runtime/interpreter/mterp/x86/instruction_end_alt.S
new file mode 100644
index 0000000000..33c2b8e2a0
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmAltInstructionEnd)
+SYMBOL(artMterpAsmAltInstructionEnd):
diff --git a/runtime/interpreter/mterp/x86/instruction_end_sister.S b/runtime/interpreter/mterp/x86/instruction_end_sister.S
new file mode 100644
index 0000000000..ea14b11ede
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmSisterEnd)
+SYMBOL(artMterpAsmSisterEnd):
diff --git a/runtime/interpreter/mterp/x86/instruction_start.S b/runtime/interpreter/mterp/x86/instruction_start.S
new file mode 100644
index 0000000000..ca711de00c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global SYMBOL(artMterpAsmInstructionStart)
+SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/x86/instruction_start_alt.S b/runtime/interpreter/mterp/x86/instruction_start_alt.S
new file mode 100644
index 0000000000..9272a6a7b0
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global SYMBOL(artMterpAsmAltInstructionStart)
+ .text
+SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
diff --git a/runtime/interpreter/mterp/x86/instruction_start_sister.S b/runtime/interpreter/mterp/x86/instruction_start_sister.S
new file mode 100644
index 0000000000..b9ac994d32
--- /dev/null
+++ b/runtime/interpreter/mterp/x86/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global SYMBOL(artMterpAsmSisterStart)
+ .text
+ .balign 4
+SYMBOL(artMterpAsmSisterStart):
diff --git a/runtime/interpreter/mterp/x86_64/entry.S b/runtime/interpreter/mterp/x86_64/entry.S
index 2f69226206..b08419b219 100644
--- a/runtime/interpreter/mterp/x86_64/entry.S
+++ b/runtime/interpreter/mterp/x86_64/entry.S
@@ -18,6 +18,7 @@
*/
.text
+ ASM_HIDDEN SYMBOL(ExecuteMterpImpl)
.global SYMBOL(ExecuteMterpImpl)
FUNCTION_TYPE(ExecuteMterpImpl)
diff --git a/runtime/interpreter/mterp/x86_64/header.S b/runtime/interpreter/mterp/x86_64/header.S
index 55638106ed..4ebe95e987 100644
--- a/runtime/interpreter/mterp/x86_64/header.S
+++ b/runtime/interpreter/mterp/x86_64/header.S
@@ -95,11 +95,13 @@ unspecified registers or condition codes.
#define SIZE(start,end)
// Mac OS' symbols have an _ prefix.
#define SYMBOL(name) _ ## name
+ #define ASM_HIDDEN .private_extern
#else
#define MACRO_LITERAL(value) $$value
#define FUNCTION_TYPE(name) .type name, @function
#define SIZE(start,end) .size start, .-end
#define SYMBOL(name) name
+ #define ASM_HIDDEN .hidden
#endif
.macro PUSH _reg
diff --git a/runtime/interpreter/mterp/x86_64/instruction_end.S b/runtime/interpreter/mterp/x86_64/instruction_end.S
new file mode 100644
index 0000000000..3a02a212e6
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_end.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmInstructionEnd)
+SYMBOL(artMterpAsmInstructionEnd):
diff --git a/runtime/interpreter/mterp/x86_64/instruction_end_alt.S b/runtime/interpreter/mterp/x86_64/instruction_end_alt.S
new file mode 100644
index 0000000000..33c2b8e2a0
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_end_alt.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmAltInstructionEnd)
+SYMBOL(artMterpAsmAltInstructionEnd):
diff --git a/runtime/interpreter/mterp/x86_64/instruction_end_sister.S b/runtime/interpreter/mterp/x86_64/instruction_end_sister.S
new file mode 100644
index 0000000000..ea14b11ede
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_end_sister.S
@@ -0,0 +1,3 @@
+
+ .global SYMBOL(artMterpAsmSisterEnd)
+SYMBOL(artMterpAsmSisterEnd):
diff --git a/runtime/interpreter/mterp/x86_64/instruction_start.S b/runtime/interpreter/mterp/x86_64/instruction_start.S
new file mode 100644
index 0000000000..ca711de00c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_start.S
@@ -0,0 +1,4 @@
+
+ .global SYMBOL(artMterpAsmInstructionStart)
+SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
+ .text
diff --git a/runtime/interpreter/mterp/x86_64/instruction_start_alt.S b/runtime/interpreter/mterp/x86_64/instruction_start_alt.S
new file mode 100644
index 0000000000..9272a6a7b0
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_start_alt.S
@@ -0,0 +1,4 @@
+
+ .global SYMBOL(artMterpAsmAltInstructionStart)
+ .text
+SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
diff --git a/runtime/interpreter/mterp/x86_64/instruction_start_sister.S b/runtime/interpreter/mterp/x86_64/instruction_start_sister.S
new file mode 100644
index 0000000000..b9ac994d32
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/instruction_start_sister.S
@@ -0,0 +1,5 @@
+
+ .global SYMBOL(artMterpAsmSisterStart)
+ .text
+ .balign 4
+SYMBOL(artMterpAsmSisterStart):
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 7abb007838..667bd03c18 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1691,7 +1691,7 @@ void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class =
- runtime->GetClassLinker()->FindArrayClass(self, &element_class);
+ runtime->GetClassLinker()->FindArrayClass(self, element_class);
DCHECK(array_class != nullptr);
gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
result->SetL(mirror::Array::Alloc<true, true>(self,
@@ -1818,13 +1818,13 @@ void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(
ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
- ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, &element_class);
+ ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, element_class);
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return;
}
DCHECK(array_class->IsObjectArrayClass());
- mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+ ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
result->SetL(new_array);
}
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 860de2c28b..655713e8c6 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -23,6 +23,7 @@
#include "base/enums.h"
#include "base/memory_tool.h"
#include "class_linker.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "dex/descriptors_names.h"
#include "dex/dex_instruction.h"
@@ -90,7 +91,7 @@ class UnstartedRuntimeTest : public CommonRuntimeTest {
REQUIRES_SHARED(Locks::mutator_lock_) {
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_type =
- runtime->GetClassLinker()->FindArrayClass(self, &component_type);
+ runtime->GetClassLinker()->FindArrayClass(self, component_type);
CHECK(array_type != nullptr);
ObjPtr<mirror::ObjectArray<mirror::Object>> result =
mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
@@ -195,7 +196,7 @@ class UnstartedRuntimeTest : public CommonRuntimeTest {
// Prepare for aborts. Aborts assume that the exception class is already resolved, as the
// loading code doesn't work under transactions.
void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Object* result = Runtime::Current()->GetClassLinker()->FindClass(
+ ObjPtr<mirror::Object> result = Runtime::Current()->GetClassLinker()->FindClass(
Thread::Current(),
Transaction::kAbortExceptionSignature,
ScopedNullHandle<mirror::ClassLoader>());
@@ -387,7 +388,7 @@ TEST_F(UnstartedRuntimeTest, StringCharAt) {
TEST_F(UnstartedRuntimeTest, StringInit) {
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
- ObjPtr<mirror::Class> klass = mirror::String::GetJavaLangString();
+ ObjPtr<mirror::Class> klass = GetClassRoot<mirror::String>();
ArtMethod* method =
klass->FindConstructor("(Ljava/lang/String;)V",
Runtime::Current()->GetClassLinker()->GetImagePointerSize());
@@ -447,8 +448,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
// Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
// allocate.
StackHandleScope<3> hs_misc(self);
- Handle<mirror::Class> object_class(
- hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
+ Handle<mirror::Class> object_class(hs_misc.NewHandle(GetClassRoot<mirror::Object>()));
StackHandleScope<3> hs_data(self);
hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
@@ -480,8 +480,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
StackHandleScope<1> hs_object(self);
- Handle<mirror::Class> object_class(
- hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
+ Handle<mirror::Class> object_class(hs_object.NewHandle(GetClassRoot<mirror::Object>()));
// Simple test:
// [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
@@ -536,7 +535,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
tmp,
false,
object_class.Get(),
- mirror::String::GetJavaLangString(),
+ GetClassRoot<mirror::String>(),
hs_src,
1,
hs_dst,
@@ -550,7 +549,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
{
StackHandleScope<3> hs_src(self);
hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
- hs_src.NewHandle(mirror::String::GetJavaLangString());
+ hs_src.NewHandle(GetClassRoot<mirror::String>());
hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
StackHandleScope<3> hs_dst(self);
@@ -567,7 +566,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
tmp,
true,
object_class.Get(),
- mirror::String::GetJavaLangString(),
+ GetClassRoot<mirror::String>(),
hs_src,
0,
hs_dst,
@@ -901,7 +900,7 @@ TEST_F(UnstartedRuntimeTest, IsAnonymousClass) {
JValue result;
ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
- ObjPtr<mirror::Class> class_klass = mirror::Class::GetJavaLangClass();
+ ObjPtr<mirror::Class> class_klass = GetClassRoot<mirror::Class>();
shadow_frame->SetVRegReference(0, class_klass);
UnstartedClassIsAnonymousClass(self, shadow_frame, &result, 0);
EXPECT_EQ(result.GetZ(), 0);
@@ -995,7 +994,7 @@ TEST_F(UnstartedRuntimeTest, ThreadLocalGet) {
{
// Just use a method in Class.
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
+ ObjPtr<mirror::Class> class_class = GetClassRoot<mirror::Class>();
ArtMethod* caller_method =
&*class_class->GetDeclaredMethods(class_linker->GetImagePointerSize()).begin();
ShadowFrame* caller_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, caller_method, 0);
@@ -1110,7 +1109,7 @@ class UnstartedClassForNameTest : public UnstartedRuntimeTest {
{
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(self);
- Handle<mirror::Class> h_class = hs.NewHandle(mirror::Class::GetJavaLangClass());
+ Handle<mirror::Class> h_class = hs.NewHandle(GetClassRoot<mirror::Class>());
CHECK(class_linker->EnsureInitialized(self, h_class, true, true));
}
@@ -1347,7 +1346,7 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
// Get Throwable.
- Handle<mirror::Class> throw_class = hs.NewHandle(mirror::Throwable::GetJavaLangThrowable());
+ Handle<mirror::Class> throw_class = hs.NewHandle(GetClassRoot<mirror::Throwable>());
ASSERT_TRUE(class_linker->EnsureInitialized(self, throw_class, true, true));
// Get an input object.
@@ -1370,7 +1369,7 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle(
mirror::ObjectArray<mirror::Object>::Alloc(
- self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), 1));
+ self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker_), 1));
ASSERT_TRUE(args != nullptr);
args->Set(0, input.Get());
@@ -1386,8 +1385,8 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
// Should be a new object.
ASSERT_NE(result.GetL(), input.Get());
- // Should be a String.
- ASSERT_EQ(mirror::Throwable::GetJavaLangThrowable(), result.GetL()->GetClass());
+ // Should be of type Throwable.
+ ASSERT_OBJ_PTR_EQ(GetClassRoot<mirror::Throwable>(), result.GetL()->GetClass());
// Should have the right string.
ObjPtr<mirror::String> result_msg =
reinterpret_cast<mirror::Throwable*>(result.GetL())->GetDetailMessage();
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5d4b9e8cc9..b7b779ce31 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -24,6 +24,7 @@
#include "base/memory_tool.h"
#include "base/runtime_debug.h"
#include "base/utils.h"
+#include "class_root.h"
#include "debugger.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "interpreter/interpreter.h"
@@ -514,8 +515,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
// this dex pc.
} else {
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind location =
- vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
+ DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
if (location == DexRegisterLocation::Kind::kNone) {
// Dex register is dead or uninitialized.
continue;
@@ -529,9 +529,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
DCHECK_EQ(location, DexRegisterLocation::Kind::kInStack);
int32_t vreg_value = shadow_frame->GetVReg(vreg);
- int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg,
- number_of_vregs,
- code_info);
+ int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg);
DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
DCHECK_GT(slot_offset, 0);
(reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
@@ -632,7 +630,8 @@ static bool IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mut
}
if (method->IsNative()) {
ObjPtr<mirror::Class> klass = method->GetDeclaringClass();
- if (klass == mirror::MethodHandle::StaticClass() || klass == mirror::VarHandle::StaticClass()) {
+ if (klass == GetClassRoot<mirror::MethodHandle>() ||
+ klass == GetClassRoot<mirror::VarHandle>()) {
// MethodHandle and VarHandle invocation methods are required to throw an
// UnsupportedOperationException if invoked reflectively. We achieve this by having native
// implementations that arise the exception. We need to disable JIT compilation of these JNI
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index d8aa00c45e..b010650345 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -471,7 +471,7 @@ static void FillRootTable(uint8_t* roots_data, Handle<mirror::ObjectArray<mirror
if (kIsDebugBuild) {
// Ensure the string is strongly interned. b/32995596
if (object->IsString()) {
- ObjPtr<mirror::String> str = reinterpret_cast<mirror::String*>(object.Ptr());
+ ObjPtr<mirror::String> str = ObjPtr<mirror::String>::DownCast(object);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
CHECK(class_linker->GetInternTable()->LookupStrong(Thread::Current(), str) != nullptr);
}
diff --git a/runtime/jit/profiling_info_test.cc b/runtime/jit/profiling_info_test.cc
new file mode 100644
index 0000000000..106a80a568
--- /dev/null
+++ b/runtime/jit/profiling_info_test.cc
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <stdio.h>
+
+#include "art_method-inl.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker-inl.h"
+#include "common_runtime_test.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "dex/method_reference.h"
+#include "dex/type_reference.h"
+#include "handle_scope-inl.h"
+#include "linear_alloc.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
+#include "profile/profile_compilation_info.h"
+#include "scoped_thread_state_change-inl.h"
+#include "ziparchive/zip_writer.h"
+
+namespace art {
+
+using Hotness = ProfileCompilationInfo::MethodHotness;
+
+static constexpr size_t kMaxMethodIds = 65535;
+
+class ProfileCompilationInfoTest : public CommonRuntimeTest {
+ public:
+ void PostRuntimeCreate() OVERRIDE {
+ allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
+ }
+
+ protected:
+ std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader,
+ const std::string& clazz) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ClassLoader> h_loader(
+ hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader()));
+ ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
+
+ const auto pointer_size = class_linker->GetImagePointerSize();
+ std::vector<ArtMethod*> methods;
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+ methods.push_back(&m);
+ }
+ return methods;
+ }
+
+ bool AddMethod(const std::string& dex_location,
+ uint32_t checksum,
+ uint16_t method_index,
+ ProfileCompilationInfo* info) {
+ return info->AddMethodIndex(Hotness::kFlagHot,
+ dex_location,
+ checksum,
+ method_index,
+ kMaxMethodIds);
+ }
+
+ bool AddMethod(const std::string& dex_location,
+ uint32_t checksum,
+ uint16_t method_index,
+ const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi,
+ ProfileCompilationInfo* info) {
+ return info->AddMethod(
+ dex_location, checksum, method_index, kMaxMethodIds, pmi, Hotness::kFlagPostStartup);
+ }
+
+ bool AddClass(const std::string& dex_location,
+ uint32_t checksum,
+ dex::TypeIndex type_index,
+ ProfileCompilationInfo* info) {
+ DexCacheResolvedClasses classes(dex_location, dex_location, checksum, kMaxMethodIds);
+ classes.AddClass(type_index);
+ return info->AddClasses({classes});
+ }
+
+ uint32_t GetFd(const ScratchFile& file) {
+ return static_cast<uint32_t>(file.GetFd());
+ }
+
+ bool SaveProfilingInfo(
+ const std::string& filename,
+ const std::vector<ArtMethod*>& methods,
+ const std::set<DexCacheResolvedClasses>& resolved_classes,
+ Hotness::Flag flags) {
+ ProfileCompilationInfo info;
+ std::vector<ProfileMethodInfo> profile_methods;
+ ScopedObjectAccess soa(Thread::Current());
+ for (ArtMethod* method : methods) {
+ profile_methods.emplace_back(
+ MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
+ }
+ if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) {
+ return false;
+ }
+ if (info.GetNumberOfMethods() != profile_methods.size()) {
+ return false;
+ }
+ ProfileCompilationInfo file_profile;
+ if (!file_profile.Load(filename, false)) {
+ return false;
+ }
+ if (!info.MergeWith(file_profile)) {
+ return false;
+ }
+
+ return info.Save(filename, nullptr);
+ }
+
+ // Saves the given art methods to a profile backed by 'filename' and adds
+ // some fake inline caches to it. The added inline caches are returned in
+ // the out map `profile_methods_map`.
+ bool SaveProfilingInfoWithFakeInlineCaches(
+ const std::string& filename,
+ const std::vector<ArtMethod*>& methods,
+ Hotness::Flag flags,
+ /*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) {
+ ProfileCompilationInfo info;
+ std::vector<ProfileMethodInfo> profile_methods;
+ ScopedObjectAccess soa(Thread::Current());
+ for (ArtMethod* method : methods) {
+ std::vector<ProfileMethodInfo::ProfileInlineCache> caches;
+ // Monomorphic
+ for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
+ std::vector<TypeReference> classes;
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(0));
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Polymorphic
+ for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
+ std::vector<TypeReference> classes;
+ for (uint16_t k = 0; k < InlineCache::kIndividualCacheSize / 2; k++) {
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
+ }
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Megamorphic
+ for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
+ std::vector<TypeReference> classes;
+ for (uint16_t k = 0; k < 2 * InlineCache::kIndividualCacheSize; k++) {
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
+ }
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Missing types
+ for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
+ std::vector<TypeReference> classes;
+ caches.emplace_back(dex_pc, /*is_missing_types*/true, classes);
+ }
+ ProfileMethodInfo pmi(MethodReference(method->GetDexFile(),
+ method->GetDexMethodIndex()),
+ caches);
+ profile_methods.push_back(pmi);
+ profile_methods_map->Put(method, pmi);
+ }
+
+ if (!info.AddMethods(profile_methods, flags)
+ || info.GetNumberOfMethods() != profile_methods.size()) {
+ return false;
+ }
+ return info.Save(filename, nullptr);
+ }
+
+ // Creates an inline cache which will be destructed at the end of the test.
+ ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
+ used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
+ std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)));
+ return used_inline_caches.back().get();
+ }
+
+ ProfileCompilationInfo::OfflineProfileMethodInfo ConvertProfileMethodInfo(
+ const ProfileMethodInfo& pmi) {
+ ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
+ ProfileCompilationInfo::OfflineProfileMethodInfo offline_pmi(ic_map);
+ SafeMap<DexFile*, uint8_t> dex_map; // dex files to profile index
+ for (const auto& inline_cache : pmi.inline_caches) {
+ ProfileCompilationInfo::DexPcData& dex_pc_data =
+ ic_map->FindOrAdd(
+ inline_cache.dex_pc, ProfileCompilationInfo::DexPcData(allocator_.get()))->second;
+ if (inline_cache.is_missing_types) {
+ dex_pc_data.SetIsMissingTypes();
+ }
+ for (const auto& class_ref : inline_cache.classes) {
+ uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file),
+ static_cast<uint8_t>(dex_map.size()))->second;
+ dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex());
+ if (dex_profile_index >= offline_pmi.dex_references.size()) {
+ // This is a new dex.
+ const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey(
+ class_ref.dex_file->GetLocation());
+ offline_pmi.dex_references.emplace_back(dex_key,
+ class_ref.dex_file->GetLocationChecksum(),
+ class_ref.dex_file->NumMethodIds());
+ }
+ }
+ }
+ return offline_pmi;
+ }
+
+ // Cannot sizeof the actual arrays so hard code the values here.
+ // They should not change anyway.
+ static constexpr int kProfileMagicSize = 4;
+ static constexpr int kProfileVersionSize = 4;
+
+ std::unique_ptr<ArenaAllocator> allocator_;
+
+ // Cache of inline caches generated during tests.
+ // This makes it easier to pass data between different utilities and ensure that
+ // caches are destructed at the end of the test.
+ std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
+};
+
+TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
+ ScratchFile profile;
+
+ Thread* self = Thread::Current();
+ jobject class_loader;
+ {
+ ScopedObjectAccess soa(self);
+ class_loader = LoadDex("ProfileTestMultiDex");
+ }
+ ASSERT_NE(class_loader, nullptr);
+
+ // Save virtual methods from Main.
+ std::set<DexCacheResolvedClasses> resolved_classes;
+ std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup));
+
+ // Check that what we saved is in the profile.
+ ProfileCompilationInfo info1;
+ ASSERT_TRUE(info1.Load(GetFd(profile)));
+ ASSERT_EQ(info1.GetNumberOfMethods(), main_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
+ }
+ }
+
+ // Save virtual methods from Second.
+ std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup));
+
+ // Check that what we saved is in the profile (methods form Main and Second).
+ ProfileCompilationInfo info2;
+ ASSERT_TRUE(profile.GetFile()->ResetOffset());
+ ASSERT_TRUE(info2.Load(GetFd(profile)));
+ ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
+ }
+ for (ArtMethod* m : second_methods) {
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
+ }
+ }
+}
+
+TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
+ ScratchFile profile;
+
+ Thread* self = Thread::Current();
+ jobject class_loader;
+ {
+ ScopedObjectAccess soa(self);
+ class_loader = LoadDex("ProfileTestMultiDex");
+ }
+ ASSERT_NE(class_loader, nullptr);
+
+ // Save virtual methods from Main.
+ std::set<DexCacheResolvedClasses> resolved_classes;
+ std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
+
+ SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map;
+ ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches(
+ profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map));
+
+ // Check that what we saved is in the profile.
+ ProfileCompilationInfo info;
+ ASSERT_TRUE(info.Load(GetFd(profile)));
+ ASSERT_EQ(info.GetNumberOfMethods(), main_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
+ const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
+ std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
+ info.GetMethod(m->GetDexFile()->GetLocation(),
+ m->GetDexFile()->GetLocationChecksum(),
+ m->GetDexMethodIndex());
+ ASSERT_TRUE(offline_pmi != nullptr);
+ ProfileCompilationInfo::OfflineProfileMethodInfo converted_pmi =
+ ConvertProfileMethodInfo(pmi);
+ ASSERT_EQ(converted_pmi, *offline_pmi);
+ }
+ }
+}
+
+} // namespace art
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index cd66a60376..7290d638f3 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -33,6 +33,7 @@
#include "base/safe_map.h"
#include "base/stl_util.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "dex/dex_file-inl.h"
#include "dex/utf.h"
#include "fault_handler.h"
@@ -305,7 +306,7 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con
return nullptr;
}
ArtField* field = nullptr;
- mirror::Class* field_type;
+ ObjPtr<mirror::Class> field_type;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (sig[1] != '\0') {
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(c->GetClassLoader()));
@@ -346,8 +347,11 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con
return jni::EncodeArtField(field);
}
-static void ThrowAIOOBE(ScopedObjectAccess& soa, mirror::Array* array, jsize start,
- jsize length, const char* identifier)
+static void ThrowAIOOBE(ScopedObjectAccess& soa,
+ ObjPtr<mirror::Array> array,
+ jsize start,
+ jsize length,
+ const char* identifier)
REQUIRES_SHARED(Locks::mutator_lock_) {
std::string type(array->PrettyTypeOf());
soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
@@ -434,7 +438,9 @@ static JavaVMExt* JavaVmExtFromEnv(JNIEnv* env) {
}
template <bool kNative>
-static ArtMethod* FindMethod(mirror::Class* c, const StringPiece& name, const StringPiece& sig)
+static ArtMethod* FindMethod(ObjPtr<mirror::Class> c,
+ const StringPiece& name,
+ const StringPiece& sig)
REQUIRES_SHARED(Locks::mutator_lock_) {
auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
for (auto& method : c->GetMethods(pointer_size)) {
@@ -462,7 +468,7 @@ class JNI {
ClassLinker* class_linker = runtime->GetClassLinker();
std::string descriptor(NormalizeJniClassDescriptor(name));
ScopedObjectAccess soa(env);
- mirror::Class* c = nullptr;
+ ObjPtr<mirror::Class> c = nullptr;
if (runtime->IsStarted()) {
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
@@ -483,7 +489,7 @@ class JNI {
CHECK_NON_NULL_ARGUMENT(jlr_field);
ScopedObjectAccess soa(env);
ObjPtr<mirror::Object> obj_field = soa.Decode<mirror::Object>(jlr_field);
- if (obj_field->GetClass() != mirror::Field::StaticClass()) {
+ if (obj_field->GetClass() != GetClassRoot<mirror::Field>()) {
// Not even a java.lang.reflect.Field, return null. TODO, is this check necessary?
return nullptr;
}
@@ -608,7 +614,7 @@ class JNI {
static jthrowable ExceptionOccurred(JNIEnv* env) {
ScopedObjectAccess soa(env);
- mirror::Object* exception = soa.Self()->GetException();
+ ObjPtr<mirror::Object> exception = soa.Self()->GetException();
return soa.AddLocalReference<jthrowable>(exception);
}
@@ -1979,7 +1985,7 @@ class JNI {
ObjPtr<mirror::ObjectArray<mirror::Object>> array =
soa.Decode<mirror::ObjectArray<mirror::Object>>(java_array);
ObjPtr<mirror::Object> value = soa.Decode<mirror::Object>(java_value);
- array->Set<false>(index, value.Ptr());
+ array->Set<false>(index, value);
}
static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
@@ -2022,7 +2028,7 @@ class JNI {
ScopedObjectAccess soa(env);
ObjPtr<mirror::Class> array_class;
{
- ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(element_jclass).Ptr();
+ ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(element_jclass);
if (UNLIKELY(element_class->IsPrimitive())) {
soa.Vm()->JniAbortF("NewObjectArray",
"not an object type: %s",
@@ -2030,19 +2036,19 @@ class JNI {
return nullptr;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+ array_class = class_linker->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
}
// Allocate and initialize if necessary.
- mirror::ObjectArray<mirror::Object>* result =
+ ObjPtr<mirror::ObjectArray<mirror::Object>> result =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), array_class, length);
if (result != nullptr && initial_element != nullptr) {
ObjPtr<mirror::Object> initial_object = soa.Decode<mirror::Object>(initial_element);
if (initial_object != nullptr) {
- mirror::Class* element_class = result->GetClass()->GetComponentType();
+ ObjPtr<mirror::Class> element_class = result->GetClass()->GetComponentType();
if (UNLIKELY(!element_class->IsAssignableFrom(initial_object->GetClass()))) {
soa.Vm()->JniAbortF("NewObjectArray", "cannot assign object of type '%s' to array with "
"element type of '%s'",
@@ -2051,7 +2057,7 @@ class JNI {
return nullptr;
} else {
for (jsize i = 0; i < length; ++i) {
- result->SetWithoutChecks<false>(i, initial_object.Ptr());
+ result->SetWithoutChecks<false>(i, initial_object);
}
}
}
@@ -2101,7 +2107,7 @@ class JNI {
return;
}
const size_t component_size = array->GetClass()->GetComponentSize();
- ReleasePrimitiveArray(soa, array.Ptr(), component_size, elements, mode);
+ ReleasePrimitiveArray(soa, array, component_size, elements, mode);
}
static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
@@ -2338,13 +2344,13 @@ class JNI {
current_class != nullptr;
current_class = current_class->GetSuperClass()) {
// Search first only comparing methods which are native.
- m = FindMethod<true>(current_class.Ptr(), name, sig);
+ m = FindMethod<true>(current_class, name, sig);
if (m != nullptr) {
break;
}
// Search again comparing to all methods, to find non-native methods that match.
- m = FindMethod<false>(current_class.Ptr(), name, sig);
+ m = FindMethod<false>(current_class, name, sig);
if (m != nullptr) {
break;
}
@@ -2542,35 +2548,37 @@ class JNI {
soa.Vm()->JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
return nullptr;
}
- ArtT* result = ArtT::Alloc(soa.Self(), length);
+ ObjPtr<ArtT> result = ArtT::Alloc(soa.Self(), length);
return soa.AddLocalReference<JniT>(result);
}
template <typename JArrayT, typename ElementT, typename ArtArrayT>
- static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array,
- const char* fn_name, const char* operation)
+ static ObjPtr<ArtArrayT> DecodeAndCheckArrayType(ScopedObjectAccess& soa,
+ JArrayT java_array,
+ const char* fn_name,
+ const char* operation)
REQUIRES_SHARED(Locks::mutator_lock_) {
ObjPtr<ArtArrayT> array = soa.Decode<ArtArrayT>(java_array);
- if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) {
+ ObjPtr<mirror::Class> expected_array_class = GetClassRoot<ArtArrayT>();
+ if (UNLIKELY(expected_array_class != array->GetClass())) {
soa.Vm()->JniAbortF(fn_name,
"attempt to %s %s primitive array elements with an object of type %s",
operation,
mirror::Class::PrettyDescriptor(
- ArtArrayT::GetArrayClass()->GetComponentType()).c_str(),
+ expected_array_class->GetComponentType()).c_str(),
mirror::Class::PrettyDescriptor(array->GetClass()).c_str());
return nullptr;
}
DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize());
- return array.Ptr();
+ return array;
}
template <typename ArrayT, typename ElementT, typename ArtArrayT>
static ElementT* GetPrimitiveArray(JNIEnv* env, ArrayT java_array, jboolean* is_copy) {
CHECK_NON_NULL_ARGUMENT(java_array);
ScopedObjectAccess soa(env);
- ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
- "GetArrayElements",
- "get");
+ ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(
+ soa, java_array, "GetArrayElements", "get");
if (UNLIKELY(array == nullptr)) {
return nullptr;
}
@@ -2596,17 +2604,19 @@ class JNI {
static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, ElementT* elements, jint mode) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
- "ReleaseArrayElements",
- "release");
+ ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(
+ soa, java_array, "ReleaseArrayElements", "release");
if (array == nullptr) {
return;
}
ReleasePrimitiveArray(soa, array, sizeof(ElementT), elements, mode);
}
- static void ReleasePrimitiveArray(ScopedObjectAccess& soa, mirror::Array* array,
- size_t component_size, void* elements, jint mode)
+ static void ReleasePrimitiveArray(ScopedObjectAccess& soa,
+ ObjPtr<mirror::Array> array,
+ size_t component_size,
+ void* elements,
+ jint mode)
REQUIRES_SHARED(Locks::mutator_lock_) {
void* array_data = array->GetRawData(component_size, 0);
gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -2649,10 +2659,8 @@ class JNI {
jsize start, jsize length, ElementT* buf) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- ArtArrayT* array =
- DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
- "GetPrimitiveArrayRegion",
- "get region of");
+ ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(
+ soa, java_array, "GetPrimitiveArrayRegion", "get region of");
if (array != nullptr) {
if (start < 0 || length < 0 || length > array->GetLength() - start) {
ThrowAIOOBE(soa, array, start, length, "src");
@@ -2669,10 +2677,8 @@ class JNI {
jsize start, jsize length, const ElementT* buf) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- ArtArrayT* array =
- DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
- "SetPrimitiveArrayRegion",
- "set region of");
+ ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(
+ soa, java_array, "SetPrimitiveArrayRegion", "set region of");
if (array != nullptr) {
if (start < 0 || length < 0 || length > array->GetLength() - start) {
ThrowAIOOBE(soa, array, start, length, "dst");
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 27de72533c..01a32a2288 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -18,6 +18,7 @@
#include "android-base/stringprintf.h"
+#include "class_root.h"
#include "common_dex_operations.h"
#include "interpreter/shadow_frame-inl.h"
#include "jvalue-inl.h"
@@ -267,7 +268,7 @@ bool ConvertJValueCommon(
// Then perform the actual boxing, and then set the reference.
ObjPtr<mirror::Object> boxed = BoxPrimitive(type, src_value);
- value->SetL(boxed.Ptr());
+ value->SetL(boxed);
return true;
} else {
// The source type is a reference and the target type is a primitive, so we must unbox.
@@ -322,7 +323,7 @@ inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame,
// Note: As an optimization, non-moving collectors leave a stale reference value
// in the references array even after the original vreg was overwritten to a non-reference.
if (src_value == reinterpret_cast<uintptr_t>(o.Ptr())) {
- callee_frame->SetVRegReference(dst_reg, o.Ptr());
+ callee_frame->SetVRegReference(dst_reg, o);
} else {
callee_frame->SetVReg(dst_reg, src_value);
}
@@ -1022,7 +1023,7 @@ bool DoVarHandleInvokeTranslation(Thread* self,
// Check that the first parameter is a VarHandle
if (callsite_ptypes->GetLength() < 1 ||
!mh_ptypes->Get(0)->IsAssignableFrom(callsite_ptypes->Get(0)) ||
- mh_ptypes->Get(0) != mirror::VarHandle::StaticClass()) {
+ mh_ptypes->Get(0) != GetClassRoot<mirror::VarHandle>()) {
ThrowWrongMethodTypeException(method_handle->GetMethodType(), callsite_type.Get());
return false;
}
@@ -1036,7 +1037,7 @@ bool DoVarHandleInvokeTranslation(Thread* self,
// Cast to VarHandle instance
Handle<mirror::VarHandle> vh(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver)));
- DCHECK(mirror::VarHandle::StaticClass()->IsAssignableFrom(vh->GetClass()));
+ DCHECK(GetClassRoot<mirror::VarHandle>()->IsAssignableFrom(vh->GetClass()));
// Determine the accessor kind to dispatch
ArtMethod* target_method = method_handle->GetTargetMethod();
diff --git a/runtime/method_handles_test.cc b/runtime/method_handles_test.cc
index a9473421cb..d123754e47 100644
--- a/runtime/method_handles_test.cc
+++ b/runtime/method_handles_test.cc
@@ -17,6 +17,7 @@
#include "method_handles.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "jvalue-inl.h"
@@ -49,12 +50,11 @@ namespace {
REQUIRES_SHARED(Locks::mutator_lock_) {
ClassLinker* cl = Runtime::Current()->GetClassLinker();
StackHandleScope<2> hs(self);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> class_array_type = cl->FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> class_array_type = GetClassRoot<mirror::ObjectArray<mirror::Class>>(cl);
auto parameter_types = hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, 1));
parameter_types->Set(0, parameter_type.Get());
- Handle<mirror::Class> void_class = hs.NewHandle(cl->FindPrimitiveClass('V'));
+ Handle<mirror::Class> void_class = hs.NewHandle(GetClassRoot(ClassRoot::kPrimitiveVoid, cl));
return mirror::MethodType::Create(self, void_class, parameter_types);
}
@@ -179,7 +179,7 @@ TEST_F(MethodHandlesTest, SupportedReferenceCast) {
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
value.SetL(boxed_value.Get());
@@ -195,8 +195,7 @@ TEST_F(MethodHandlesTest, UnsupportedReferenceCast) {
ClassLinker* cl = Runtime::Current()->GetClassLinker();
StackHandleScope<3> hs(soa.Self());
JValue value = JValue::FromPrimitive(3.733e2);
- Handle<mirror::Object> boxed_value =
- hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
value.SetL(boxed_value.Get());
@@ -293,7 +292,7 @@ TEST_F(MethodHandlesTest, SupportedBoxedToPrimitiveConversion) {
StackHandleScope<3> hs(soa.Self());
const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
value.SetL(boxed_value.Get());
@@ -308,7 +307,7 @@ TEST_F(MethodHandlesTest, SupportedBoxedToWiderPrimitiveConversion) {
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
value.SetL(boxed_value.Get());
@@ -352,7 +351,7 @@ TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionNoCast) {
StackHandleScope<3> hs(soa.Self());
static const int32_t kInitialValue = 101;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('S'));
value.SetL(boxed_value.Get());
@@ -368,8 +367,7 @@ TEST_F(MethodHandlesTest, UnsupportedBoxedToNarrowerPrimitiveConversionWithCast)
StackHandleScope<3> hs(soa.Self());
static const double kInitialValue = 1e77;
JValue value = JValue::FromPrimitive(kInitialValue);
- Handle<mirror::Object> boxed_value =
- hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+ Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F'));
value.SetL(boxed_value.Get());
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 636c84c759..2e395302af 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -151,11 +151,11 @@ class SetLengthToUsableSizeVisitor {
};
template <bool kIsInstrumented, bool kFillUsable>
-inline Array* Array::Alloc(Thread* self,
- ObjPtr<Class> array_class,
- int32_t component_count,
- size_t component_size_shift,
- gc::AllocatorType allocator_type) {
+inline ObjPtr<Array> Array::Alloc(Thread* self,
+ ObjPtr<Class> array_class,
+ int32_t component_count,
+ size_t component_size_shift,
+ gc::AllocatorType allocator_type) {
DCHECK(allocator_type != gc::kAllocatorTypeLOS);
DCHECK(array_class != nullptr);
DCHECK(array_class->IsArrayClass());
@@ -175,19 +175,19 @@ inline Array* Array::Alloc(Thread* self,
}
#endif
gc::Heap* heap = Runtime::Current()->GetHeap();
- Array* result;
+ ObjPtr<Array> result;
if (!kFillUsable) {
SetLengthVisitor visitor(component_count);
- result = down_cast<Array*>(
+ result = ObjPtr<Array>::DownCast(MakeObjPtr(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
- allocator_type, visitor));
+ allocator_type, visitor)));
} else {
SetLengthToUsableSizeVisitor visitor(component_count,
DataOffset(1U << component_size_shift).SizeValue(),
component_size_shift);
- result = down_cast<Array*>(
+ result = ObjPtr<Array>::DownCast(MakeObjPtr(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
- allocator_type, visitor));
+ allocator_type, visitor)));
}
if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
array_class = result->GetClass(); // In case the array class moved.
@@ -201,15 +201,10 @@ inline Array* Array::Alloc(Thread* self,
return result;
}
-template<class T>
-inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor) {
- array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
template<typename T>
-inline PrimitiveArray<T>* PrimitiveArray<T>::AllocateAndFill(Thread* self,
- const T* data,
- size_t length) {
+inline ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::AllocateAndFill(Thread* self,
+ const T* data,
+ size_t length) {
StackHandleScope<1> hs(self);
Handle<PrimitiveArray<T>> arr(hs.NewHandle(PrimitiveArray<T>::Alloc(self, length)));
if (!arr.IsNull()) {
@@ -220,16 +215,6 @@ inline PrimitiveArray<T>* PrimitiveArray<T>::AllocateAndFill(Thread* self,
}
template<typename T>
-inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
- Array* raw_array = Array::Alloc<true>(self,
- GetArrayClass(),
- length,
- ComponentSizeShiftWidth(sizeof(T)),
- Runtime::Current()->GetHeap()->GetCurrentAllocator());
- return down_cast<PrimitiveArray<T>*>(raw_array);
-}
-
-template<typename T>
inline T PrimitiveArray<T>::Get(int32_t i) {
if (!CheckIsValidIndex(i)) {
DCHECK(Thread::Current()->IsExceptionPending());
@@ -461,13 +446,6 @@ void PointerArray::Memcpy(int32_t dst_pos,
}
}
-template<typename T>
-inline void PrimitiveArray<T>::SetArrayClass(ObjPtr<Class> array_class) {
- CHECK(array_class_.IsNull());
- CHECK(array_class != nullptr);
- array_class_ = GcRoot<Class>(array_class);
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index ea202e766f..66ec368935 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -20,6 +20,7 @@
#include "class-inl.h"
#include "class.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
@@ -41,17 +42,18 @@ using android::base::StringPrintf;
// piece and work our way in.
// Recursively create an array with multiple dimensions. Elements may be
// Objects or primitive types.
-static Array* RecursiveCreateMultiArray(Thread* self,
- Handle<Class> array_class, int current_dimension,
- Handle<mirror::IntArray> dimensions)
+static ObjPtr<Array> RecursiveCreateMultiArray(Thread* self,
+ Handle<Class> array_class,
+ int current_dimension,
+ Handle<mirror::IntArray> dimensions)
REQUIRES_SHARED(Locks::mutator_lock_) {
int32_t array_length = dimensions->Get(current_dimension);
- StackHandleScope<1> hs(self);
- Handle<Array> new_array(
- hs.NewHandle(
- Array::Alloc<true>(self, array_class.Get(), array_length,
- array_class->GetComponentSizeShift(),
- Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType()));
+ size_t component_size_shift = h_component_type->GetPrimitiveTypeSizeShift();
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ Handle<Array> new_array(hs.NewHandle(Array::Alloc<true>(
+ self, array_class.Get(), array_length, component_size_shift, allocator_type)));
if (UNLIKELY(new_array == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -59,10 +61,8 @@ static Array* RecursiveCreateMultiArray(Thread* self,
if (current_dimension + 1 < dimensions->GetLength()) {
// Create a new sub-array in every element of the array.
for (int32_t i = 0; i < array_length; i++) {
- StackHandleScope<1> hs2(self);
- Handle<mirror::Class> h_component_type(hs2.NewHandle(array_class->GetComponentType()));
- ObjPtr<Array> sub_array = RecursiveCreateMultiArray(self, h_component_type,
- current_dimension + 1, dimensions);
+ ObjPtr<Array> sub_array =
+ RecursiveCreateMultiArray(self, h_component_type, current_dimension + 1, dimensions);
if (UNLIKELY(sub_array == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -74,8 +74,9 @@ static Array* RecursiveCreateMultiArray(Thread* self,
return new_array.Get();
}
-Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
- Handle<IntArray> dimensions) {
+ObjPtr<Array> Array::CreateMultiArray(Thread* self,
+ Handle<Class> element_class,
+ Handle<IntArray> dimensions) {
// Verify dimensions.
//
// The caller is responsible for verifying that "dimArray" is non-null
@@ -94,17 +95,15 @@ Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
// Find/generate the array class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> element_class_ptr = element_class.Get();
StackHandleScope<1> hs(self);
MutableHandle<mirror::Class> array_class(
- hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
+ hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
}
for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
- ObjPtr<mirror::Class> array_class_ptr = array_class.Get();
- array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
+ array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
if (UNLIKELY(array_class == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
@@ -118,6 +117,17 @@ Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
return new_array.Ptr();
}
+template<typename T>
+ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ ObjPtr<Array> raw_array = Array::Alloc<true>(self,
+ GetClassRoot<PrimitiveArray<T>>(),
+ length,
+ ComponentSizeShiftWidth(sizeof(T)),
+ allocator_type);
+ return ObjPtr<PrimitiveArray<T>>::DownCast(raw_array);
+}
+
void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
}
@@ -126,7 +136,7 @@ void Array::ThrowArrayStoreException(ObjPtr<Object> object) {
art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
}
-Array* Array::CopyOf(Thread* self, int32_t new_length) {
+ObjPtr<Array> Array::CopyOf(Thread* self, int32_t new_length) {
CHECK(GetClass()->GetComponentType()->IsPrimitive()) << "Will miss write barriers";
DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
@@ -137,7 +147,8 @@ Array* Array::CopyOf(Thread* self, int32_t new_length) {
heap->GetCurrentNonMovingAllocator();
const auto component_size = GetClass()->GetComponentSize();
const auto component_shift = GetClass()->GetComponentSizeShift();
- ObjPtr<Array> new_array = Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
+ ObjPtr<Array> new_array =
+ Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
if (LIKELY(new_array != nullptr)) {
memcpy(new_array->GetRawData(component_size, 0),
h_this->GetRawData(component_size, 0),
@@ -146,9 +157,6 @@ Array* Array::CopyOf(Thread* self, int32_t new_length) {
return new_array.Ptr();
}
-
-template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_;
-
// Explicitly instantiate all the primitive array types.
template class PrimitiveArray<uint8_t>; // BooleanArray
template class PrimitiveArray<int8_t>; // ByteArray
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 11128bb5a2..8bdd561ec4 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -19,7 +19,6 @@
#include "base/enums.h"
#include "gc/allocator_type.h"
-#include "gc_root.h"
#include "obj_ptr.h"
#include "object.h"
@@ -38,17 +37,17 @@ class MANAGED Array : public Object {
// least component_count size, however, if there's usable space at the end of the allocation the
// array will fill it.
template <bool kIsInstrumented, bool kFillUsable = false>
- ALWAYS_INLINE static Array* Alloc(Thread* self,
- ObjPtr<Class> array_class,
- int32_t component_count,
- size_t component_size_shift,
- gc::AllocatorType allocator_type)
+ ALWAYS_INLINE static ObjPtr<Array> Alloc(Thread* self,
+ ObjPtr<Class> array_class,
+ int32_t component_count,
+ size_t component_size_shift,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- static Array* CreateMultiArray(Thread* self,
- Handle<Class> element_class,
- Handle<IntArray> dimensions)
+ static ObjPtr<Array> CreateMultiArray(Thread* self,
+ Handle<Class> element_class,
+ Handle<IntArray> dimensions)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
@@ -91,7 +90,7 @@ class MANAGED Array : public Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
- Array* CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
+ ObjPtr<Array> CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
protected:
@@ -115,10 +114,10 @@ class MANAGED PrimitiveArray : public Array {
public:
typedef T ElementType;
- static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
+ static ObjPtr<PrimitiveArray<T>> Alloc(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static PrimitiveArray<T>* AllocateAndFill(Thread* self, const T* data, size_t length)
+ static ObjPtr<PrimitiveArray<T>> AllocateAndFill(Thread* self, const T* data, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
@@ -167,24 +166,7 @@ class MANAGED PrimitiveArray : public Array {
void Memcpy(int32_t dst_pos, ObjPtr<PrimitiveArray<T>> src, int32_t src_pos, int32_t count)
REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetArrayClass(ObjPtr<Class> array_class);
-
- template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- static Class* GetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!array_class_.IsNull());
- return array_class_.Read<kReadBarrierOption>();
- }
-
- static void ResetArrayClass() {
- CHECK(!array_class_.IsNull());
- array_class_ = GcRoot<Class>(nullptr);
- }
-
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- static GcRoot<Class> array_class_;
-
DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
};
diff --git a/runtime/mirror/call_site.cc b/runtime/mirror/call_site.cc
index eb613df4c6..738106c0e4 100644
--- a/runtime/mirror/call_site.cc
+++ b/runtime/mirror/call_site.cc
@@ -17,35 +17,18 @@
#include "call_site.h"
#include "class-inl.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
+#include "obj_ptr-inl.h"
namespace art {
namespace mirror {
-GcRoot<mirror::Class> CallSite::static_class_;
-
mirror::CallSite* CallSite::Create(Thread* const self, Handle<MethodHandle> target) {
- StackHandleScope<1> hs(self);
- Handle<mirror::CallSite> cs(
- hs.NewHandle(ObjPtr<CallSite>::DownCast(StaticClass()->AllocObject(self))));
+ ObjPtr<mirror::CallSite> cs =
+ ObjPtr<CallSite>::DownCast(GetClassRoot<CallSite>()->AllocObject(self));
CHECK(!Runtime::Current()->IsActiveTransaction());
cs->SetFieldObject<false>(TargetOffset(), target.Get());
- return cs.Get();
-}
-
-void CallSite::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void CallSite::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void CallSite::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+ return cs.Ptr();
}
} // namespace mirror
diff --git a/runtime/mirror/call_site.h b/runtime/mirror/call_site.h
index 93f274808c..9b6afca3aa 100644
--- a/runtime/mirror/call_site.h
+++ b/runtime/mirror/call_site.h
@@ -33,18 +33,10 @@ class MANAGED CallSite : public Object {
Handle<MethodHandle> method_handle)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
MethodHandle* GetTarget() REQUIRES_SHARED(Locks::mutator_lock_) {
return GetFieldObject<MethodHandle>(TargetOffset());
}
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
static inline MemberOffset TargetOffset() {
return MemberOffset(OFFSETOF_MEMBER(CallSite, target_));
@@ -52,8 +44,6 @@ class MANAGED CallSite : public Object {
HeapReference<mirror::MethodHandle> target_;
- static GcRoot<mirror::Class> static_class_; // java.lang.invoke.CallSite.class
-
friend struct art::CallSiteOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(CallSite);
};
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 72b31790f0..fffd7f3062 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -36,7 +36,6 @@
#include "object-inl.h"
#include "object_array.h"
#include "read_barrier-inl.h"
-#include "reference-inl.h"
#include "runtime.h"
#include "string.h"
@@ -146,6 +145,7 @@ inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(PointerSize
GetDirectMethodsStartOffset(),
GetCopiedMethodsStartOffset());
}
+
template<VerifyObjectFlags kVerifyFlags>
inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(PointerSize pointer_size) {
DCHECK(IsLoaded() || IsErroneous());
@@ -282,8 +282,7 @@ inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, PointerSize pointer
return &GetVirtualMethodsSliceUnchecked(pointer_size)[i];
}
-template<VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline PointerArray* Class::GetVTable() {
DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(
@@ -295,7 +294,7 @@ inline PointerArray* Class::GetVTableDuringLinking() {
return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
}
-inline void Class::SetVTable(PointerArray* new_vtable) {
+inline void Class::SetVTable(ObjPtr<PointerArray> new_vtable) {
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
}
@@ -303,8 +302,7 @@ inline bool Class::HasVTable() {
return GetVTable() != nullptr || ShouldHaveEmbeddedVTable();
}
- template<VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline int32_t Class::GetVTableLength() {
if (ShouldHaveEmbeddedVTable<kVerifyFlags, kReadBarrierOption>()) {
return GetEmbeddedVTableLength();
@@ -313,15 +311,15 @@ inline int32_t Class::GetVTableLength() {
GetVTable<kVerifyFlags, kReadBarrierOption>()->GetLength() : 0;
}
- template<VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ArtMethod* Class::GetVTableEntry(uint32_t i, PointerSize pointer_size) {
if (ShouldHaveEmbeddedVTable<kVerifyFlags, kReadBarrierOption>()) {
return GetEmbeddedVTableEntry(i, pointer_size);
}
auto* vtable = GetVTable<kVerifyFlags, kReadBarrierOption>();
DCHECK(vtable != nullptr);
- return vtable->template GetElementPtrSize<ArtMethod*, kVerifyFlags, kReadBarrierOption>(i, pointer_size);
+ return vtable->template GetElementPtrSize<ArtMethod*, kVerifyFlags, kReadBarrierOption>(
+ i, pointer_size);
}
inline int32_t Class::GetEmbeddedVTableLength() {
@@ -411,7 +409,7 @@ inline void Class::SetObjectSize(uint32_t new_object_size) {
// Object[] = int[] --> false
//
inline bool Class::IsArrayAssignableFromArray(ObjPtr<Class> src) {
- DCHECK(IsArrayClass()) << PrettyClass();
+ DCHECK(IsArrayClass()) << PrettyClass();
DCHECK(src->IsArrayClass()) << src->PrettyClass();
return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}
@@ -488,7 +486,7 @@ inline bool Class::ResolvedMethodAccessTest(ObjPtr<Class> access_to,
if (UNLIKELY(!this->CanAccess(dex_access_to))) {
if (throw_on_failure) {
ThrowIllegalAccessErrorClassForMethodDispatch(this,
- dex_access_to.Ptr(),
+ dex_access_to,
method,
throw_invoke_type);
}
@@ -623,16 +621,14 @@ inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* metho
return FindVirtualMethodForVirtual(method, pointer_size);
}
-template<VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline IfTable* Class::GetIfTable() {
ObjPtr<IfTable> ret = GetFieldObject<IfTable, kVerifyFlags, kReadBarrierOption>(IfTableOffset());
DCHECK(ret != nullptr) << PrettyClass(this);
return ret.Ptr();
}
-template<VerifyObjectFlags kVerifyFlags,
- ReadBarrierOption kReadBarrierOption>
+template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline int32_t Class::GetIfTableCount() {
return GetIfTable<kVerifyFlags, kReadBarrierOption>()->Count();
}
@@ -735,7 +731,7 @@ inline String* Class::GetName() {
}
inline void Class::SetName(ObjPtr<String> name) {
- SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
+ SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
}
template<VerifyObjectFlags kVerifyFlags>
@@ -801,7 +797,7 @@ inline ObjPtr<Object> Class::Alloc(Thread* self, gc::AllocatorType allocator_typ
obj = nullptr;
}
}
- return obj.Ptr();
+ return obj;
}
inline ObjPtr<Object> Class::AllocObject(Thread* self) {
@@ -857,11 +853,6 @@ inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable,
return size;
}
-template<ReadBarrierOption kReadBarrierOption>
-inline bool Class::IsReferenceClass() const {
- return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
-}
-
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool Class::IsClassClass() {
ObjPtr<Class> java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
@@ -893,8 +884,8 @@ inline bool Class::DescriptorEquals(const char* match) {
inline void Class::AssertInitializedOrInitializingInThread(Thread* self) {
if (kIsDebugBuild && !IsInitialized()) {
CHECK(IsInitializing()) << PrettyClass() << " is not initializing: " << GetStatus();
- CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass()
- << " is initializing in a different thread";
+ CHECK_EQ(GetClinitThreadId(), self->GetTid())
+ << PrettyClass() << " is initializing in a different thread";
}
}
@@ -916,30 +907,6 @@ inline ObjectArray<ObjectArray<Class>>* Class::GetProxyThrows() {
return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
}
-inline MemberOffset Class::GetDisableIntrinsicFlagOffset() {
- CHECK(IsReferenceClass());
- // First static field
- auto* field = GetStaticField(0);
- DCHECK_STREQ(field->GetName(), "disableIntrinsic");
- return field->GetOffset();
-}
-
-inline MemberOffset Class::GetSlowPathFlagOffset() {
- CHECK(IsReferenceClass());
- // Second static field
- auto* field = GetStaticField(1);
- DCHECK_STREQ(field->GetName(), "slowPathEnabled");
- return field->GetOffset();
-}
-
-inline bool Class::GetSlowPathEnabled() {
- return GetFieldBoolean(GetSlowPathFlagOffset());
-}
-
-inline void Class::SetSlowPath(bool enabled) {
- SetFieldBoolean<false, false>(GetSlowPathFlagOffset(), enabled);
-}
-
inline void Class::InitializeClassVisitor::operator()(ObjPtr<Object> obj,
size_t usable_size) const {
DCHECK_LE(class_size_, usable_size);
@@ -994,18 +961,15 @@ inline ArraySlice<ArtMethod> Class::GetDirectMethods(PointerSize pointer_size) {
return GetDirectMethodsSliceUnchecked(pointer_size);
}
-inline ArraySlice<ArtMethod> Class::GetDeclaredMethods(
- PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetDeclaredMethods(PointerSize pointer_size) {
return GetDeclaredMethodsSliceUnchecked(pointer_size);
}
-inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethods(
- PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethods(PointerSize pointer_size) {
return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size);
}
-inline ArraySlice<ArtMethod> Class::GetVirtualMethods(
- PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetVirtualMethods(PointerSize pointer_size) {
CheckPointerSize(pointer_size);
return GetVirtualMethodsSliceUnchecked(pointer_size);
}
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 3f4e841f86..227ace08c2 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -26,6 +26,7 @@
#include "class_ext.h"
#include "class_linker-inl.h"
#include "class_loader.h"
+#include "class_root.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_annotations.h"
@@ -38,6 +39,7 @@
#include "object-refvisitor-inl.h"
#include "object_array-inl.h"
#include "object_lock.h"
+#include "string-inl.h"
#include "runtime.h"
#include "thread.h"
#include "throwable.h"
@@ -53,48 +55,28 @@ namespace mirror {
using android::base::StringPrintf;
-GcRoot<Class> Class::java_lang_Class_;
-
-void Class::SetClassClass(ObjPtr<Class> java_lang_Class) {
- CHECK(java_lang_Class_.IsNull())
- << java_lang_Class_.Read()
- << " " << java_lang_Class;
- CHECK(java_lang_Class != nullptr);
- java_lang_Class->SetClassFlags(kClassFlagClass);
- java_lang_Class_ = GcRoot<Class>(java_lang_Class);
-}
-
-void Class::ResetClass() {
- CHECK(!java_lang_Class_.IsNull());
- java_lang_Class_ = GcRoot<Class>(nullptr);
-}
-
-void Class::VisitRoots(RootVisitor* visitor) {
- java_lang_Class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
const char* expected_name = nullptr;
- ClassLinker::ClassRoot class_root = ClassLinker::kJavaLangObject; // Invalid.
+ ClassRoot class_root = ClassRoot::kJavaLangObject; // Invalid.
if (name != nullptr && name->GetLength() >= 2) {
// Perfect hash for the expected values: from the second letters of the primitive types,
// only 'y' has the bit 0x10 set, so use it to change 'b' to 'B'.
char hash = name->CharAt(0) ^ ((name->CharAt(1) & 0x10) << 1);
switch (hash) {
- case 'b': expected_name = "boolean"; class_root = ClassLinker::kPrimitiveBoolean; break;
- case 'B': expected_name = "byte"; class_root = ClassLinker::kPrimitiveByte; break;
- case 'c': expected_name = "char"; class_root = ClassLinker::kPrimitiveChar; break;
- case 'd': expected_name = "double"; class_root = ClassLinker::kPrimitiveDouble; break;
- case 'f': expected_name = "float"; class_root = ClassLinker::kPrimitiveFloat; break;
- case 'i': expected_name = "int"; class_root = ClassLinker::kPrimitiveInt; break;
- case 'l': expected_name = "long"; class_root = ClassLinker::kPrimitiveLong; break;
- case 's': expected_name = "short"; class_root = ClassLinker::kPrimitiveShort; break;
- case 'v': expected_name = "void"; class_root = ClassLinker::kPrimitiveVoid; break;
+ case 'b': expected_name = "boolean"; class_root = ClassRoot::kPrimitiveBoolean; break;
+ case 'B': expected_name = "byte"; class_root = ClassRoot::kPrimitiveByte; break;
+ case 'c': expected_name = "char"; class_root = ClassRoot::kPrimitiveChar; break;
+ case 'd': expected_name = "double"; class_root = ClassRoot::kPrimitiveDouble; break;
+ case 'f': expected_name = "float"; class_root = ClassRoot::kPrimitiveFloat; break;
+ case 'i': expected_name = "int"; class_root = ClassRoot::kPrimitiveInt; break;
+ case 'l': expected_name = "long"; class_root = ClassRoot::kPrimitiveLong; break;
+ case 's': expected_name = "short"; class_root = ClassRoot::kPrimitiveShort; break;
+ case 'v': expected_name = "void"; class_root = ClassRoot::kPrimitiveVoid; break;
default: break;
}
}
if (expected_name != nullptr && name->Equals(expected_name)) {
- ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->GetClassRoot(class_root);
+ ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
DCHECK(klass != nullptr);
return klass;
} else {
@@ -1209,13 +1191,15 @@ Class* Class::CopyOf(Thread* self, int32_t new_length, ImTable* imt, PointerSize
// We may get copied by a compacting GC.
StackHandleScope<1> hs(self);
Handle<Class> h_this(hs.NewHandle(this));
- gc::Heap* heap = Runtime::Current()->GetHeap();
+ Runtime* runtime = Runtime::Current();
+ gc::Heap* heap = runtime->GetHeap();
// The num_bytes (3rd param) is sizeof(Class) as opposed to SizeOf()
// to skip copying the tail part that we will overwrite here.
CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class), imt, pointer_size);
+ ObjPtr<mirror::Class> java_lang_Class = GetClassRoot<mirror::Class>(runtime->GetClassLinker());
ObjPtr<Object> new_class = kMovingClasses ?
- heap->AllocObject<true>(self, java_lang_Class_.Read(), new_length, visitor) :
- heap->AllocNonMovableObject<true>(self, java_lang_Class_.Read(), new_length, visitor);
+ heap->AllocObject<true>(self, java_lang_Class, new_length, visitor) :
+ heap->AllocNonMovableObject<true>(self, java_lang_Class, new_length, visitor);
if (UNLIKELY(new_class == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
@@ -1249,7 +1233,7 @@ ArtMethod* Class::GetDeclaredConstructor(
uint32_t Class::Depth() {
uint32_t depth = 0;
- for (ObjPtr<Class> klass = this; klass->GetSuperClass() != nullptr; klass = klass->GetSuperClass()) {
+ for (ObjPtr<Class> cls = this; cls->GetSuperClass() != nullptr; cls = cls->GetSuperClass()) {
depth++;
}
return depth;
@@ -1285,7 +1269,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal(
for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
- ObjPtr<String> np_name = np_method->GetNameAsString(self);
+ ObjPtr<String> np_name = np_method->ResolveNameString();
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
@@ -1307,7 +1291,7 @@ ObjPtr<Method> Class::GetDeclaredMethodInternal(
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
- ObjPtr<String> np_name = np_method->GetNameAsString(self);
+ ObjPtr<String> np_name = np_method->ResolveNameString();
if (np_name == nullptr) {
self->AssertPendingException();
return nullptr;
@@ -1459,12 +1443,12 @@ template<VerifyObjectFlags kVerifyFlags> void Class::GetAccessFlagsDCheck() {
// circularity issue during loading the names of its members
DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
- this == String::GetJavaLangString())
+ this == GetClassRoot<String>())
<< "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>()
<< " IsRetired=" << IsRetired<kVerifyFlags>()
<< " IsErroneous=" <<
IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
- << " IsString=" << (this == String::GetJavaLangString())
+ << " IsString=" << (this == GetClassRoot<String>())
<< " status= " << GetStatus<kVerifyFlags>()
<< " descriptor=" << PrettyDescriptor();
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 98e25eb320..c3e167c306 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -30,7 +30,6 @@
#include "dex/modifiers.h"
#include "dex/primitive.h"
#include "gc/allocator_type.h"
-#include "gc_root.h"
#include "imtable.h"
#include "object.h"
#include "object_array.h"
@@ -437,9 +436,6 @@ class MANAGED Class FINAL : public Object {
bool IsThrowableClass() REQUIRES_SHARED(Locks::mutator_lock_);
- template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- bool IsReferenceClass() const REQUIRES_SHARED(Locks::mutator_lock_);
-
static MemberOffset ComponentTypeOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
}
@@ -785,7 +781,7 @@ class MANAGED Class FINAL : public Object {
ALWAYS_INLINE PointerArray* GetVTableDuringLinking() REQUIRES_SHARED(Locks::mutator_lock_);
- void SetVTable(PointerArray* new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
+ void SetVTable(ObjPtr<PointerArray> new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
static MemberOffset VTableOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
@@ -936,12 +932,10 @@ class MANAGED Class FINAL : public Object {
ArtMethod* FindConstructor(const StringPiece& signature, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethodByName(const StringPiece& name,
- PointerSize pointer_size)
+ ArtMethod* FindDeclaredVirtualMethodByName(const StringPiece& name, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethodByName(const StringPiece& name,
- PointerSize pointer_size)
+ ArtMethod* FindDeclaredDirectMethodByName(const StringPiece& name, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
ArtMethod* FindClassInitializer(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1133,21 +1127,6 @@ class MANAGED Class FINAL : public Object {
dex::TypeIndex FindTypeIndexInOtherDexFile(const DexFile& dex_file)
REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* GetJavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(HasJavaLangClass());
- return java_lang_Class_.Read();
- }
-
- static bool HasJavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return !java_lang_Class_.IsNull();
- }
-
- // Can't call this SetClass or else gets called instead of Object::SetClass in places.
- static void SetClassClass(ObjPtr<Class> java_lang_Class) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Visit native roots visits roots which are keyed off the native pointers such as ArtFields and
// ArtMethods.
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor>
@@ -1200,10 +1179,7 @@ class MANAGED Class FINAL : public Object {
void AssertInitializedOrInitializingInThread(Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_);
- Class* CopyOf(Thread* self,
- int32_t new_length,
- ImTable* imt,
- PointerSize pointer_size)
+ Class* CopyOf(Thread* self, int32_t new_length, ImTable* imt, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// For proxy class only.
@@ -1212,12 +1188,6 @@ class MANAGED Class FINAL : public Object {
// For proxy class only.
ObjectArray<ObjectArray<Class>>* GetProxyThrows() REQUIRES_SHARED(Locks::mutator_lock_);
- // For reference class only.
- MemberOffset GetDisableIntrinsicFlagOffset() REQUIRES_SHARED(Locks::mutator_lock_);
- MemberOffset GetSlowPathFlagOffset() REQUIRES_SHARED(Locks::mutator_lock_);
- bool GetSlowPathEnabled() REQUIRES_SHARED(Locks::mutator_lock_);
- void SetSlowPath(bool enabled) REQUIRES_SHARED(Locks::mutator_lock_);
-
// May cause thread suspension due to EqualParameters.
ArtMethod* GetDeclaredConstructor(Thread* self,
Handle<ObjectArray<Class>> args,
@@ -1513,9 +1483,6 @@ class MANAGED Class FINAL : public Object {
// Static fields, variable size.
// uint32_t fields_[0];
- // java.lang.Class
- static GcRoot<Class> java_lang_Class_;
-
ART_FRIEND_TEST(DexCacheTest, TestResolvedFieldAccess); // For ResolvedFieldAccessTest
friend struct art::ClassOffsets; // for verifying offset information
friend class Object; // For VisitReferences
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index 081957964c..44bf9891cd 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -21,6 +21,7 @@
#include "base/enums.h"
#include "base/utils.h"
#include "class-inl.h"
+#include "class_root.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "object-inl.h"
@@ -31,8 +32,6 @@
namespace art {
namespace mirror {
-GcRoot<Class> ClassExt::dalvik_system_ClassExt_;
-
uint32_t ClassExt::ClassSize(PointerSize pointer_size) {
uint32_t vtable_entries = Object::kVTableLength;
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
@@ -44,8 +43,8 @@ void ClassExt::SetObsoleteArrays(ObjPtr<PointerArray> methods,
auto obsolete_dex_cache_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_);
auto obsolete_methods_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_);
DCHECK(!Runtime::Current()->IsActiveTransaction());
- SetFieldObject<false>(obsolete_dex_cache_off, dex_caches.Ptr());
- SetFieldObject<false>(obsolete_methods_off, methods.Ptr());
+ SetFieldObject<false>(obsolete_dex_cache_off, dex_caches);
+ SetFieldObject<false>(obsolete_methods_off, methods);
}
// We really need to be careful how we update this. If we ever in the future make it so that
@@ -102,8 +101,7 @@ bool ClassExt::ExtendObsoleteArrays(Thread* self, uint32_t increase) {
}
ClassExt* ClassExt::Alloc(Thread* self) {
- DCHECK(dalvik_system_ClassExt_.Read() != nullptr);
- return down_cast<ClassExt*>(dalvik_system_ClassExt_.Read()->AllocObject(self).Ptr());
+ return down_cast<ClassExt*>(GetClassRoot<ClassExt>()->AllocObject(self).Ptr());
}
void ClassExt::SetVerifyError(ObjPtr<Object> err) {
@@ -119,19 +117,5 @@ void ClassExt::SetOriginalDexFile(ObjPtr<Object> bytes) {
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_), bytes);
}
-void ClassExt::SetClass(ObjPtr<Class> dalvik_system_ClassExt) {
- CHECK(dalvik_system_ClassExt != nullptr);
- dalvik_system_ClassExt_ = GcRoot<Class>(dalvik_system_ClassExt);
-}
-
-void ClassExt::ResetClass() {
- CHECK(!dalvik_system_ClassExt_.IsNull());
- dalvik_system_ClassExt_ = GcRoot<Class>(nullptr);
-}
-
-void ClassExt::VisitRoots(RootVisitor* visitor) {
- dalvik_system_ClassExt_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class_ext.h b/runtime/mirror/class_ext.h
index 75a3800989..612fd0f256 100644
--- a/runtime/mirror/class_ext.h
+++ b/runtime/mirror/class_ext.h
@@ -20,7 +20,6 @@
#include "array.h"
#include "class.h"
#include "dex_cache.h"
-#include "gc_root.h"
#include "object.h"
#include "object_array.h"
#include "string.h"
@@ -72,10 +71,6 @@ class MANAGED ClassExt : public Object {
bool ExtendObsoleteArrays(Thread* self, uint32_t increase)
REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(ObjPtr<Class> dalvik_system_ClassExt);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor>
inline void VisitNativeRoots(Visitor& visitor, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -93,8 +88,6 @@ class MANAGED ClassExt : public Object {
// The saved verification error of this class.
HeapReference<Object> verify_error_;
- static GcRoot<Class> dalvik_system_ClassExt_;
-
friend struct art::ClassExtOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassExt);
};
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 72f1443dfa..96778aa98d 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -28,7 +28,7 @@
#include "class_linker.h"
#include "dex/dex_file.h"
#include "gc/heap-inl.h"
-#include "gc_root.h"
+#include "gc_root-inl.h"
#include "mirror/call_site.h"
#include "mirror/class.h"
#include "mirror/method_type.h"
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 9aff9ec49a..bb86004a90 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -21,6 +21,7 @@
#include "base/bit_utils.h"
#include "base/mutex.h"
#include "dex/dex_file_types.h"
+#include "gc_root-inl.h"
#include "object.h"
#include "object_array.h"
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
index 5f00c6e9c7..ce39049e11 100644
--- a/runtime/mirror/emulated_stack_frame.cc
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -17,7 +17,7 @@
#include "emulated_stack_frame.h"
#include "class-inl.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
#include "jvalue-inl.h"
#include "method_handles-inl.h"
#include "method_handles.h"
@@ -26,8 +26,6 @@
namespace art {
namespace mirror {
-GcRoot<mirror::Class> EmulatedStackFrame::static_class_;
-
// Calculates the size of a stack frame based on the size of its argument
// types and return types.
static void CalculateFrameAndReferencesSize(ObjPtr<mirror::ObjectArray<mirror::Class>> p_types,
@@ -166,8 +164,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs(
CalculateFrameAndReferencesSize(to_types.Get(), r_type.Get(), &frame_size, &refs_size);
// Step 3 : Allocate the arrays.
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> array_class(class_linker->GetClassRoot(ClassLinker::kObjectArrayClass));
+ ObjPtr<mirror::Class> array_class(GetClassRoot<mirror::ObjectArray<mirror::Object>>());
Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(
mirror::ObjectArray<mirror::Object>::Alloc(self, array_class, refs_size)));
@@ -192,7 +189,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs(
// Step 5: Construct the EmulatedStackFrame object.
Handle<EmulatedStackFrame> sf(hs.NewHandle(
- ObjPtr<EmulatedStackFrame>::DownCast(StaticClass()->AllocObject(self))));
+ ObjPtr<EmulatedStackFrame>::DownCast(GetClassRoot<EmulatedStackFrame>()->AllocObject(self))));
sf->SetFieldObject<false>(CallsiteTypeOffset(), caller_type.Get());
sf->SetFieldObject<false>(TypeOffset(), callee_type.Get());
sf->SetFieldObject<false>(ReferencesOffset(), references.Get());
@@ -272,20 +269,5 @@ void EmulatedStackFrame::SetReturnValue(Thread* self, const JValue& value) {
}
}
-void EmulatedStackFrame::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void EmulatedStackFrame::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void EmulatedStackFrame::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index 23626f46e0..ec45f57a4d 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -64,15 +64,7 @@ class MANAGED EmulatedStackFrame : public Object {
return GetReferences()->Get(0);
}
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
mirror::ObjectArray<mirror::Object>* GetReferences() REQUIRES_SHARED(Locks::mutator_lock_) {
return GetFieldObject<mirror::ObjectArray<mirror::Object>>(
OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, references_));
@@ -104,8 +96,6 @@ class MANAGED EmulatedStackFrame : public Object {
HeapReference<mirror::ByteArray> stack_frame_;
HeapReference<mirror::MethodType> type_;
- static GcRoot<mirror::Class> static_class_; // dalvik.system.EmulatedStackFrame.class
-
friend struct art::EmulatedStackFrameOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(EmulatedStackFrame);
};
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 8a28f66868..23dd787c80 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -18,7 +18,6 @@
#define ART_RUNTIME_MIRROR_EXECUTABLE_H_
#include "accessible_object.h"
-#include "gc_root.h"
#include "object.h"
#include "read_barrier_option.h"
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index bcd2db4dbd..2e263b9517 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -21,6 +21,7 @@
#include "art_field-inl.h"
#include "class-inl.h"
+#include "class_root.h"
#include "dex_cache-inl.h"
namespace art {
@@ -48,7 +49,7 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field, b
self->ClearException();
}
}
- auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(StaticClass()->AllocObject(self)));
+ auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(GetClassRoot<Field>()->AllocObject(self)));
if (UNLIKELY(ret == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index b4d93b6d4d..a2b51d8d9a 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -24,36 +24,6 @@
namespace art {
namespace mirror {
-GcRoot<Class> Field::static_class_;
-GcRoot<Class> Field::array_class_;
-
-void Field::SetClass(ObjPtr<Class> klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void Field::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void Field::SetArrayClass(ObjPtr<Class> klass) {
- CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- array_class_ = GcRoot<Class>(klass);
-}
-
-void Field::ResetArrayClass() {
- CHECK(!array_class_.IsNull());
- array_class_ = GcRoot<Class>(nullptr);
-}
-
-void Field::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
- array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
ArtField* Field::GetArtField() {
mirror::Class* declaring_class = GetDeclaringClass();
if (UNLIKELY(declaring_class->IsProxyClass())) {
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 03fd031304..3501e71f82 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -21,7 +21,6 @@
#include "base/enums.h"
#include "dex/modifiers.h"
#include "dex/primitive.h"
-#include "gc_root.h"
#include "obj_ptr.h"
#include "object.h"
#include "read_barrier_option.h"
@@ -39,14 +38,6 @@ class String;
// C++ mirror of java.lang.reflect.Field.
class MANAGED Field : public AccessibleObject {
public:
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
- static mirror::Class* ArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return array_class_.Read();
- }
-
ALWAYS_INLINE uint32_t GetDexFieldIndex() REQUIRES_SHARED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, dex_field_index_));
}
@@ -81,14 +72,6 @@ class MANAGED Field : public AccessibleObject {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_));
}
- static void SetClass(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void SetArrayClass(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Slow, try to use only for PrettyField and such.
ArtField* GetArtField() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -128,9 +111,6 @@ class MANAGED Field : public AccessibleObject {
SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, offset_), offset);
}
- static GcRoot<Class> static_class_; // java.lang.reflect.Field.class.
- static GcRoot<Class> array_class_; // array of java.lang.reflect.Field.
-
friend struct art::FieldOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
};
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 25cbdc131b..cf03b95d5e 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -17,44 +17,17 @@
#include "method.h"
#include "art_method.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
namespace art {
namespace mirror {
-GcRoot<Class> Method::static_class_;
-GcRoot<Class> Method::array_class_;
-GcRoot<Class> Constructor::static_class_;
-GcRoot<Class> Constructor::array_class_;
-
-void Method::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void Method::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void Method::SetArrayClass(Class* klass) {
- CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- array_class_ = GcRoot<Class>(klass);
-}
-
-void Method::ResetArrayClass() {
- CHECK(!array_class_.IsNull());
- array_class_ = GcRoot<Class>(nullptr);
-}
-
template <PointerSize kPointerSize, bool kTransactionActive>
Method* Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
DCHECK(!method->IsConstructor()) << method->PrettyMethod();
- ObjPtr<Method> ret = ObjPtr<Method>::DownCast(StaticClass()->AllocObject(self));
+ ObjPtr<Method> ret = ObjPtr<Method>::DownCast(GetClassRoot<Method>()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
ObjPtr<Executable>(ret)->
CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
@@ -71,42 +44,11 @@ template Method* Method::CreateFromArtMethod<PointerSize::k64, false>(Thread* se
template Method* Method::CreateFromArtMethod<PointerSize::k64, true>(Thread* self,
ArtMethod* method);
-void Method::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
- array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-void Constructor::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void Constructor::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void Constructor::SetArrayClass(Class* klass) {
- CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- array_class_ = GcRoot<Class>(klass);
-}
-
-void Constructor::ResetArrayClass() {
- CHECK(!array_class_.IsNull());
- array_class_ = GcRoot<Class>(nullptr);
-}
-
-void Constructor::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
- array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
template <PointerSize kPointerSize, bool kTransactionActive>
Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
DCHECK(method->IsConstructor()) << method->PrettyMethod();
- ObjPtr<Constructor> ret = ObjPtr<Constructor>::DownCast(StaticClass()->AllocObject(self));
+ ObjPtr<Constructor> ret =
+ ObjPtr<Constructor>::DownCast(GetClassRoot<Constructor>()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
ObjPtr<Executable>(ret)->
CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 61332e3bd9..aea15a7748 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -18,7 +18,6 @@
#define ART_RUNTIME_MIRROR_METHOD_H_
#include "executable.h"
-#include "gc_root.h"
namespace art {
namespace mirror {
@@ -32,28 +31,7 @@ class MANAGED Method : public Executable {
static Method* CreateFromArtMethod(Thread* self, ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static mirror::Class* ArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return array_class_.Read();
- }
-
- static void SetArrayClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void ResetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- static GcRoot<Class> static_class_; // java.lang.reflect.Method.class.
- static GcRoot<Class> array_class_; // [java.lang.reflect.Method.class.
-
DISALLOW_COPY_AND_ASSIGN(Method);
};
@@ -64,28 +42,7 @@ class MANAGED Constructor: public Executable {
static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static mirror::Class* ArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return array_class_.Read();
- }
-
- static void SetArrayClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void ResetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- static GcRoot<Class> static_class_; // java.lang.reflect.Constructor.class.
- static GcRoot<Class> array_class_; // [java.lang.reflect.Constructor.class.
-
DISALLOW_COPY_AND_ASSIGN(Constructor);
};
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
index 0b4dde1aa8..88ccbc947d 100644
--- a/runtime/mirror/method_handle_impl.cc
+++ b/runtime/mirror/method_handle_impl.cc
@@ -17,7 +17,7 @@
#include "method_handle_impl-inl.h"
#include "class-inl.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
namespace art {
namespace mirror {
@@ -30,12 +30,6 @@ const char* MethodHandle::GetReturnTypeDescriptor(const char* invoke_method_name
}
}
-mirror::Class* MethodHandle::StaticClass() {
- mirror::Class* klass = MethodHandleImpl::StaticClass()->GetSuperClass();
- DCHECK(klass->DescriptorEquals("Ljava/lang/invoke/MethodHandle;"));
- return klass;
-}
-
void MethodHandle::Initialize(uintptr_t art_field_or_method,
Kind kind,
Handle<MethodType> method_type)
@@ -48,35 +42,14 @@ void MethodHandle::Initialize(uintptr_t art_field_or_method,
SetField64<false>(ArtFieldOrMethodOffset(), art_field_or_method);
}
-GcRoot<mirror::Class> MethodHandleImpl::static_class_;
-
-mirror::Class* MethodHandleImpl::StaticClass() {
- return static_class_.Read();
-}
-
-void MethodHandleImpl::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodHandleImpl::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodHandleImpl::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
mirror::MethodHandleImpl* MethodHandleImpl::Create(Thread* const self,
uintptr_t art_field_or_method,
MethodHandle::Kind kind,
Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<1> hs(self);
- Handle<mirror::MethodHandleImpl> mh(
- hs.NewHandle(ObjPtr<MethodHandleImpl>::DownCast(StaticClass()->AllocObject(self))));
+ Handle<mirror::MethodHandleImpl> mh(hs.NewHandle(ObjPtr<MethodHandleImpl>::DownCast(
+ GetClassRoot<MethodHandleImpl>()->AllocObject(self))));
mh->Initialize(art_field_or_method, kind, method_type);
return mh.Get();
}
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index 3b0002c2af..030a49ed1e 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -20,7 +20,6 @@
#include "art_field.h"
#include "art_method.h"
#include "class.h"
-#include "gc_root.h"
#include "method_type.h"
#include "object.h"
@@ -87,8 +86,6 @@ class MANAGED MethodHandle : public Object {
// supported.
static const char* GetReturnTypeDescriptor(const char* invoke_method_name);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
protected:
void Initialize(uintptr_t art_field_or_method, Kind kind, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -130,19 +127,12 @@ class MANAGED MethodHandleImpl : public MethodHandle {
Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
static MemberOffset InfoOffset() {
return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, info_));
}
HeapReference<mirror::Object> info_; // Unused by the runtime.
- static GcRoot<mirror::Class> static_class_; // java.lang.invoke.MethodHandleImpl.class
friend struct art::MethodHandleImplOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index aeecf75c1f..d1e7a6dbfa 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -17,8 +17,8 @@
#include "method_handles_lookup.h"
#include "class-inl.h"
+#include "class_root.h"
#include "dex/modifiers.h"
-#include "gc_root-inl.h"
#include "handle_scope.h"
#include "jni/jni_internal.h"
#include "mirror/method_handle_impl.h"
@@ -28,33 +28,15 @@
namespace art {
namespace mirror {
-GcRoot<mirror::Class> MethodHandlesLookup::static_class_;
-
-void MethodHandlesLookup::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodHandlesLookup::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodHandlesLookup::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
MethodHandlesLookup* MethodHandlesLookup::Create(Thread* const self, Handle<Class> lookup_class)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
static constexpr uint32_t kAllModes = kAccPublic | kAccPrivate | kAccProtected | kAccStatic;
- StackHandleScope<1> hs(self);
- Handle<MethodHandlesLookup> mhl(
- hs.NewHandle(ObjPtr<MethodHandlesLookup>::DownCast(StaticClass()->AllocObject(self))));
+ ObjPtr<MethodHandlesLookup> mhl = ObjPtr<MethodHandlesLookup>::DownCast(
+ GetClassRoot<MethodHandlesLookup>()->AllocObject(self));
mhl->SetFieldObject<false>(LookupClassOffset(), lookup_class.Get());
mhl->SetField32<false>(AllowedModesOffset(), kAllModes);
- return mhl.Get();
+ return mhl.Ptr();
}
MethodHandlesLookup* MethodHandlesLookup::GetDefault(Thread* const self) {
diff --git a/runtime/mirror/method_handles_lookup.h b/runtime/mirror/method_handles_lookup.h
index fefcb2ed29..56261eca67 100644
--- a/runtime/mirror/method_handles_lookup.h
+++ b/runtime/mirror/method_handles_lookup.h
@@ -18,7 +18,6 @@
#define ART_RUNTIME_MIRROR_METHOD_HANDLES_LOOKUP_H_
#include "base/utils.h"
-#include "gc_root.h"
#include "handle.h"
#include "obj_ptr.h"
#include "object.h"
@@ -40,14 +39,6 @@ class MANAGED MethodHandlesLookup : public Object {
Handle<Class> lookup_class)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Returns the result of java.lang.invoke.MethodHandles.lookup().
static mirror::MethodHandlesLookup* GetDefault(Thread* const self)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -71,8 +62,6 @@ class MANAGED MethodHandlesLookup : public Object {
int32_t allowed_modes_;
- static GcRoot<mirror::Class> static_class_; // java.lang.invoke.MethodHandles.Lookup.class
-
friend struct art::MethodHandlesLookupOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandlesLookup);
};
diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc
index 45f7a87951..bc62ebdc8b 100644
--- a/runtime/mirror/method_type.cc
+++ b/runtime/mirror/method_type.cc
@@ -17,7 +17,7 @@
#include "method_type.h"
#include "class-inl.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
#include "method_handles.h"
namespace art {
@@ -27,22 +27,18 @@ namespace {
ObjPtr<ObjectArray<Class>> AllocatePTypesArray(Thread* self, int count)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<Class> class_type = Class::GetJavaLangClass();
- ObjPtr<Class> class_array_type =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_type);
+ ObjPtr<Class> class_array_type = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
return ObjectArray<Class>::Alloc(self, class_array_type, count);
}
} // namespace
-GcRoot<Class> MethodType::static_class_;
-
MethodType* MethodType::Create(Thread* const self,
Handle<Class> return_type,
Handle<ObjectArray<Class>> parameter_types) {
StackHandleScope<1> hs(self);
Handle<MethodType> mt(
- hs.NewHandle(ObjPtr<MethodType>::DownCast(StaticClass()->AllocObject(self))));
+ hs.NewHandle(ObjPtr<MethodType>::DownCast(GetClassRoot<MethodType>()->AllocObject(self))));
// TODO: Do we ever create a MethodType during a transaction ? There doesn't
// seem like a good reason to do a polymorphic invoke that results in the
@@ -172,20 +168,5 @@ std::string MethodType::PrettyDescriptor() REQUIRES_SHARED(Locks::mutator_lock_)
return ss.str();
}
-void MethodType::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodType::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodType::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h
index 771162a2de..014b211d66 100644
--- a/runtime/mirror/method_type.h
+++ b/runtime/mirror/method_type.h
@@ -48,10 +48,6 @@ class MANAGED MethodType : public Object {
int32_t start_index)
REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
ObjectArray<Class>* GetPTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
return GetFieldObject<ObjectArray<Class>>(OFFSET_OF_OBJECT_MEMBER(MethodType, p_types_));
}
@@ -68,10 +64,6 @@ class MANAGED MethodType : public Object {
return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(MethodType, r_type_));
}
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Returns true iff. |this| is an exact match for method type |target|, i.e
// iff. they have the same return types and parameter types.
bool IsExactMatch(MethodType* target) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -111,8 +103,6 @@ class MANAGED MethodType : public Object {
HeapReference<Class> r_type_;
HeapReference<Object> wrap_alt_; // Unused in the runtime
- static GcRoot<Class> static_class_; // java.lang.invoke.MethodType.class
-
friend struct art::MethodTypeOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(MethodType);
};
diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc
index 16bfc73e04..2bdea72f14 100644
--- a/runtime/mirror/method_type_test.cc
+++ b/runtime/mirror/method_type_test.cc
@@ -22,6 +22,7 @@
#include "class-inl.h"
#include "class_linker-inl.h"
#include "class_loader.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "object_array-inl.h"
@@ -53,8 +54,8 @@ static mirror::MethodType* CreateMethodType(const std::string& return_type,
soa.Self(), FullyQualifiedType(return_type).c_str(), boot_class_loader));
CHECK(return_clazz != nullptr);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> class_array_type = class_linker->FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> class_array_type =
+ GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker);
Handle<mirror::ObjectArray<mirror::Class>> param_classes = hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, param_types.size()));
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index c7561f4278..ee4f53b695 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -37,7 +37,7 @@
#include "read_barrier-inl.h"
#include "reference.h"
#include "runtime.h"
-#include "string-inl.h"
+#include "string.h"
#include "throwable.h"
namespace art {
@@ -114,10 +114,6 @@ inline void Object::NotifyAll(Thread* self) {
Monitor::NotifyAll(self, this);
}
-inline void Object::Wait(Thread* self) {
- Monitor::Wait(self, this, 0, 0, true, kWaiting);
-}
-
inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
@@ -412,17 +408,21 @@ inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
return GetFieldByte<kVerifyFlags, true>(field_offset);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
- GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
- kIsVolatile);
+ Runtime::Current()->RecordWriteFieldBoolean(
+ this,
+ field_offset,
+ GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
+ kIsVolatile);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
@@ -430,17 +430,20 @@ inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value
SetField<uint8_t, kIsVolatile>(field_offset, new_value);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteFieldByte(this, field_offset,
- GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
- kIsVolatile);
+ Runtime::Current()->RecordWriteFieldByte(this,
+ field_offset,
+ GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
+ kIsVolatile);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
@@ -486,16 +489,19 @@ inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
return GetFieldShort<kVerifyFlags, true>(field_offset);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteFieldChar(this, field_offset,
- GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
- kIsVolatile);
+ Runtime::Current()->RecordWriteFieldChar(this,
+ field_offset,
+ GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
+ kIsVolatile);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
@@ -503,16 +509,19 @@ inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value)
SetField<uint16_t, kIsVolatile>(field_offset, new_value);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteFieldChar(this, field_offset,
- GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
- kIsVolatile);
+ Runtime::Current()->RecordWriteFieldChar(this,
+ field_offset,
+ GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
+ kIsVolatile);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
@@ -532,14 +541,17 @@ inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new
field_offset, new_value);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteField32(this, field_offset,
+ Runtime::Current()->RecordWriteField32(this,
+ field_offset,
GetField32<kVerifyFlags, kIsVolatile>(field_offset),
kIsVolatile);
}
@@ -567,7 +579,8 @@ inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
+ int32_t old_value,
+ int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -585,7 +598,8 @@ inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offs
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
+ int32_t old_value,
+ int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -603,7 +617,8 @@ inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
+ int32_t old_value,
+ int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -621,7 +636,8 @@ inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset,
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
+ int32_t old_value,
+ int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -637,14 +653,17 @@ inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_of
return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
- Runtime::Current()->RecordWriteField64(this, field_offset,
+ Runtime::Current()->RecordWriteField64(this,
+ field_offset,
GetField64<kVerifyFlags, kIsVolatile>(field_offset),
kIsVolatile);
}
@@ -678,7 +697,8 @@ inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
- int64_t old_value, int64_t new_value) {
+ int64_t old_value,
+ int64_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -695,7 +715,8 @@ inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offs
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
- int64_t old_value, int64_t new_value) {
+ int64_t old_value,
+ int64_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -710,7 +731,9 @@ inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_of
return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
}
-template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
+template<class T,
+ VerifyObjectFlags kVerifyFlags,
+ ReadBarrierOption kReadBarrierOption,
bool kIsVolatile>
inline T* Object::GetFieldObject(MemberOffset field_offset) {
if (kVerifyFlags & kVerifyThis) {
@@ -733,8 +756,10 @@ inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
ObjPtr<Object> new_value) {
if (kCheckTransaction) {
@@ -747,7 +772,7 @@ inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
} else {
obj = GetFieldObject<Object>(field_offset);
}
- Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
+ Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
@@ -760,8 +785,10 @@ inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
objref_addr->Assign<kIsVolatile>(new_value.Ptr());
}
-template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
- bool kIsVolatile>
+template<bool kTransactionActive,
+ bool kCheckTransaction,
+ VerifyObjectFlags kVerifyFlags,
+ bool kIsVolatile>
inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
kIsVolatile>(field_offset, new_value);
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 0e03e3741c..4240e702b5 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -271,7 +271,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, ObjPtr<Object>
}
}
LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
- << " of type " << c->PrettyDescriptor() << " at offset " << field_offset;
+ << " of type " << c->PrettyDescriptor() << " at offset " << field_offset;
UNREACHABLE();
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 82045c7b66..a89d6323a5 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -176,7 +176,6 @@ class MANAGED LOCKABLE Object {
UNLOCK_FUNCTION();
void Notify(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
void NotifyAll(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
- void Wait(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
void Wait(Thread* self, int64_t timeout, int32_t nanos) REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -282,13 +281,16 @@ class MANAGED LOCKABLE Object {
bool IsPhantomReferenceInstance() REQUIRES_SHARED(Locks::mutator_lock_);
// Accessor for Java type fields.
- template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithReadBarrier, bool kIsVolatile = false>
+ template<class T,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
+ bool kIsVolatile = false>
ALWAYS_INLINE T* GetFieldObject(MemberOffset field_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ template<class T,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ALWAYS_INLINE T* GetFieldObjectVolatile(MemberOffset field_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -310,11 +312,11 @@ class MANAGED LOCKABLE Object {
template<bool kTransactionActive,
bool kCheckTransaction = true,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE void SetFieldObjectVolatile(MemberOffset field_offset,
- ObjPtr<Object> new_value)
+ ALWAYS_INLINE void SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kCheckTransaction = true, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ template<bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
bool kIsVolatile = false>
ALWAYS_INLINE void SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -416,23 +418,29 @@ class MANAGED LOCKABLE Object {
ALWAYS_INLINE int8_t GetFieldByteVolatile(MemberOffset field_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetFieldByte(MemberOffset field_offset, int8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -452,23 +460,29 @@ class MANAGED LOCKABLE Object {
ALWAYS_INLINE int16_t GetFieldShortVolatile(MemberOffset field_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetFieldChar(MemberOffset field_offset, uint16_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetFieldShort(MemberOffset field_offset, int16_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -487,13 +501,16 @@ class MANAGED LOCKABLE Object {
return GetField32<kVerifyFlags, true>(field_offset);
}
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetField32(MemberOffset field_offset, int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetField32Volatile(MemberOffset field_offset, int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -503,34 +520,44 @@ class MANAGED LOCKABLE Object {
ALWAYS_INLINE void SetField32Transaction(MemberOffset field_offset, int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value)
+ int32_t old_value,
+ int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldWeakRelaxed32(MemberOffset field_offset, int32_t old_value,
- int32_t new_value) ALWAYS_INLINE
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ALWAYS_INLINE bool CasFieldWeakRelaxed32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldWeakAcquire32(MemberOffset field_offset, int32_t old_value,
- int32_t new_value) ALWAYS_INLINE
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ALWAYS_INLINE bool CasFieldWeakAcquire32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldWeakRelease32(MemberOffset field_offset, int32_t old_value,
- int32_t new_value) ALWAYS_INLINE
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ALWAYS_INLINE bool CasFieldWeakRelease32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset, int32_t old_value,
- int32_t new_value) ALWAYS_INLINE
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ALWAYS_INLINE bool CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
@@ -548,13 +575,16 @@ class MANAGED LOCKABLE Object {
return GetField64<kVerifyFlags, true>(field_offset);
}
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ bool kIsVolatile = false>
ALWAYS_INLINE void SetField64(MemberOffset field_offset, int64_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE void SetField64Volatile(MemberOffset field_offset, int64_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -564,35 +594,45 @@ class MANAGED LOCKABLE Object {
ALWAYS_INLINE void SetField64Transaction(MemberOffset field_offset, int32_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, int64_t old_value,
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ bool CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
+ int64_t old_value,
int64_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, int64_t old_value,
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ bool CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
+ int64_t old_value,
int64_t new_value)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename T>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ typename T>
void SetFieldPtr(MemberOffset field_offset, T new_value)
REQUIRES_SHARED(Locks::mutator_lock_) {
SetFieldPtrWithSize<kTransactionActive, kCheckTransaction, kVerifyFlags>(
field_offset, new_value, kRuntimePointerSize);
}
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename T>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ typename T>
void SetFieldPtr64(MemberOffset field_offset, T new_value)
REQUIRES_SHARED(Locks::mutator_lock_) {
SetFieldPtrWithSize<kTransactionActive, kCheckTransaction, kVerifyFlags>(
field_offset, new_value, 8u);
}
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename T>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ typename T>
ALWAYS_INLINE void SetFieldPtrWithSize(MemberOffset field_offset,
T new_value,
PointerSize pointer_size)
@@ -628,28 +668,34 @@ class MANAGED LOCKABLE Object {
// Update methods that expose the raw address of a primitive value-type to an Accessor instance
// that will attempt to update the field. These are used by VarHandle accessor methods to
// atomically update fields with a wider range of memory orderings than usually required.
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateFieldBooleanViaAccessor(MemberOffset field_offset, Accessor<uint8_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateFieldByteViaAccessor(MemberOffset field_offset, Accessor<int8_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateFieldCharViaAccessor(MemberOffset field_offset, Accessor<uint16_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateFieldShortViaAccessor(MemberOffset field_offset, Accessor<int16_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateField32ViaAccessor(MemberOffset field_offset, Accessor<int32_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true,
- VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void UpdateField64ViaAccessor(MemberOffset field_offset, Accessor<int64_t>* accessor)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 086d2f4672..ed3c567464 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -37,14 +37,15 @@ namespace art {
namespace mirror {
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length, gc::AllocatorType allocator_type) {
- Array* array = Array::Alloc<true>(self,
- object_array_class.Ptr(),
- length,
- ComponentSizeShiftWidth(kHeapReferenceSize),
- allocator_type);
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length,
+ gc::AllocatorType allocator_type) {
+ ObjPtr<Array> array = Array::Alloc<true>(self,
+ object_array_class,
+ length,
+ ComponentSizeShiftWidth(kHeapReferenceSize),
+ allocator_type);
if (UNLIKELY(array == nullptr)) {
return nullptr;
}
@@ -54,9 +55,9 @@ inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
}
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length) {
return Alloc(self,
object_array_class,
length,
@@ -346,7 +347,7 @@ inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
}
template<class T>
-inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
StackHandleScope<1> hs(self);
@@ -354,7 +355,7 @@ inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length)
gc::Heap* heap = Runtime::Current()->GetHeap();
gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
heap->GetCurrentNonMovingAllocator();
- ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
+ ObjPtr<ObjectArray<T>> new_array = Alloc(self, GetClass(), new_length, allocator_type);
if (LIKELY(new_array != nullptr)) {
new_array->AssignableMemcpy(0, h_this.Get(), 0, std::min(h_this->GetLength(), new_length));
}
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index b7a956176f..6506f6ea9a 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -31,15 +31,15 @@ class MANAGED ObjectArray: public Array {
return Array::ClassSize(pointer_size);
}
- static ObjectArray<T>* Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length,
- gc::AllocatorType allocator_type)
+ static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length,
+ gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static ObjectArray<T>* Alloc(Thread* self,
- ObjPtr<Class> object_array_class,
- int32_t length)
+ static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+ ObjPtr<Class> object_array_class,
+ int32_t length)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -99,7 +99,7 @@ class MANAGED ObjectArray: public Array {
bool throw_exception)
REQUIRES_SHARED(Locks::mutator_lock_);
- ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
+ ObjPtr<ObjectArray<T>> CopyOf(Thread* self, int32_t new_length)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 69ba4b98cf..0b615a6b9a 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -28,6 +28,7 @@
#include "class-inl.h"
#include "class_linker-inl.h"
#include "class_linker.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "dex/dex_file.h"
#include "entrypoints/entrypoint_utils-inl.h"
@@ -75,10 +76,10 @@ class ObjectTest : public CommonRuntimeTest {
}
template <class T>
- mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+ ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
REQUIRES_SHARED(Locks::mutator_lock_) {
return mirror::ObjectArray<T>::Alloc(
- self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), length);
+ self, GetClassRoot(ClassRoot::kObjectArrayClass, class_linker_), length);
}
};
@@ -205,7 +206,8 @@ void TestPrimitiveArray(ClassLinker* cl) {
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_EQ(2, a->GetLength());
EXPECT_EQ(0, a->Get(0));
EXPECT_EQ(0, a->Get(1));
@@ -216,7 +218,6 @@ void TestPrimitiveArray(ClassLinker* cl) {
EXPECT_EQ(T(123), a->Get(0));
EXPECT_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -255,7 +256,8 @@ TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) {
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_EQ(2, a->GetLength());
EXPECT_DOUBLE_EQ(0, a->Get(0));
EXPECT_DOUBLE_EQ(0, a->Get(1));
@@ -266,7 +268,6 @@ TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) {
EXPECT_DOUBLE_EQ(T(123), a->Get(0));
EXPECT_DOUBLE_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -286,7 +287,8 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
ScopedObjectAccess soa(Thread::Current());
typedef typename ArrayT::ElementType T;
- ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
EXPECT_FLOAT_EQ(2, a->GetLength());
EXPECT_FLOAT_EQ(0, a->Get(0));
EXPECT_FLOAT_EQ(0, a->Get(1));
@@ -297,7 +299,6 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
EXPECT_FLOAT_EQ(T(123), a->Get(0));
EXPECT_FLOAT_EQ(T(321), a->Get(1));
- StackHandleScope<1> hs(soa.Self());
Handle<Class> aioobe = hs.NewHandle(
class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
@@ -316,16 +317,17 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
TEST_F(ObjectTest, CreateMultiArray) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<2> hs(soa.Self());
- Handle<Class> c(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+ StackHandleScope<4> hs(soa.Self());
+ Handle<Class> int_class(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+ Handle<Class> int_array_class = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I"));
MutableHandle<IntArray> dims(hs.NewHandle(IntArray::Alloc(soa.Self(), 1)));
dims->Set<false>(0, 1);
- Array* multi = Array::CreateMultiArray(soa.Self(), c, dims);
- EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+ MutableHandle<Array> multi = hs.NewHandle(Array::CreateMultiArray(soa.Self(), int_class, dims));
+ EXPECT_OBJ_PTR_EQ(int_array_class.Get(), multi->GetClass());
EXPECT_EQ(1, multi->GetLength());
dims->Set<false>(0, -1);
- multi = Array::CreateMultiArray(soa.Self(), c, dims);
+ multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
EXPECT_EQ(mirror::Class::PrettyDescriptor(soa.Self()->GetException()->GetClass()),
"java.lang.NegativeArraySizeException");
@@ -336,12 +338,12 @@ TEST_F(ObjectTest, CreateMultiArray) {
for (int j = 0; j < 20; ++j) {
dims->Set<false>(0, i);
dims->Set<false>(1, j);
- multi = Array::CreateMultiArray(soa.Self(), c, dims);
+ multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[[I"));
EXPECT_EQ(i, multi->GetLength());
for (int k = 0; k < i; ++k) {
- Array* outer = multi->AsObjectArray<Array>()->Get(k);
- EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+ ObjPtr<Array> outer = multi->AsObjectArray<Array>()->Get(k);
+ EXPECT_OBJ_PTR_EQ(int_array_class.Get(), outer->GetClass());
EXPECT_EQ(j, outer->GetLength());
}
}
@@ -816,7 +818,7 @@ TEST_F(ObjectTest, PrettyTypeOf) {
ObjPtr<mirror::Class> c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
ASSERT_TRUE(c != nullptr);
- mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+ ObjPtr<mirror::Object> o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o));
EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass()));
}
diff --git a/runtime/mirror/reference-inl.h b/runtime/mirror/reference-inl.h
index 84e54948dd..f8de6e6d90 100644
--- a/runtime/mirror/reference-inl.h
+++ b/runtime/mirror/reference-inl.h
@@ -19,7 +19,6 @@
#include "reference.h"
-#include "gc_root-inl.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
@@ -49,12 +48,6 @@ inline void FinalizerReference::SetZombie(ObjPtr<Object> zombie) {
return SetFieldObjectVolatile<kTransactionActive>(ZombieOffset(), zombie);
}
-template<ReadBarrierOption kReadBarrierOption>
-inline Class* Reference::GetJavaLangRefReference() {
- DCHECK(!java_lang_ref_Reference_.IsNull());
- return java_lang_ref_Reference_.Read<kReadBarrierOption>();
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc
deleted file mode 100644
index 1d0b4c5b27..0000000000
--- a/runtime/mirror/reference.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "reference-inl.h"
-
-#include "art_method.h"
-#include "gc_root-inl.h"
-
-namespace art {
-namespace mirror {
-
-GcRoot<Class> Reference::java_lang_ref_Reference_;
-
-void Reference::SetClass(ObjPtr<Class> java_lang_ref_Reference) {
- CHECK(java_lang_ref_Reference_.IsNull());
- CHECK(java_lang_ref_Reference != nullptr);
- java_lang_ref_Reference_ = GcRoot<Class>(java_lang_ref_Reference);
-}
-
-void Reference::ResetClass() {
- CHECK(!java_lang_ref_Reference_.IsNull());
- java_lang_ref_Reference_ = GcRoot<Class>(nullptr);
-}
-
-void Reference::VisitRoots(RootVisitor* visitor) {
- java_lang_ref_Reference_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-} // namespace mirror
-} // namespace art
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index b10c29444e..63c5ae5ff8 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -20,8 +20,6 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
-#include "class.h"
-#include "gc_root.h"
#include "obj_ptr.h"
#include "object.h"
#include "read_barrier_option.h"
@@ -98,12 +96,6 @@ class MANAGED Reference : public Object {
return GetPendingNext<kWithoutReadBarrier>() == nullptr;
}
- template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- static ALWAYS_INLINE Class* GetJavaLangRefReference() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(ObjPtr<Class> klass);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
// Note: This avoids a read barrier, it should only be used by the GC.
HeapReference<Object>* GetReferentReferenceAddr() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -116,8 +108,6 @@ class MANAGED Reference : public Object {
HeapReference<Reference> queue_next_;
HeapReference<Object> referent_; // Note this is Java volatile:
- static GcRoot<Class> java_lang_ref_Reference_;
-
friend struct art::ReferenceOffsets; // for verifying offset information
friend class gc::ReferenceProcessor;
friend class gc::ReferenceQueue;
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index bb3242e035..5a7575a027 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -18,8 +18,8 @@
#include "class-inl.h"
#include "class.h"
+#include "class_root.h"
#include "gc/accounting/card_table-inl.h"
-#include "gc_root-inl.h"
#include "handle_scope-inl.h"
#include "object-inl.h"
#include "string.h"
@@ -27,26 +27,13 @@
namespace art {
namespace mirror {
-GcRoot<Class> StackTraceElement::java_lang_StackTraceElement_;
-
-void StackTraceElement::SetClass(ObjPtr<Class> java_lang_StackTraceElement) {
- CHECK(java_lang_StackTraceElement_.IsNull());
- CHECK(java_lang_StackTraceElement != nullptr);
- java_lang_StackTraceElement_ = GcRoot<Class>(java_lang_StackTraceElement);
-}
-
-void StackTraceElement::ResetClass() {
- CHECK(!java_lang_StackTraceElement_.IsNull());
- java_lang_StackTraceElement_ = GcRoot<Class>(nullptr);
-}
-
StackTraceElement* StackTraceElement::Alloc(Thread* self,
Handle<String> declaring_class,
Handle<String> method_name,
Handle<String> file_name,
int32_t line_number) {
ObjPtr<StackTraceElement> trace =
- ObjPtr<StackTraceElement>::DownCast(GetStackTraceElement()->AllocObject(self));
+ ObjPtr<StackTraceElement>::DownCast(GetClassRoot<StackTraceElement>()->AllocObject(self));
if (LIKELY(trace != nullptr)) {
if (Runtime::Current()->IsActiveTransaction()) {
trace->Init<true>(declaring_class.Get(), method_name.Get(), file_name.Get(), line_number);
@@ -72,10 +59,5 @@ void StackTraceElement::Init(ObjPtr<String> declaring_class,
line_number);
}
-void StackTraceElement::VisitRoots(RootVisitor* visitor) {
- java_lang_StackTraceElement_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 87e8a1f659..55a2ef0b49 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -17,7 +17,6 @@
#ifndef ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_
#define ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_
-#include "gc_root.h"
#include "object.h"
namespace art {
@@ -53,15 +52,6 @@ class MANAGED StackTraceElement FINAL : public Object {
int32_t line_number)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static void SetClass(ObjPtr<Class> java_lang_StackTraceElement);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* GetStackTraceElement() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_StackTraceElement_.IsNull());
- return java_lang_StackTraceElement_.Read();
- }
-
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
HeapReference<String> declaring_class_;
@@ -76,8 +66,6 @@ class MANAGED StackTraceElement FINAL : public Object {
int32_t line_number)
REQUIRES_SHARED(Locks::mutator_lock_);
- static GcRoot<Class> java_lang_StackTraceElement_;
-
friend struct art::StackTraceElementOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
};
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index a60861cc28..8fa2c6cf7f 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -25,6 +25,7 @@
#include "base/globals.h"
#include "base/utils.h"
#include "class.h"
+#include "class_root.h"
#include "common_throws.h"
#include "dex/utf.h"
#include "gc/heap-inl.h"
@@ -194,21 +195,6 @@ int32_t String::FastIndexOf(MemoryType* chars, int32_t ch, int32_t start) {
return -1;
}
-template<VerifyObjectFlags kVerifyFlags>
-inline size_t String::SizeOf() {
- size_t size = sizeof(String);
- if (IsCompressed()) {
- size += (sizeof(uint8_t) * GetLength<kVerifyFlags>());
- } else {
- size += (sizeof(uint16_t) * GetLength<kVerifyFlags>());
- }
- // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
- // so make sure the zero-padding is actually copied around if GC compaction
- // chooses to copy only SizeOf() bytes.
- // http://b/23528461
- return RoundUp(size, kObjectAlignment);
-}
-
template <bool kIsInstrumented, typename PreFenceVisitor>
inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
gc::AllocatorType allocator_type,
@@ -226,7 +212,8 @@ inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
// http://b/23528461
size_t alloc_size = RoundUp(size, kObjectAlignment);
- Class* string_class = GetJavaLangString();
+ Runtime* runtime = Runtime::Current();
+ ObjPtr<Class> string_class = GetClassRoot<String>(runtime->GetClassLinker());
// Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
// Do this by comparing with the maximum length that will _not_ cause an overflow.
const size_t overflow_length = (-header_size) / block_size; // Unsigned arithmetic.
@@ -242,7 +229,7 @@ inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
return nullptr;
}
- gc::Heap* heap = Runtime::Current()->GetHeap();
+ gc::Heap* heap = runtime->GetHeap();
return down_cast<String*>(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, string_class, alloc_size,
allocator_type, pre_fence_visitor));
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 6208a962e5..d5ef039273 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -24,7 +24,6 @@
#include "dex/descriptors_names.h"
#include "dex/utf-inl.h"
#include "gc/accounting/card_table-inl.h"
-#include "gc_root-inl.h"
#include "handle_scope-inl.h"
#include "intern_table.h"
#include "object-inl.h"
@@ -35,9 +34,6 @@
namespace art {
namespace mirror {
-// TODO: get global references for these
-GcRoot<Class> String::java_lang_String_;
-
int32_t String::FastIndexOf(int32_t ch, int32_t start) {
int32_t count = GetLength();
if (start < 0) {
@@ -52,18 +48,6 @@ int32_t String::FastIndexOf(int32_t ch, int32_t start) {
}
}
-void String::SetClass(ObjPtr<Class> java_lang_String) {
- CHECK(java_lang_String_.IsNull());
- CHECK(java_lang_String != nullptr);
- CHECK(java_lang_String->IsStringClass());
- java_lang_String_ = GcRoot<Class>(java_lang_String);
-}
-
-void String::ResetClass() {
- CHECK(!java_lang_String_.IsNull());
- java_lang_String_ = GcRoot<Class>(nullptr);
-}
-
int String::ComputeHashCode() {
int32_t hash_code = 0;
if (IsCompressed()) {
@@ -372,10 +356,6 @@ int32_t String::CompareTo(ObjPtr<String> rhs) {
return count_diff;
}
-void String::VisitRoots(RootVisitor* visitor) {
- java_lang_String_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
CharArray* String::ToCharArray(Thread* self) {
StackHandleScope<1> hs(self);
Handle<String> string(hs.NewHandle(this));
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 545fe93516..0e2fc903b5 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -17,8 +17,10 @@
#ifndef ART_RUNTIME_MIRROR_STRING_H_
#define ART_RUNTIME_MIRROR_STRING_H_
+#include "base/bit_utils.h"
+#include "base/globals.h"
#include "gc/allocator_type.h"
-#include "gc_root.h"
+#include "class.h"
#include "object.h"
namespace art {
@@ -65,7 +67,19 @@ class MANAGED String FINAL : public Object {
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_);
+ size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_) {
+ size_t size = sizeof(String);
+ if (IsCompressed()) {
+ size += (sizeof(uint8_t) * GetLength<kVerifyFlags>());
+ } else {
+ size += (sizeof(uint16_t) * GetLength<kVerifyFlags>());
+ }
+ // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
+ // so make sure the zero-padding is actually copied around if GC compaction
+ // chooses to copy only SizeOf() bytes.
+ // http://b/23528461
+ return RoundUp(size, kObjectAlignment);
+ }
// Taking out the first/uppermost bit because it is not part of actual length value
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -213,15 +227,6 @@ class MANAGED String FINAL : public Object {
: length;
}
- static Class* GetJavaLangString() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_String_.IsNull());
- return java_lang_String_.Read();
- }
-
- static void SetClass(ObjPtr<Class> java_lang_String) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
// "[[I" would be "int[][]", "[Ljava/lang/String;" would be
// "java.lang.String[]", and so forth.
@@ -266,10 +271,7 @@ class MANAGED String FINAL : public Object {
uint8_t value_compressed_[0];
};
- static GcRoot<Class> java_lang_String_;
-
friend struct art::StringOffsets; // for verifying offset information
- ART_FRIEND_TEST(art::StubTest, ReadBarrierForRoot); // For java_lang_String_.
DISALLOW_IMPLICIT_CONSTRUCTORS(String);
};
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 70069733d1..82e295a616 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -22,6 +22,7 @@
#include "base/enums.h"
#include "base/utils.h"
#include "class-inl.h"
+#include "class_root.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "object-inl.h"
@@ -36,8 +37,6 @@ namespace mirror {
using android::base::StringPrintf;
-GcRoot<Class> Throwable::java_lang_Throwable_;
-
void Throwable::SetDetailMessage(ObjPtr<String> new_detail_message) {
if (Runtime::Current()->IsActiveTransaction()) {
SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message);
@@ -128,8 +127,7 @@ std::string Throwable::Dump() {
} else {
ObjPtr<Object> stack_trace = GetStackTrace();
if (stack_trace != nullptr && stack_trace->IsObjectArray()) {
- CHECK_EQ(stack_trace->GetClass()->GetComponentType(),
- StackTraceElement::GetStackTraceElement());
+ CHECK_EQ(stack_trace->GetClass()->GetComponentType(), GetClassRoot<StackTraceElement>());
ObjPtr<ObjectArray<StackTraceElement>> ste_array =
ObjPtr<ObjectArray<StackTraceElement>>::DownCast(stack_trace);
if (ste_array->GetLength() == 0) {
@@ -159,21 +157,6 @@ std::string Throwable::Dump() {
return result;
}
-void Throwable::SetClass(ObjPtr<Class> java_lang_Throwable) {
- CHECK(java_lang_Throwable_.IsNull());
- CHECK(java_lang_Throwable != nullptr);
- java_lang_Throwable_ = GcRoot<Class>(java_lang_Throwable);
-}
-
-void Throwable::ResetClass() {
- CHECK(!java_lang_Throwable_.IsNull());
- java_lang_Throwable_ = GcRoot<Class>(nullptr);
-}
-
-void Throwable::VisitRoots(RootVisitor* visitor) {
- java_lang_Throwable_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
Object* Throwable::GetStackState() {
return GetFieldObjectVolatile<Object>(OFFSET_OF_OBJECT_MEMBER(Throwable, backtrace_));
}
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index b901ca2d00..a9e5d1a30b 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -17,7 +17,6 @@
#ifndef ART_RUNTIME_MIRROR_THROWABLE_H_
#define ART_RUNTIME_MIRROR_THROWABLE_H_
-#include "gc_root.h"
#include "object.h"
namespace art {
@@ -46,18 +45,8 @@ class MANAGED Throwable : public Object {
bool IsCheckedException() REQUIRES_SHARED(Locks::mutator_lock_);
bool IsError() REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* GetJavaLangThrowable() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_Throwable_.IsNull());
- return java_lang_Throwable_.Read();
- }
-
int32_t GetStackDepth() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(ObjPtr<Class> java_lang_Throwable);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
Object* GetStackState() REQUIRES_SHARED(Locks::mutator_lock_);
Object* GetStackTrace() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -69,8 +58,6 @@ class MANAGED Throwable : public Object {
HeapReference<Object> stack_trace_;
HeapReference<Object> suppressed_exceptions_;
- static GcRoot<Class> java_lang_Throwable_;
-
friend struct art::ThrowableOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);
};
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index c755299a79..4319c5df25 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -20,12 +20,13 @@
#include "art_field-inl.h"
#include "class-inl.h"
#include "class_linker.h"
-#include "gc_root-inl.h"
+#include "class_root.h"
#include "intrinsics_enum.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
#include "method_handles-inl.h"
#include "method_type.h"
+#include "obj_ptr-inl.h"
#include "well_known_classes.h"
namespace art {
@@ -265,31 +266,22 @@ int32_t BuildParameterArray(ObjPtr<Class> (&parameters)[VarHandle::kMaxAccessorP
// Returns the return type associated with an AccessModeTemplate based
// on the template and the variable type specified.
-Class* GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType)
+static ObjPtr<Class> GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(varType != nullptr);
switch (access_mode_template) {
case AccessModeTemplate::kCompareAndSet:
- return Runtime::Current()->GetClassLinker()->FindPrimitiveClass('Z');
+ return GetClassRoot(ClassRoot::kPrimitiveBoolean);
case AccessModeTemplate::kCompareAndExchange:
case AccessModeTemplate::kGet:
case AccessModeTemplate::kGetAndUpdate:
- return varType.Ptr();
+ return varType;
case AccessModeTemplate::kSet:
- return Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V');
+ return GetClassRoot(ClassRoot::kPrimitiveVoid);
}
return nullptr;
}
-ObjectArray<Class>* NewArrayOfClasses(Thread* self, int count)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Runtime* const runtime = Runtime::Current();
- ClassLinker* const class_linker = runtime->GetClassLinker();
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = class_linker->FindArrayClass(self, &class_type);
- return ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, count);
-}
-
// Method to insert a read barrier for accessors to reference fields.
inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> obj, MemberOffset field_offset)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1409,15 +1401,15 @@ class ByteArrayViewAccessor {
} // namespace
-Class* VarHandle::GetVarType() {
+ObjPtr<Class> VarHandle::GetVarType() {
return GetFieldObject<Class>(VarTypeOffset());
}
-Class* VarHandle::GetCoordinateType0() {
+ObjPtr<Class> VarHandle::GetCoordinateType0() {
return GetFieldObject<Class>(CoordinateType0Offset());
}
-Class* VarHandle::GetCoordinateType1() {
+ObjPtr<Class> VarHandle::GetCoordinateType1() {
return GetFieldObject<Class>(CoordinateType1Offset());
}
@@ -1437,7 +1429,7 @@ VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode acces
// Check return type first. If the return type of the method
// of the VarHandle is immaterial.
if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
- ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type.Ptr());
+ ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
if (vh_rtype != mt_rtype) {
if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
return MatchKind::kNone;
@@ -1512,9 +1504,9 @@ bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
return true;
}
-MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self,
- ObjPtr<VarHandle> var_handle,
- AccessMode access_mode) {
+ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
+ ObjPtr<VarHandle> var_handle,
+ AccessMode access_mode) {
// This is a static method as the var_handle might be moved by the GC during it's execution.
AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
@@ -1524,7 +1516,9 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self,
const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
vh->GetCoordinateType0(),
vh->GetCoordinateType1());
- Handle<ObjectArray<Class>> ptypes = hs.NewHandle(NewArrayOfClasses(self, ptypes_count));
+ ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>();
+ Handle<ObjectArray<Class>> ptypes =
+ hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
if (ptypes == nullptr) {
return nullptr;
}
@@ -1536,12 +1530,12 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self,
vh->GetCoordinateType0(),
vh->GetCoordinateType1());
for (int32_t i = 0; i < ptypes_count; ++i) {
- ptypes->Set(i, ptypes_array[i].Ptr());
+ ptypes->Set(i, ptypes_array[i]);
}
return MethodType::Create(self, rtype, ptypes);
}
-MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
+ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
return GetMethodTypeForAccessMode(self, this, access_mode);
}
@@ -1580,17 +1574,18 @@ bool VarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
const InstructionOperands* const operands,
JValue* result) {
- Class* klass = GetClass();
- if (klass == FieldVarHandle::StaticClass()) {
+ ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
+ ObjPtr<Class> klass = GetClass();
+ if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
auto vh = reinterpret_cast<FieldVarHandle*>(this);
return vh->Access(access_mode, shadow_frame, operands, result);
- } else if (klass == ArrayElementVarHandle::StaticClass()) {
+ } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
return vh->Access(access_mode, shadow_frame, operands, result);
- } else if (klass == ByteArrayViewVarHandle::StaticClass()) {
+ } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
return vh->Access(access_mode, shadow_frame, operands, result);
- } else if (klass == ByteBufferViewVarHandle::StaticClass()) {
+ } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
return vh->Access(access_mode, shadow_frame, operands, result);
} else {
@@ -1681,27 +1676,6 @@ bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* a
return true;
}
-Class* VarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
-}
-
-void VarHandle::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void VarHandle::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void VarHandle::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> VarHandle::static_class_;
-
ArtField* FieldVarHandle::GetField() {
uintptr_t opaque_field = static_cast<uintptr_t>(GetField64(ArtFieldOffset()));
return reinterpret_cast<ArtField*>(opaque_field);
@@ -1758,27 +1732,6 @@ bool FieldVarHandle::Access(AccessMode access_mode,
UNREACHABLE();
}
-Class* FieldVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
-}
-
-void FieldVarHandle::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void FieldVarHandle::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void FieldVarHandle::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> FieldVarHandle::static_class_;
-
bool ArrayElementVarHandle::Access(AccessMode access_mode,
ShadowFrame* shadow_frame,
const InstructionOperands* const operands,
@@ -1867,27 +1820,6 @@ bool ArrayElementVarHandle::Access(AccessMode access_mode,
UNREACHABLE();
}
-Class* ArrayElementVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
-}
-
-void ArrayElementVarHandle::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void ArrayElementVarHandle::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ArrayElementVarHandle::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ArrayElementVarHandle::static_class_;
-
bool ByteArrayViewVarHandle::GetNativeByteOrder() {
return GetFieldBoolean(NativeByteOrderOffset());
}
@@ -1976,27 +1908,6 @@ bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
UNREACHABLE();
}
-Class* ByteArrayViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
-}
-
-void ByteArrayViewVarHandle::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void ByteArrayViewVarHandle::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ByteArrayViewVarHandle::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ByteArrayViewVarHandle::static_class_;
-
bool ByteBufferViewVarHandle::GetNativeByteOrder() {
return GetFieldBoolean(NativeByteOrderOffset());
}
@@ -2117,26 +2028,5 @@ bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
UNREACHABLE();
}
-Class* ByteBufferViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
-}
-
-void ByteBufferViewVarHandle::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void ByteBufferViewVarHandle::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ByteBufferViewVarHandle::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ByteBufferViewVarHandle::static_class_;
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index 5186d43830..48c9d74e30 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -19,7 +19,6 @@
#include "handle.h"
#include "interpreter/shadow_frame.h"
-#include "gc_root.h"
#include "jvalue.h"
#include "object.h"
@@ -27,6 +26,7 @@ namespace art {
template<class T> class Handle;
class InstructionOperands;
+template<class T> class ObjPtr;
enum class Intrinsics;
@@ -121,7 +121,7 @@ class MANAGED VarHandle : public Object {
// AccessMode. No check is made for whether the AccessMode is a
// supported operation so the MethodType can be used when raising a
// WrongMethodTypeException exception.
- MethodType* GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
+ ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a string representing the descriptor of the MethodType associated with
@@ -136,7 +136,7 @@ class MANAGED VarHandle : public Object {
REQUIRES_SHARED(Locks::mutator_lock_);
// Gets the variable type that is operated on by this VarHandle instance.
- Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<Class> GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
// Gets the return type descriptor for a named accessor method,
// nullptr if accessor_method is not supported.
@@ -149,19 +149,14 @@ class MANAGED VarHandle : public Object {
// VarHandle access method, such as "setOpaque". Returns false otherwise.
static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
- Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
- static MethodType* GetMethodTypeForAccessMode(Thread* self,
- ObjPtr<VarHandle> var_handle,
- AccessMode access_mode)
+ static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
+ ObjPtr<VarHandle> var_handle,
+ AccessMode access_mode)
REQUIRES_SHARED(Locks::mutator_lock_);
static MemberOffset VarTypeOffset() {
@@ -185,9 +180,6 @@ class MANAGED VarHandle : public Object {
HeapReference<mirror::Class> var_type_;
int32_t access_modes_bit_mask_;
- // Root representing java.lang.invoke.VarHandle.class.
- static GcRoot<mirror::Class> static_class_;
-
friend class VarHandleTest; // for testing purposes
friend struct art::VarHandleOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(VarHandle);
@@ -218,9 +210,6 @@ class MANAGED FieldVarHandle : public VarHandle {
// ArtField instance corresponding to variable for accessors.
int64_t art_field_;
- // Root representing java.lang.invoke.FieldVarHandle.class.
- static GcRoot<mirror::Class> static_class_;
-
friend class VarHandleTest; // for var_handle_test.
friend struct art::FieldVarHandleOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
@@ -236,15 +225,7 @@ class MANAGED ArrayElementVarHandle : public VarHandle {
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- // Root representing java.lang.invoke.ArrayElementVarHandle.class.
- static GcRoot<mirror::Class> static_class_;
-
friend class VarHandleTest;
DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle);
};
@@ -261,11 +242,6 @@ class MANAGED ByteArrayViewVarHandle : public VarHandle {
bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
static MemberOffset NativeByteOrderOffset() {
return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
@@ -274,9 +250,6 @@ class MANAGED ByteArrayViewVarHandle : public VarHandle {
// Flag indicating that accessors should use native byte-ordering.
uint8_t native_byte_order_;
- // Root representing java.lang.invoke.ByteArrayViewVarHandle.class.
- static GcRoot<mirror::Class> static_class_;
-
friend class VarHandleTest; // for var_handle_test.
friend struct art::ByteArrayViewVarHandleOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle);
@@ -294,11 +267,6 @@ class MANAGED ByteBufferViewVarHandle : public VarHandle {
bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
bool AccessHeapBuffer(AccessMode access_mode,
ObjPtr<Object> byte_buffer,
@@ -322,9 +290,6 @@ class MANAGED ByteBufferViewVarHandle : public VarHandle {
// Flag indicating that accessors should use native byte-ordering.
uint8_t native_byte_order_;
- // Root representing java.lang.invoke.ByteBufferViewVarHandle.class.
- static GcRoot<mirror::Class> static_class_;
-
friend class VarHandleTest; // for var_handle_test.
friend struct art::ByteBufferViewVarHandleOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle);
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index 005aba3edd..9df96ddbd1 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -23,6 +23,7 @@
#include "class-inl.h"
#include "class_linker-inl.h"
#include "class_loader.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "jvalue-inl.h"
@@ -43,7 +44,7 @@ class VarHandleTest : public CommonRuntimeTest {
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<4> hs(self);
Handle<FieldVarHandle> fvh = hs.NewHandle(
- ObjPtr<FieldVarHandle>::DownCast(FieldVarHandle::StaticClass()->AllocObject(self)));
+ ObjPtr<FieldVarHandle>::DownCast(GetClassRoot<FieldVarHandle>()->AllocObject(self)));
Handle<Class> var_type = hs.NewHandle(art_field->ResolveType());
if (art_field->IsStatic()) {
@@ -67,7 +68,7 @@ class VarHandleTest : public CommonRuntimeTest {
StackHandleScope<3> hs(self);
Handle<ArrayElementVarHandle> vh = hs.NewHandle(
ObjPtr<ArrayElementVarHandle>::DownCast(
- ArrayElementVarHandle::StaticClass()->AllocObject(self)));
+ GetClassRoot<ArrayElementVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -85,14 +86,13 @@ class VarHandleTest : public CommonRuntimeTest {
StackHandleScope<4> hs(self);
Handle<ByteArrayViewVarHandle> bvh = hs.NewHandle(
ObjPtr<ByteArrayViewVarHandle>::DownCast(
- ByteArrayViewVarHandle::StaticClass()->AllocObject(self)));
+ GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class> var_type = hs.NewHandle(view_array_class->GetComponentType());
Handle<Class> index_type = hs.NewHandle(class_linker->FindPrimitiveClass('I'));
- ObjPtr<mirror::Class> byte_class = class_linker->FindPrimitiveClass('B');
- Handle<Class> byte_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &byte_class)));
+ Handle<Class> byte_array_class(hs.NewHandle(GetClassRoot<mirror::ByteArray>()));
InitializeVarHandle(bvh.Get(), var_type, byte_array_class, index_type, access_modes_bit_mask);
bvh->SetFieldBoolean<false>(ByteArrayViewVarHandle::NativeByteOrderOffset(), native_byte_order);
return bvh.Get();
@@ -106,7 +106,7 @@ class VarHandleTest : public CommonRuntimeTest {
StackHandleScope<5> hs(self);
Handle<ByteBufferViewVarHandle> bvh = hs.NewHandle(
ObjPtr<ByteBufferViewVarHandle>::DownCast(
- ByteArrayViewVarHandle::StaticClass()->AllocObject(self)));
+ GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class> var_type = hs.NewHandle(view_array_class->GetComponentType());
@@ -130,17 +130,17 @@ class VarHandleTest : public CommonRuntimeTest {
}
// Helper to get the VarType of a VarHandle.
- static Class* GetVarType(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
+ static ObjPtr<Class> GetVarType(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetVarType();
}
// Helper to get the CoordinateType0 of a VarHandle.
- static Class* GetCoordinateType0(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
+ static ObjPtr<Class> GetCoordinateType0(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetCoordinateType0();
}
// Helper to get the CoordinateType1 of a VarHandle.
- static Class* GetCoordinateType1(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
+ static ObjPtr<Class> GetCoordinateType1(VarHandle* vh) REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetCoordinateType1();
}
@@ -150,7 +150,7 @@ class VarHandleTest : public CommonRuntimeTest {
}
private:
- static void InitializeVarHandle(VarHandle* vh,
+ static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class> var_type,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -158,7 +158,7 @@ class VarHandleTest : public CommonRuntimeTest {
vh->SetField32<false>(VarHandle::AccessModesBitMaskOffset(), access_modes_bit_mask);
}
- static void InitializeVarHandle(VarHandle* vh,
+ static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class> var_type,
Handle<Class> coordinate_type0,
int32_t access_modes_bit_mask)
@@ -167,7 +167,7 @@ class VarHandleTest : public CommonRuntimeTest {
vh->SetFieldObject<false>(VarHandle::CoordinateType0Offset(), coordinate_type0.Get());
}
- static void InitializeVarHandle(VarHandle* vh,
+ static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class> var_type,
Handle<Class> coordinate_type0,
Handle<Class> coordinate_type1,
@@ -233,8 +233,7 @@ static MethodType* MethodTypeOf(const std::string& method_descriptor) {
ScopedObjectAccess soa(self);
StackHandleScope<3> hs(self);
int ptypes_count = static_cast<int>(descriptors.size()) - 1;
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = class_linker->FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
Handle<ObjectArray<Class>> ptypes = hs.NewHandle(
ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
@@ -598,10 +597,10 @@ TEST_F(VarHandleTest, ArrayElementVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXorRelease,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Handle<Class> string_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &string_class)));
- Handle<mirror::ArrayElementVarHandle> vh(hs.NewHandle(CreateArrayElementVarHandle(self, string_array_class, mask)));
+ Handle<mirror::Class> string_array_class = hs.NewHandle(
+ GetClassRoot<mirror::ObjectArray<mirror::String>>());
+ Handle<mirror::ArrayElementVarHandle> vh(
+ hs.NewHandle(CreateArrayElementVarHandle(self, string_array_class, mask)));
EXPECT_FALSE(vh.IsNull());
// Check access modes
@@ -745,11 +744,10 @@ TEST_F(VarHandleTest, ByteArrayViewVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> char_class = class_linker->FindPrimitiveClass('C');
- Handle<Class> char_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &char_class)));
+ Handle<Class> char_array_class(hs.NewHandle(GetClassRoot<mirror::CharArray>()));
const bool native_byte_order = true;
- Handle<mirror::ByteArrayViewVarHandle> vh(hs.NewHandle(CreateByteArrayViewVarHandle(self, char_array_class, native_byte_order, mask)));
+ Handle<mirror::ByteArrayViewVarHandle> vh(
+ hs.NewHandle(CreateByteArrayViewVarHandle(self, char_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
@@ -894,11 +892,10 @@ TEST_F(VarHandleTest, ByteBufferViewVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> double_class = class_linker->FindPrimitiveClass('D');
- Handle<Class> double_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &double_class)));
+ Handle<Class> double_array_class(hs.NewHandle(GetClassRoot<mirror::DoubleArray>()));
const bool native_byte_order = false;
- Handle<mirror::ByteBufferViewVarHandle> vh(hs.NewHandle(CreateByteBufferViewVarHandle(self, double_array_class, native_byte_order, mask)));
+ Handle<mirror::ByteBufferViewVarHandle> vh(hs.NewHandle(
+ CreateByteBufferViewVarHandle(self, double_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 6c820190b4..3227c69305 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,6 +32,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version);
#include "class_linker-inl.h"
#include "common_throws.h"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "gc/accounting/card_table-inl.h"
@@ -111,7 +112,7 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle
}
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class =
- runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
+ runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
@@ -138,7 +139,7 @@ static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaEleme
}
Runtime* runtime = Runtime::Current();
ObjPtr<mirror::Class> array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(),
- &element_class);
+ element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
@@ -573,30 +574,12 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
}
if (kPreloadDexCachesFieldsAndMethods) {
- for (size_t class_def_index = 0;
- class_def_index < dex_file->NumClassDefs();
- class_def_index++) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data == nullptr) {
- continue;
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ for (const ClassAccessor::Field& field : accessor.GetFields()) {
+ PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
}
- ClassDataItemIterator it(*dex_file, class_data);
- for (; it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- PreloadDexCachesResolveField(dex_cache, field_idx, true);
- }
- for (; it.HasNextInstanceField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- PreloadDexCachesResolveField(dex_cache, field_idx, false);
- }
- for (; it.HasNextDirectMethod(); it.Next()) {
- uint32_t method_idx = it.GetMemberIndex();
- PreloadDexCachesResolveMethod(dex_cache, method_idx);
- }
- for (; it.HasNextVirtualMethod(); it.Next()) {
- uint32_t method_idx = it.GetMemberIndex();
- PreloadDexCachesResolveMethod(dex_cache, method_idx);
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
}
}
}
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 38c65f5deb..5b47eaca86 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -100,7 +100,7 @@ class ClassSet {
}
void AddClass(ObjPtr<mirror::Class> klass) REQUIRES(Locks::mutator_lock_) {
- class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass.Ptr()));
+ class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
}
const std::unordered_set<jclass>& GetClasses() const {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 9f595b1c29..82e54e2f4c 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -22,6 +22,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_throws.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
@@ -82,7 +83,7 @@ static bool IsCallerTrusted(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_)
// is subject to change so conservatively cover the entire package.
// NB Static initializers within java.lang.invoke are permitted and do not
// need further stack inspection.
- ObjPtr<mirror::Class> lookup_class = mirror::MethodHandlesLookup::StaticClass();
+ ObjPtr<mirror::Class> lookup_class = GetClassRoot<mirror::MethodHandlesLookup>();
if ((declaring_class == lookup_class || declaring_class->IsInSamePackage(lookup_class))
&& !m->IsClassInitializer()) {
return true;
@@ -214,17 +215,9 @@ static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
}
-// TODO: Move this to mirror::Class ? Other mirror types that commonly appear
-// as arrays have a GetArrayClass() method.
-static ObjPtr<mirror::Class> GetClassArrayClass(Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- return Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_class);
-}
-
static jobjectArray Class_getInterfacesInternal(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- StackHandleScope<4> hs(soa.Self());
+ StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> klass = hs.NewHandle(DecodeClass(soa, javaThis));
if (klass->IsProxyClass()) {
@@ -236,10 +229,12 @@ static jobjectArray Class_getInterfacesInternal(JNIEnv* env, jobject javaThis) {
return nullptr;
}
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
const uint32_t num_ifaces = iface_list->Size();
- Handle<mirror::Class> class_array_class = hs.NewHandle(GetClassArrayClass(soa.Self()));
- Handle<mirror::ObjectArray<mirror::Class>> ifaces = hs.NewHandle(
- mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class.Get(), num_ifaces));
+ ObjPtr<mirror::Class> class_array_class =
+ GetClassRoot<mirror::ObjectArray<mirror::Class>>(linker);
+ ObjPtr<mirror::ObjectArray<mirror::Class>> ifaces =
+ mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, num_ifaces);
if (ifaces.IsNull()) {
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
@@ -249,20 +244,21 @@ static jobjectArray Class_getInterfacesInternal(JNIEnv* env, jobject javaThis) {
// with kActiveTransaction == false.
DCHECK(!Runtime::Current()->IsActiveTransaction());
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- MutableHandle<mirror::Class> interface(hs.NewHandle<mirror::Class>(nullptr));
for (uint32_t i = 0; i < num_ifaces; ++i) {
const dex::TypeIndex type_idx = iface_list->GetTypeItem(i).type_idx_;
- interface.Assign(linker->LookupResolvedType(type_idx, klass.Get()));
- ifaces->SetWithoutChecks<false>(i, interface.Get());
+ ObjPtr<mirror::Class> interface = linker->LookupResolvedType(type_idx, klass.Get());
+ DCHECK(interface != nullptr);
+ ifaces->SetWithoutChecks<false>(i, interface);
}
- return soa.AddLocalReference<jobjectArray>(ifaces.Get());
+ return soa.AddLocalReference<jobjectArray>(ifaces);
}
-static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
- Thread* self, ObjPtr<mirror::Class> klass, bool public_only, bool force_resolve)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+static ObjPtr<mirror::ObjectArray<mirror::Field>> GetDeclaredFields(
+ Thread* self,
+ ObjPtr<mirror::Class> klass,
+ bool public_only,
+ bool force_resolve) REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<1> hs(self);
IterationRange<StrideIterator<ArtField>> ifields = klass->GetIFields();
IterationRange<StrideIterator<ArtField>> sfields = klass->GetSFields();
@@ -281,7 +277,7 @@ static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
}
size_t array_idx = 0;
auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
- self, mirror::Field::ArrayClass(), array_size));
+ self, GetClassRoot<mirror::ObjectArray<mirror::Field>>(), array_size));
if (object_array == nullptr) {
return nullptr;
}
@@ -538,7 +534,7 @@ static jobjectArray Class_getDeclaredConstructorsInternal(
constructor_count += MethodMatchesConstructor(&m, public_only, enforce_hidden_api) ? 1u : 0u;
}
auto h_constructors = hs.NewHandle(mirror::ObjectArray<mirror::Constructor>::Alloc(
- soa.Self(), mirror::Constructor::ArrayClass(), constructor_count));
+ soa.Self(), GetClassRoot<mirror::ObjectArray<mirror::Constructor>>(), constructor_count));
if (UNLIKELY(h_constructors == nullptr)) {
soa.Self()->AssertPendingException();
return nullptr;
@@ -597,7 +593,7 @@ static jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaT
}
}
auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
- soa.Self(), mirror::Method::ArrayClass(), num_methods));
+ soa.Self(), GetClassRoot<mirror::ObjectArray<mirror::Method>>(), num_methods));
if (ret == nullptr) {
soa.Self()->AssertPendingOOMException();
return nullptr;
@@ -650,8 +646,8 @@ static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis)
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
- annotation_array_class.Ptr(),
- 0);
+ annotation_array_class,
+ /* length */ 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
@@ -671,10 +667,8 @@ static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) {
// Pending exception from GetDeclaredClasses.
return nullptr;
}
- ObjPtr<mirror::Class> class_array_class = GetClassArrayClass(soa.Self());
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::ObjectArray<mirror::Class>> empty_array =
mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
@@ -701,7 +695,7 @@ static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis
}
ObjPtr<mirror::Object> method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
- if (mirror::Constructor::StaticClass() == method->GetClass()) {
+ if (GetClassRoot<mirror::Constructor>() == method->GetClass()) {
return soa.AddLocalReference<jobject>(method);
}
}
@@ -717,7 +711,7 @@ static jobject Class_getEnclosingMethodNative(JNIEnv* env, jobject javaThis) {
}
ObjPtr<mirror::Object> method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
- if (mirror::Method::StaticClass() == method->GetClass()) {
+ if (GetClassRoot<mirror::Method>() == method->GetClass()) {
return soa.AddLocalReference<jobject>(method);
}
}
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 208ccf6a82..48540f877d 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -41,11 +41,6 @@ static void Object_notifyAll(JNIEnv* env, jobject java_this) {
soa.Decode<mirror::Object>(java_this)->NotifyAll(soa.Self());
}
-static void Object_wait(JNIEnv* env, jobject java_this) {
- ScopedFastNativeObjectAccess soa(env);
- soa.Decode<mirror::Object>(java_this)->Wait(soa.Self());
-}
-
static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
ScopedFastNativeObjectAccess soa(env);
soa.Decode<mirror::Object>(java_this)->Wait(soa.Self(), ms, ns);
@@ -61,7 +56,6 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"),
FAST_NATIVE_METHOD(Object, notify, "()V"),
FAST_NATIVE_METHOD(Object, notifyAll, "()V"),
- OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "()V", wait),
OVERLOADED_FAST_NATIVE_METHOD(Object, wait, "(JI)V", waitJI),
FAST_NATIVE_METHOD(Object, identityHashCodeNative, "(Ljava/lang/Object;)I"),
};
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 07e875efcb..3978ca8a36 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -19,7 +19,7 @@
#include "common_throws.h"
#include "jni/jni_internal.h"
#include "mirror/object-inl.h"
-#include "mirror/string.h"
+#include "mirror/string-inl.h"
#include "native_util.h"
#include "nativehelper/jni_macros.h"
#include "nativehelper/scoped_local_ref.h"
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 9edb0c21dd..13871f7be7 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -111,16 +111,15 @@ static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean ha
return -1; // Unreachable.
}
-static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject java_object) {
+static jboolean Thread_holdsLock(JNIEnv* env, jclass, jobject java_object) {
ScopedObjectAccess soa(env);
ObjPtr<mirror::Object> object = soa.Decode<mirror::Object>(java_object);
if (object == nullptr) {
ThrowNullPointerException("object == null");
return JNI_FALSE;
}
- MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
- Thread* thread = Thread::FromManagedThread(soa, java_thread);
- return thread->HoldsLock(object.Ptr());
+ Thread* thread = soa.Self();
+ return thread->HoldsLock(object);
}
static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
@@ -200,7 +199,7 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"),
NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"),
NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"),
- NATIVE_METHOD(Thread, nativeHoldsLock, "(Ljava/lang/Object;)Z"),
+ NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"),
FAST_NATIVE_METHOD(Thread, nativeInterrupt, "()V"),
NATIVE_METHOD(Thread, nativeSetName, "(Ljava/lang/String;)V"),
NATIVE_METHOD(Thread, nativeSetPriority, "(I)V"),
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 0630737d29..1ad233a6b2 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -20,6 +20,7 @@
#include "class_linker.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file_loader.h"
+#include "dex/utf.h"
#include "jni/jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
@@ -36,11 +37,11 @@ namespace art {
// A class so we can be friends with ClassLinker and access internal methods.
class VMClassLoader {
public:
- static mirror::Class* LookupClass(ClassLinker* cl,
- Thread* self,
- const char* descriptor,
- size_t hash,
- ObjPtr<mirror::ClassLoader> class_loader)
+ static ObjPtr<mirror::Class> LookupClass(ClassLinker* cl,
+ Thread* self,
+ const char* descriptor,
+ size_t hash,
+ ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_) {
return cl->LookupClass(self, descriptor, hash, class_loader);
@@ -85,7 +86,7 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa
}
// If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733.
if (c != nullptr && c->IsErroneous()) {
- cl->ThrowEarlierClassFailure(c.Ptr());
+ cl->ThrowEarlierClassFailure(c);
Thread* self = soa.Self();
ObjPtr<mirror::Class> iae_class =
self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass();
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 8bcda10f2a..452a66dca2 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -44,9 +44,8 @@ static jobject Array_createMultiArray(
Primitive::kPrimInt);
Handle<mirror::IntArray> dimensions_array(
hs.NewHandle(ObjPtr<mirror::IntArray>::DownCast(dimensions_obj)));
- mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(),
- element_class,
- dimensions_array);
+ ObjPtr<mirror::Array> new_array =
+ mirror::Array::CreateMultiArray(soa.Self(), element_class, dimensions_array);
return soa.AddLocalReference<jobject>(new_array);
}
@@ -57,16 +56,16 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl
ThrowNegativeArraySizeException(length);
return nullptr;
}
- ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(javaElementClass);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
- ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+ ObjPtr<mirror::Class> array_class =
+ class_linker->FindArrayClass(soa.Self(), soa.Decode<mirror::Class>(javaElementClass));
if (UNLIKELY(array_class == nullptr)) {
CHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
DCHECK(array_class->IsObjectArrayClass());
- ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+ ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
soa.Self(),
array_class,
length,
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 13a8d28267..a961cb2597 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -20,8 +20,8 @@
#include "art_method-inl.h"
#include "base/enums.h"
-#include "class_linker-inl.h"
#include "class_linker.h"
+#include "class_root.h"
#include "dex/dex_file_annotations.h"
#include "jni/jni_internal.h"
#include "mirror/class-inl.h"
@@ -42,12 +42,8 @@ static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMetho
annotations::GetExceptionTypesForMethod(method);
if (result_array == nullptr) {
// Return an empty array instead of a null pointer.
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> class_array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::ObjectArray<mirror::Class>> empty_array =
mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index 9a2d3020c0..a10db9115f 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -20,6 +20,7 @@
#include "nativehelper/jni_macros.h"
#include "art_method-inl.h"
+#include "class_root.h"
#include "dex/dex_file_annotations.h"
#include "handle.h"
#include "jni/jni_internal.h"
@@ -319,7 +320,7 @@ static jstring Executable_getMethodNameInternal(JNIEnv* env, jobject javaMethod)
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- return soa.AddLocalReference<jstring>(method->GetNameAsString(soa.Self()));
+ return soa.AddLocalReference<jstring>(method->ResolveNameString());
}
static jclass Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMethod) {
@@ -335,15 +336,6 @@ static jclass Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMe
return soa.AddLocalReference<jclass>(return_type);
}
-// TODO: Move this to mirror::Class ? Other mirror types that commonly appear
-// as arrays have a GetArrayClass() method. This is duplicated in
-// java_lang_Class.cc as well.
-static ObjPtr<mirror::Class> GetClassArrayClass(Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- return Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_class);
-}
-
static jobjectArray Executable_getParameterTypesInternal(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
@@ -356,10 +348,10 @@ static jobjectArray Executable_getParameterTypesInternal(JNIEnv* env, jobject ja
const uint32_t num_params = params->Size();
- StackHandleScope<3> hs(soa.Self());
- Handle<mirror::Class> class_array_class = hs.NewHandle(GetClassArrayClass(soa.Self()));
+ StackHandleScope<2> hs(soa.Self());
+ ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
Handle<mirror::ObjectArray<mirror::Class>> ptypes = hs.NewHandle(
- mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class.Get(), num_params));
+ mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, num_params));
if (ptypes.IsNull()) {
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 25599843e9..895b2f9fd7 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -464,8 +464,7 @@ static jlong Field_getArtField(JNIEnv* env, jobject javaField) {
static jstring Field_getNameInternal(JNIEnv* env, jobject javaField) {
ScopedFastNativeObjectAccess soa(env);
ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
- return soa.AddLocalReference<jstring>(
- field->GetStringName(soa.Self(), true /* resolve */));
+ return soa.AddLocalReference<jstring>(field->ResolveNameString());
}
static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
@@ -476,7 +475,7 @@ static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField)
ObjPtr<mirror::Class> annotation_array_class =
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Ptr(), 0);
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForField(field));
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 52e04941c6..87fda6bf5d 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -22,6 +22,7 @@
#include "base/enums.h"
#include "class_linker-inl.h"
#include "class_linker.h"
+#include "class_root.h"
#include "dex/dex_file_annotations.h"
#include "jni/jni_internal.h"
#include "mirror/class-inl.h"
@@ -66,13 +67,9 @@ static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) {
annotations::GetExceptionTypesForMethod(method);
if (result_array == nullptr) {
// Return an empty array instead of a null pointer
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> class_array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
- if (class_array_class == nullptr) {
- return nullptr;
- }
- mirror::ObjectArray<mirror::Class>* empty_array =
+ ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
+ DCHECK(class_array_class != nullptr);
+ ObjPtr<mirror::ObjectArray<mirror::Class>> empty_array =
mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
} else {
diff --git a/runtime/oat.h b/runtime/oat.h
index 7b8f71a3f3..e7e5848dd6 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: Refactor stackmap encoding.
- static constexpr uint8_t kOatVersion[] = { '1', '4', '4', '\0' };
+ // Last oat version changed reason: Rewrite dex register map encoding.
+ static constexpr uint8_t kOatVersion[] = { '1', '4', '6', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 4e0bf890db..946ea018f3 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -44,9 +44,9 @@ TEST_F(ProxyTest, ProxyClassHelper) {
ASSERT_TRUE(I != nullptr);
ASSERT_TRUE(J != nullptr);
- std::vector<mirror::Class*> interfaces;
- interfaces.push_back(I.Get());
- interfaces.push_back(J.Get());
+ std::vector<Handle<mirror::Class>> interfaces;
+ interfaces.push_back(I);
+ interfaces.push_back(J);
Handle<mirror::Class> proxy_class(hs.NewHandle(
GenerateProxyClass(soa, jclass_loader, class_linker_, "$Proxy1234", interfaces)));
interfaces.clear(); // Don't least possibly stale objects in the array as good practice.
@@ -80,9 +80,9 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
Handle<mirror::Class> proxyClass;
{
- std::vector<mirror::Class*> interfaces;
- interfaces.push_back(I.Get());
- interfaces.push_back(J.Get());
+ std::vector<Handle<mirror::Class>> interfaces;
+ interfaces.push_back(I);
+ interfaces.push_back(J);
proxyClass = hs.NewHandle(
GenerateProxyClass(soa, jclass_loader, class_linker_, "$Proxy1234", interfaces));
}
@@ -131,7 +131,7 @@ TEST_F(ProxyTest, CheckArtMirrorFieldsOfProxyStaticFields) {
Handle<mirror::Class> proxyClass0;
Handle<mirror::Class> proxyClass1;
{
- std::vector<mirror::Class*> interfaces;
+ std::vector<Handle<mirror::Class>> interfaces;
proxyClass0 = hs.NewHandle(
GenerateProxyClass(soa, jclass_loader, class_linker_, "$Proxy0", interfaces));
proxyClass1 = hs.NewHandle(
diff --git a/runtime/proxy_test.h b/runtime/proxy_test.h
index 98362649f5..411dc7af82 100644
--- a/runtime/proxy_test.h
+++ b/runtime/proxy_test.h
@@ -22,8 +22,10 @@
#include "art_method-inl.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "mirror/class-inl.h"
#include "mirror/method.h"
+#include "obj_ptr-inl.h"
namespace art {
namespace proxy_test {
@@ -31,35 +33,36 @@ namespace proxy_test {
// Generate a proxy class with the given name and interfaces. This is a simplification from what
// libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
// we do not declare exceptions.
-mirror::Class* GenerateProxyClass(ScopedObjectAccess& soa,
- jobject jclass_loader,
- ClassLinker* class_linker,
- const char* className,
- const std::vector<mirror::Class*>& interfaces)
+ObjPtr<mirror::Class> GenerateProxyClass(ScopedObjectAccess& soa,
+ jobject jclass_loader,
+ ClassLinker* class_linker,
+ const char* className,
+ const std::vector<Handle<mirror::Class>>& interfaces)
REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::Class> javaLangObject = hs.NewHandle(
- class_linker->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
+ Handle<mirror::Class> javaLangObject = hs.NewHandle(GetClassRoot<mirror::Object>());
CHECK(javaLangObject != nullptr);
- jclass javaLangClass = soa.AddLocalReference<jclass>(mirror::Class::GetJavaLangClass());
+ jclass javaLangClass = soa.AddLocalReference<jclass>(GetClassRoot<mirror::Class>());
// Builds the interfaces array.
- jobjectArray proxyClassInterfaces = soa.Env()->NewObjectArray(interfaces.size(), javaLangClass,
- nullptr);
+ jobjectArray proxyClassInterfaces =
+ soa.Env()->NewObjectArray(interfaces.size(), javaLangClass, /* initialElement */ nullptr);
soa.Self()->AssertNoPendingException();
for (size_t i = 0; i < interfaces.size(); ++i) {
soa.Env()->SetObjectArrayElement(proxyClassInterfaces, i,
- soa.AddLocalReference<jclass>(interfaces[i]));
+ soa.AddLocalReference<jclass>(interfaces[i].Get()));
}
// Builds the method array.
jsize methods_count = 3; // Object.equals, Object.hashCode and Object.toString.
- for (mirror::Class* interface : interfaces) {
+ for (Handle<mirror::Class> interface : interfaces) {
methods_count += interface->NumVirtualMethods();
}
jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
- methods_count, soa.AddLocalReference<jclass>(mirror::Method::StaticClass()), nullptr);
+ methods_count,
+ soa.AddLocalReference<jclass>(GetClassRoot<mirror::Method>()),
+ /* initialElement */ nullptr);
soa.Self()->AssertNoPendingException();
jsize array_index = 0;
@@ -90,7 +93,7 @@ mirror::Class* GenerateProxyClass(ScopedObjectAccess& soa,
proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
// Now adds all interfaces virtual methods.
- for (mirror::Class* interface : interfaces) {
+ for (Handle<mirror::Class> interface : interfaces) {
for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
soa.Env()->SetObjectArrayElement(
proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
@@ -103,9 +106,13 @@ mirror::Class* GenerateProxyClass(ScopedObjectAccess& soa,
jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
soa.Self()->AssertNoPendingException();
- mirror::Class* proxyClass = class_linker->CreateProxyClass(
- soa, soa.Env()->NewStringUTF(className), proxyClassInterfaces, jclass_loader,
- proxyClassMethods, proxyClassThrows);
+ ObjPtr<mirror::Class> proxyClass = class_linker->CreateProxyClass(
+ soa,
+ soa.Env()->NewStringUTF(className),
+ proxyClassInterfaces,
+ jclass_loader,
+ proxyClassMethods,
+ proxyClassThrows);
soa.Self()->AssertNoPendingException();
return proxyClass;
}
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index de613d3b20..4f4abf7f7f 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -232,7 +232,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
DCHECK(catch_stack_map.IsValid());
DexRegisterMap catch_vreg_map =
code_info.GetDexRegisterMapOf(catch_stack_map, number_of_vregs);
- if (!catch_vreg_map.IsValid()) {
+ if (!catch_vreg_map.IsValid() || !catch_vreg_map.HasAnyLiveDexRegisters()) {
return;
}
@@ -246,8 +246,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
// Copy values between them.
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind catch_location =
- catch_vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
+ DexRegisterLocation::Kind catch_location = catch_vreg_map.GetLocationKind(vreg);
if (catch_location == DexRegisterLocation::Kind::kNone) {
continue;
}
@@ -255,9 +254,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
// Get vreg value from its current location.
uint32_t vreg_value;
- VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg,
- number_of_vregs,
- code_info));
+ VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg));
bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
vreg,
vreg_kind,
@@ -268,9 +265,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
<< "native_pc_offset=" << stack_visitor->GetNativePcOffset() << ")";
// Copy value to the catch phi's stack slot.
- int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg,
- number_of_vregs,
- code_info);
+ int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg);
ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
@@ -425,21 +420,18 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
continue;
}
- DexRegisterLocation::Kind location =
- vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
+ DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
static constexpr uint32_t kDeadValue = 0xEBADDE09;
uint32_t value = kDeadValue;
bool is_reference = false;
switch (location) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg,
- number_of_vregs,
- code_info);
+ const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg);
const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
value = *reinterpret_cast<const uint32_t*>(addr);
uint32_t bit = (offset >> 2);
- if (bit < code_info.GetNumberOfStackMaskBits() && stack_mask.LoadBit(bit)) {
+ if (bit < stack_mask.size_in_bits() && stack_mask.LoadBit(bit)) {
is_reference = true;
}
break;
@@ -448,7 +440,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = vreg_map.GetMachineRegister(vreg, number_of_vregs, code_info);
+ uint32_t reg = vreg_map.GetMachineRegister(vreg);
bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
CHECK(result);
if (location == DexRegisterLocation::Kind::kInRegister) {
@@ -459,7 +451,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
break;
}
case DexRegisterLocation::Kind::kConstant: {
- value = vreg_map.GetConstant(vreg, number_of_vregs, code_info);
+ value = vreg_map.GetConstant(vreg);
if (value == 0) {
// Make it a reference for extra safety.
is_reference = true;
@@ -472,9 +464,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
default: {
LOG(FATAL)
<< "Unexpected location kind "
- << vreg_map.GetLocationInternalKind(vreg,
- number_of_vregs,
- code_info);
+ << vreg_map.GetLocationInternalKind(vreg);
UNREACHABLE();
}
}
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 06ea384aa3..1d54d21187 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -106,7 +106,7 @@ TEST_F(ReferenceTableTest, Basics) {
}
// Add a second object 10 times and check dumping is sane.
- mirror::Object* o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
+ ObjPtr<mirror::Object> o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
for (size_t i = 0; i < 10; ++i) {
rt.Add(o2);
EXPECT_EQ(i + 2, rt.Size());
@@ -276,23 +276,26 @@ TEST_F(ReferenceTableTest, SummaryOrder) {
ReferenceTable rt("test", 0, 20);
{
- mirror::Object* s1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello");
- mirror::Object* s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::String> s1 =
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
+ ObjPtr<mirror::String> s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
// 3 copies of s1, 2 copies of s2, interleaved.
for (size_t i = 0; i != 2; ++i) {
- rt.Add(s1);
+ rt.Add(s1.Get());
rt.Add(s2);
}
- rt.Add(s1);
+ rt.Add(s1.Get());
}
{
- // Differently sized byte arrays. Should be sorted by identical (non-unique cound).
- mirror::Object* b1_1 = mirror::ByteArray::Alloc(soa.Self(), 1);
- rt.Add(b1_1);
+ // Differently sized byte arrays. Should be sorted by identical (non-unique count).
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::ByteArray> b1_1 = hs.NewHandle(mirror::ByteArray::Alloc(soa.Self(), 1));
+ rt.Add(b1_1.Get());
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
- rt.Add(b1_1);
+ rt.Add(b1_1.Get());
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 1));
rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index 26fb021903..9fe4bca9dd 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -121,7 +121,7 @@ inline bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class>
if (UNLIKELY(o == nullptr)) {
ThrowNullPointerException("null receiver");
return false;
- } else if (UNLIKELY(!o->InstanceOf(c.Ptr()))) {
+ } else if (UNLIKELY(!o->InstanceOf(c))) {
InvalidReceiverError(o, c);
return false;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 66eba1e1d4..6aeedd4f02 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -243,7 +243,7 @@ class ArgArray {
// we've seen cases where it's not b/34440020.
ObjPtr<mirror::Class> dst_class(
m->ResolveClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_));
- if (dst_class.Ptr() == nullptr) {
+ if (dst_class == nullptr) {
CHECK(self->IsExceptionPending());
return false;
}
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index d2d720f722..424ee0681a 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -80,7 +80,7 @@ class ReflectionTest : public CommonCompilerTest {
jclass GetPrimitiveClass(char descriptor) {
ScopedObjectAccess soa(env_);
- mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
+ ObjPtr<mirror::Class> c = class_linker_->FindPrimitiveClass(descriptor);
CHECK(c != nullptr);
return soa.AddLocalReference<jclass>(c);
}
@@ -518,7 +518,7 @@ TEST_F(ReflectionTest, StaticMainMethod) {
hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
- mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
+ ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
ASSERT_TRUE(klass != nullptr);
ArtMethod* method = klass->FindClassMethod("main",
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 14027493d8..0d9d16cd01 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -67,6 +67,7 @@
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "compiler_callbacks.h"
#include "debugger.h"
#include "dex/art_dex_file_loader.h"
@@ -736,8 +737,9 @@ bool Runtime::Start() {
ScopedObjectAccess soa(self);
StackHandleScope<2> hs(soa.Self());
- auto class_class(hs.NewHandle<mirror::Class>(mirror::Class::GetJavaLangClass()));
- auto field_class(hs.NewHandle<mirror::Class>(mirror::Field::StaticClass()));
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassLinker()->GetClassRoots();
+ auto class_class(hs.NewHandle<mirror::Class>(GetClassRoot<mirror::Class>(class_roots)));
+ auto field_class(hs.NewHandle<mirror::Class>(GetClassRoot<mirror::Field>(class_roots)));
class_linker_->EnsureInitialized(soa.Self(), class_class, true, true);
// Field class is needed for register_java_net_InetAddress in libcore, b/28153851.
@@ -1974,36 +1976,6 @@ mirror::Throwable* Runtime::GetPreAllocatedNoClassDefFoundError() {
}
void Runtime::VisitConstantRoots(RootVisitor* visitor) {
- // Visit the classes held as static in mirror classes, these can be visited concurrently and only
- // need to be visited once per GC since they never change.
- mirror::Class::VisitRoots(visitor);
- mirror::Constructor::VisitRoots(visitor);
- mirror::Reference::VisitRoots(visitor);
- mirror::Method::VisitRoots(visitor);
- mirror::StackTraceElement::VisitRoots(visitor);
- mirror::String::VisitRoots(visitor);
- mirror::Throwable::VisitRoots(visitor);
- mirror::Field::VisitRoots(visitor);
- mirror::MethodType::VisitRoots(visitor);
- mirror::MethodHandleImpl::VisitRoots(visitor);
- mirror::MethodHandlesLookup::VisitRoots(visitor);
- mirror::EmulatedStackFrame::VisitRoots(visitor);
- mirror::ClassExt::VisitRoots(visitor);
- mirror::CallSite::VisitRoots(visitor);
- mirror::VarHandle::VisitRoots(visitor);
- mirror::FieldVarHandle::VisitRoots(visitor);
- mirror::ArrayElementVarHandle::VisitRoots(visitor);
- mirror::ByteArrayViewVarHandle::VisitRoots(visitor);
- mirror::ByteBufferViewVarHandle::VisitRoots(visitor);
- // Visit all the primitive array types classes.
- mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor); // BooleanArray
- mirror::PrimitiveArray<int8_t>::VisitRoots(visitor); // ByteArray
- mirror::PrimitiveArray<uint16_t>::VisitRoots(visitor); // CharArray
- mirror::PrimitiveArray<double>::VisitRoots(visitor); // DoubleArray
- mirror::PrimitiveArray<float>::VisitRoots(visitor); // FloatArray
- mirror::PrimitiveArray<int32_t>::VisitRoots(visitor); // IntArray
- mirror::PrimitiveArray<int64_t>::VisitRoots(visitor); // LongArray
- mirror::PrimitiveArray<int16_t>::VisitRoots(visitor); // ShortArray
// Visiting the roots of these ArtMethods is not currently required since all the GcRoots are
// null.
BufferedRootVisitor<16> buffered_visitor(visitor, RootInfo(kRootVMInternal));
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 8cb0700ce2..6da7dcb697 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -245,13 +245,10 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
if (!dex_register_map.IsValid()) {
return false;
}
- DexRegisterLocation::Kind location_kind =
- dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info);
+ DexRegisterLocation::Kind location_kind = dex_register_map.GetLocationKind(vreg);
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg,
- number_of_dex_registers,
- code_info);
+ const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
*val = *reinterpret_cast<const uint32_t*>(addr);
return true;
@@ -260,21 +257,18 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg =
- dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info);
+ uint32_t reg = dex_register_map.GetMachineRegister(vreg);
return GetRegisterIfAccessible(reg, kind, val);
}
case DexRegisterLocation::Kind::kConstant:
- *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info);
+ *val = dex_register_map.GetConstant(vreg);
return true;
case DexRegisterLocation::Kind::kNone:
return false;
default:
LOG(FATAL)
<< "Unexpected location kind "
- << dex_register_map.GetLocationInternalKind(vreg,
- number_of_dex_registers,
- code_info);
+ << dex_register_map.GetLocationInternalKind(vreg);
UNREACHABLE();
}
}
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 2b7e8dd748..923bb3559a 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -16,6 +16,7 @@
#include "stack_map.h"
+#include <iomanip>
#include <stdint.h>
#include "art_method.h"
@@ -24,158 +25,102 @@
namespace art {
-constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
-
-std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind) {
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
using Kind = DexRegisterLocation::Kind;
- switch (kind) {
+ switch (reg.GetKind()) {
case Kind::kNone:
- return stream << "none";
+ return stream << "None";
case Kind::kInStack:
- return stream << "in stack";
+ return stream << "sp+" << reg.GetValue();
case Kind::kInRegister:
- return stream << "in register";
+ return stream << "r" << reg.GetValue();
case Kind::kInRegisterHigh:
- return stream << "in register high";
+ return stream << "r" << reg.GetValue() << "/hi";
case Kind::kInFpuRegister:
- return stream << "in fpu register";
+ return stream << "f" << reg.GetValue();
case Kind::kInFpuRegisterHigh:
- return stream << "in fpu register high";
+ return stream << "f" << reg.GetValue() << "/hi";
case Kind::kConstant:
- return stream << "as constant";
- case Kind::kInStackLargeOffset:
- return stream << "in stack (large offset)";
- case Kind::kConstantLargeValue:
- return stream << "as constant (large value)";
+ return stream << "#" << reg.GetValue();
+ default:
+ return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
+ << "," << reg.GetValue() << ")";
}
- return stream << "Kind<" << static_cast<uint32_t>(kind) << ">";
-}
-
-DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(
- uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- DexRegisterLocationCatalog dex_register_location_catalog =
- code_info.GetDexRegisterLocationCatalog();
- size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
- dex_register_number,
- number_of_dex_registers,
- code_info.GetNumberOfLocationCatalogEntries());
- return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
-}
-
-DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- DexRegisterLocationCatalog dex_register_location_catalog =
- code_info.GetDexRegisterLocationCatalog();
- size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
- dex_register_number,
- number_of_dex_registers,
- code_info.GetNumberOfLocationCatalogEntries());
- return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
}
-static void DumpRegisterMapping(std::ostream& os,
- size_t dex_register_num,
- DexRegisterLocation location,
- const std::string& prefix = "v",
- const std::string& suffix = "") {
- os << prefix << dex_register_num << ": "
- << location.GetInternalKind()
- << " (" << location.GetValue() << ")" << suffix << '\n';
-}
-
-void StackMap::DumpEncoding(const BitTable<6>& table,
- VariableIndentationOutputStream* vios) {
- vios->Stream()
- << "StackMapEncoding"
- << " (NativePcOffsetBits=" << table.NumColumnBits(kNativePcOffset)
- << ", DexPcBits=" << table.NumColumnBits(kDexPc)
- << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
- << ", InlineInfoIndexBits=" << table.NumColumnBits(kInlineInfoIndex)
- << ", RegisterMaskIndexBits=" << table.NumColumnBits(kRegisterMaskIndex)
- << ", StackMaskIndexBits=" << table.NumColumnBits(kStackMaskIndex)
- << ")\n";
+static void DumpDexRegisterMap(VariableIndentationOutputStream* vios,
+ const DexRegisterMap& map) {
+ if (map.IsValid()) {
+ ScopedIndentation indent1(vios);
+ for (size_t i = 0; i < map.size(); ++i) {
+ if (map.IsDexRegisterLive(i)) {
+ vios->Stream() << "v" << i << ":" << map.Get(i) << " ";
+ }
+ }
+ vios->Stream() << "\n";
+ }
}
-void InlineInfo::DumpEncoding(const BitTable<5>& table,
- VariableIndentationOutputStream* vios) {
- vios->Stream()
- << "InlineInfoEncoding"
- << " (IsLastBits=" << table.NumColumnBits(kIsLast)
- << ", MethodIndexIdxBits=" << table.NumColumnBits(kMethodIndexIdx)
- << ", DexPcBits=" << table.NumColumnBits(kDexPc)
- << ", ExtraDataBits=" << table.NumColumnBits(kExtraData)
- << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
- << ")\n";
+template<uint32_t kNumColumns>
+static void DumpTable(VariableIndentationOutputStream* vios,
+ const char* table_name,
+ const BitTable<kNumColumns>& table,
+ bool verbose,
+ bool is_mask = false) {
+ if (table.NumRows() != 0) {
+ vios->Stream() << table_name << " BitSize=" << table.NumRows() * table.NumRowBits();
+ vios->Stream() << " Rows=" << table.NumRows() << " Bits={";
+ for (size_t c = 0; c < table.NumColumns(); c++) {
+ vios->Stream() << (c != 0 ? " " : "");
+ vios->Stream() << table.NumColumnBits(c);
+ }
+ vios->Stream() << "}\n";
+ if (verbose) {
+ ScopedIndentation indent1(vios);
+ for (size_t r = 0; r < table.NumRows(); r++) {
+ vios->Stream() << "[" << std::right << std::setw(3) << r << "]={";
+ for (size_t c = 0; c < table.NumColumns(); c++) {
+ vios->Stream() << (c != 0 ? " " : "");
+ if (is_mask) {
+ BitMemoryRegion bits = table.GetBitMemoryRegion(r, c);
+ for (size_t b = 0, e = bits.size_in_bits(); b < e; b++) {
+ vios->Stream() << bits.LoadBit(e - b - 1);
+ }
+ } else {
+ vios->Stream() << std::right << std::setw(8) << static_cast<int32_t>(table.Get(r, c));
+ }
+ }
+ vios->Stream() << "}\n";
+ }
+ }
+ }
}
void CodeInfo::Dump(VariableIndentationOutputStream* vios,
uint32_t code_offset,
- uint16_t number_of_dex_registers,
- bool dump_stack_maps,
+ uint16_t num_dex_registers,
+ bool verbose,
InstructionSet instruction_set,
const MethodInfo& method_info) const {
- size_t number_of_stack_maps = GetNumberOfStackMaps();
vios->Stream()
- << "Optimized CodeInfo (number_of_dex_registers=" << number_of_dex_registers
- << ", number_of_stack_maps=" << number_of_stack_maps
- << ")\n";
+ << "CodeInfo"
+ << " BitSize=" << size_ * kBitsPerByte
+ << "\n";
ScopedIndentation indent1(vios);
- StackMap::DumpEncoding(stack_maps_, vios);
- if (HasInlineInfo()) {
- InlineInfo::DumpEncoding(inline_infos_, vios);
- }
- // Display the Dex register location catalog.
- GetDexRegisterLocationCatalog().Dump(vios, *this);
+ DumpTable(vios, "StackMaps", stack_maps_, verbose);
+ DumpTable(vios, "RegisterMasks", register_masks_, verbose);
+ DumpTable(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
+ DumpTable(vios, "InvokeInfos", invoke_infos_, verbose);
+ DumpTable(vios, "InlineInfos", inline_infos_, verbose);
+ DumpTable(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
+ DumpTable(vios, "DexRegisterMaps", dex_register_maps_, verbose);
+ DumpTable(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
+
// Display stack maps along with (live) Dex register maps.
- if (dump_stack_maps) {
- for (size_t i = 0; i < number_of_stack_maps; ++i) {
+ if (verbose) {
+ for (size_t i = 0; i < GetNumberOfStackMaps(); ++i) {
StackMap stack_map = GetStackMapAt(i);
- stack_map.Dump(vios,
- *this,
- method_info,
- code_offset,
- number_of_dex_registers,
- instruction_set,
- " " + std::to_string(i));
- }
- }
- // TODO: Dump the stack map's inline information? We need to know more from the caller:
- // we need to know the number of dex registers for each inlined method.
-}
-
-void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
- const CodeInfo& code_info) {
- size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
- size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
- vios->Stream()
- << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
- << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
- for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
- DexRegisterLocation location = GetDexRegisterLocation(i);
- ScopedIndentation indent1(vios);
- DumpRegisterMapping(vios->Stream(), i, location, "entry ");
- }
-}
-
-void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
- const CodeInfo& code_info,
- uint16_t number_of_dex_registers) const {
- size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
- // TODO: Display the bit mask of live Dex registers.
- for (size_t j = 0; j < number_of_dex_registers; ++j) {
- if (IsDexRegisterLive(j)) {
- size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
- j, number_of_dex_registers, number_of_location_catalog_entries);
- DexRegisterLocation location = GetDexRegisterLocation(j,
- number_of_dex_registers,
- code_info);
- ScopedIndentation indent1(vios);
- DumpRegisterMapping(
- vios->Stream(), j, location, "v",
- "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
+ stack_map.Dump(vios, *this, method_info, code_offset, num_dex_registers, instruction_set);
}
}
}
@@ -185,30 +130,22 @@ void StackMap::Dump(VariableIndentationOutputStream* vios,
const MethodInfo& method_info,
uint32_t code_offset,
uint16_t number_of_dex_registers,
- InstructionSet instruction_set,
- const std::string& header_suffix) const {
+ InstructionSet instruction_set) const {
const uint32_t pc_offset = GetNativePcOffset(instruction_set);
vios->Stream()
- << "StackMap" << header_suffix
+ << "StackMap[" << Row() << "]"
<< std::hex
- << " [native_pc=0x" << code_offset + pc_offset << "]"
- << " (dex_pc=0x" << GetDexPc()
- << ", native_pc_offset=0x" << pc_offset
- << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset()
- << ", inline_info_offset=0x" << GetInlineInfoIndex()
+ << " (native_pc=0x" << code_offset + pc_offset
+ << ", dex_pc=0x" << GetDexPc()
<< ", register_mask=0x" << code_info.GetRegisterMaskOf(*this)
<< std::dec
<< ", stack_mask=0b";
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(*this);
- for (size_t i = 0, e = code_info.GetNumberOfStackMaskBits(); i < e; ++i) {
+ for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
vios->Stream() << stack_mask.LoadBit(e - i - 1);
}
vios->Stream() << ")\n";
- if (HasDexRegisterMap()) {
- DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
- *this, number_of_dex_registers);
- dex_register_map.Dump(vios, code_info, number_of_dex_registers);
- }
+ DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this, number_of_dex_registers));
if (HasInlineInfo()) {
InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
// We do not know the length of the dex register maps of inlined frames
@@ -222,15 +159,12 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
const MethodInfo& method_info,
uint16_t number_of_dex_registers[]) const {
- vios->Stream() << "InlineInfo with depth "
- << static_cast<uint32_t>(GetDepth())
- << "\n";
-
for (size_t i = 0; i < GetDepth(); ++i) {
vios->Stream()
- << " At depth " << i
+ << "InlineInfo[" << Row() + i << "]"
+ << " (depth=" << i
<< std::hex
- << " (dex_pc=0x" << GetDexPcAtDepth(i);
+ << ", dex_pc=0x" << GetDexPcAtDepth(i);
if (EncodesArtMethodAtDepth(i)) {
ScopedObjectAccess soa(Thread::Current());
vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
@@ -240,11 +174,9 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios,
<< ", method_index=" << GetMethodIndexAtDepth(method_info, i);
}
vios->Stream() << ")\n";
- if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
- DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
- ScopedIndentation indent1(vios);
- dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
+ if (number_of_dex_registers != nullptr) {
+ uint16_t vregs = number_of_dex_registers[i];
+ DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(i, *this, vregs));
}
}
}
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 91cecf0690..9aac204e70 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -19,7 +19,6 @@
#include <limits>
-#include "arch/code_offset.h"
#include "base/bit_memory_region.h"
#include "base/bit_table.h"
#include "base/bit_utils.h"
@@ -27,6 +26,7 @@
#include "base/leb128.h"
#include "base/memory_region.h"
#include "dex/dex_file_types.h"
+#include "dex_register_location.h"
#include "method_info.h"
#include "oat_quick_method_header.h"
@@ -42,538 +42,76 @@ static constexpr ssize_t kFrameSlotSize = 4;
class ArtMethod;
class CodeInfo;
-/**
- * Classes in the following file are wrapper on stack map information backed
- * by a MemoryRegion. As such they read and write to the region, they don't have
- * their own fields.
- */
-
-// Dex register location container used by DexRegisterMap and StackMapStream.
-class DexRegisterLocation {
- public:
- /*
- * The location kind used to populate the Dex register information in a
- * StackMapStream can either be:
- * - kStack: vreg stored on the stack, value holds the stack offset;
- * - kInRegister: vreg stored in low 32 bits of a core physical register,
- * value holds the register number;
- * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register,
- * value holds the register number;
- * - kInFpuRegister: vreg stored in low 32 bits of an FPU register,
- * value holds the register number;
- * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register,
- * value holds the register number;
- * - kConstant: value holds the constant;
- *
- * In addition, DexRegisterMap also uses these values:
- * - kInStackLargeOffset: value holds a "large" stack offset (greater than
- * or equal to 128 bytes);
- * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
- * or greater than or equal to 32);
- * - kNone: the register has no location, meaning it has not been set.
- */
- enum class Kind : uint8_t {
- // Short location kinds, for entries fitting on one byte (3 bits
- // for the kind, 5 bits for the value) in a DexRegisterMap.
- kInStack = 0, // 0b000
- kInRegister = 1, // 0b001
- kInRegisterHigh = 2, // 0b010
- kInFpuRegister = 3, // 0b011
- kInFpuRegisterHigh = 4, // 0b100
- kConstant = 5, // 0b101
-
- // Large location kinds, requiring a 5-byte encoding (1 byte for the
- // kind, 4 bytes for the value).
-
- // Stack location at a large offset, meaning that the offset value
- // divided by the stack frame slot size (4 bytes) cannot fit on a
- // 5-bit unsigned integer (i.e., this offset value is greater than
- // or equal to 2^5 * 4 = 128 bytes).
- kInStackLargeOffset = 6, // 0b110
-
- // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
- // lower than 0, or greater than or equal to 2^5 = 32).
- kConstantLargeValue = 7, // 0b111
-
- // Entries with no location are not stored and do not need own marker.
- kNone = static_cast<uint8_t>(-1),
-
- kLastLocationKind = kConstantLargeValue
- };
-
- static_assert(
- sizeof(Kind) == 1u,
- "art::DexRegisterLocation::Kind has a size different from one byte.");
-
- static bool IsShortLocationKind(Kind kind) {
- switch (kind) {
- case Kind::kInStack:
- case Kind::kInRegister:
- case Kind::kInRegisterHigh:
- case Kind::kInFpuRegister:
- case Kind::kInFpuRegisterHigh:
- case Kind::kConstant:
- return true;
-
- case Kind::kInStackLargeOffset:
- case Kind::kConstantLargeValue:
- return false;
-
- case Kind::kNone:
- LOG(FATAL) << "Unexpected location kind";
- }
- UNREACHABLE();
- }
-
- // Convert `kind` to a "surface" kind, i.e. one that doesn't include
- // any value with a "large" qualifier.
- // TODO: Introduce another enum type for the surface kind?
- static Kind ConvertToSurfaceKind(Kind kind) {
- switch (kind) {
- case Kind::kInStack:
- case Kind::kInRegister:
- case Kind::kInRegisterHigh:
- case Kind::kInFpuRegister:
- case Kind::kInFpuRegisterHigh:
- case Kind::kConstant:
- return kind;
-
- case Kind::kInStackLargeOffset:
- return Kind::kInStack;
-
- case Kind::kConstantLargeValue:
- return Kind::kConstant;
-
- case Kind::kNone:
- return kind;
- }
- UNREACHABLE();
- }
-
- // Required by art::StackMapStream::LocationCatalogEntriesIndices.
- DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
-
- DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
-
- static DexRegisterLocation None() {
- return DexRegisterLocation(Kind::kNone, 0);
- }
-
- // Get the "surface" kind of the location, i.e., the one that doesn't
- // include any value with a "large" qualifier.
- Kind GetKind() const {
- return ConvertToSurfaceKind(kind_);
- }
-
- // Get the value of the location.
- int32_t GetValue() const { return value_; }
-
- // Get the actual kind of the location.
- Kind GetInternalKind() const { return kind_; }
-
- bool operator==(DexRegisterLocation other) const {
- return kind_ == other.kind_ && value_ == other.value_;
- }
-
- bool operator!=(DexRegisterLocation other) const {
- return !(*this == other);
- }
-
- private:
- Kind kind_;
- int32_t value_;
-
- friend class DexRegisterLocationHashFn;
-};
-
-std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind);
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg);
-/**
- * Store information on unique Dex register locations used in a method.
- * The information is of the form:
- *
- * [DexRegisterLocation+].
- *
- * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
- */
-class DexRegisterLocationCatalog {
+// Information on Dex register locations for a specific PC.
+// Effectively just a convenience wrapper for DexRegisterLocation vector.
+// If the size is small enough, it keeps the data on the stack.
+class DexRegisterMap {
public:
- explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
-
- // Short (compressed) location, fitting on one byte.
- typedef uint8_t ShortLocation;
-
- void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
- DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
- int32_t value = dex_register_location.GetValue();
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Compress the kind and the value as a single byte.
- if (kind == DexRegisterLocation::Kind::kInStack) {
- // Instead of storing stack offsets expressed in bytes for
- // short stack locations, store slot offsets. A stack offset
- // is a multiple of 4 (kFrameSlotSize). This means that by
- // dividing it by 4, we can fit values from the [0, 128)
- // interval in a short stack location, and not just values
- // from the [0, 32) interval.
- DCHECK_EQ(value % kFrameSlotSize, 0);
- value /= kFrameSlotSize;
- }
- DCHECK(IsShortValue(value)) << value;
- region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
- } else {
- // Large location. Write the location on one byte and the value
- // on 4 bytes.
- DCHECK(!IsShortValue(value)) << value;
- if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
- // Also divide large stack offsets by 4 for the sake of consistency.
- DCHECK_EQ(value % kFrameSlotSize, 0);
- value /= kFrameSlotSize;
- }
- // Data can be unaligned as the written Dex register locations can
- // either be 1-byte or 5-byte wide. Use
- // art::MemoryRegion::StoreUnaligned instead of
- // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
- region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
- region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
- }
- }
-
- // Find the offset of the location catalog entry number `location_catalog_entry_index`.
- size_t FindLocationOffset(size_t location_catalog_entry_index) const {
- size_t offset = kFixedSize;
- // Skip the first `location_catalog_entry_index - 1` entries.
- for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
- // Read the first next byte and inspect its first 3 bits to decide
- // whether it is a short or a large location.
- DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Skip the current byte.
- offset += SingleShortEntrySize();
- } else {
- // Large location. Skip the 5 next bytes.
- offset += SingleLargeEntrySize();
- }
- }
- return offset;
- }
-
- // Get the internal kind of entry at `location_catalog_entry_index`.
- DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
- if (location_catalog_entry_index == kNoLocationEntryIndex) {
- return DexRegisterLocation::Kind::kNone;
- }
- return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
- }
-
- // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
- DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
- if (location_catalog_entry_index == kNoLocationEntryIndex) {
- return DexRegisterLocation::None();
- }
- size_t offset = FindLocationOffset(location_catalog_entry_index);
- // Read the first byte and inspect its first 3 bits to get the location.
- ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
- DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Extract the value from the remaining 5 bits.
- int32_t value = ExtractValueFromShortLocation(first_byte);
- if (kind == DexRegisterLocation::Kind::kInStack) {
- // Convert the stack slot (short) offset to a byte offset value.
- value *= kFrameSlotSize;
- }
- return DexRegisterLocation(kind, value);
+ // Create map for given number of registers and initialize all locations to None.
+ explicit DexRegisterMap(size_t count) : count_(count), regs_small_{} {
+ if (count_ <= kSmallCount) {
+ std::fill_n(regs_small_.begin(), count, DexRegisterLocation::None());
} else {
- // Large location. Read the four next bytes to get the value.
- int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
- if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
- // Convert the stack slot (large) offset to a byte offset value.
- value *= kFrameSlotSize;
- }
- return DexRegisterLocation(kind, value);
+ regs_large_.resize(count, DexRegisterLocation::None());
}
}
- // Compute the compressed kind of `location`.
- static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
- DexRegisterLocation::Kind kind = location.GetInternalKind();
- switch (kind) {
- case DexRegisterLocation::Kind::kInStack:
- return IsShortStackOffsetValue(location.GetValue())
- ? DexRegisterLocation::Kind::kInStack
- : DexRegisterLocation::Kind::kInStackLargeOffset;
-
- case DexRegisterLocation::Kind::kInRegister:
- case DexRegisterLocation::Kind::kInRegisterHigh:
- DCHECK_GE(location.GetValue(), 0);
- DCHECK_LT(location.GetValue(), 1 << kValueBits);
- return kind;
-
- case DexRegisterLocation::Kind::kInFpuRegister:
- case DexRegisterLocation::Kind::kInFpuRegisterHigh:
- DCHECK_GE(location.GetValue(), 0);
- DCHECK_LT(location.GetValue(), 1 << kValueBits);
- return kind;
-
- case DexRegisterLocation::Kind::kConstant:
- return IsShortConstantValue(location.GetValue())
- ? DexRegisterLocation::Kind::kConstant
- : DexRegisterLocation::Kind::kConstantLargeValue;
-
- case DexRegisterLocation::Kind::kConstantLargeValue:
- case DexRegisterLocation::Kind::kInStackLargeOffset:
- case DexRegisterLocation::Kind::kNone:
- LOG(FATAL) << "Unexpected location kind " << kind;
- }
- UNREACHABLE();
- }
-
- // Can `location` be turned into a short location?
- static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
- DexRegisterLocation::Kind kind = location.GetInternalKind();
- switch (kind) {
- case DexRegisterLocation::Kind::kInStack:
- return IsShortStackOffsetValue(location.GetValue());
-
- case DexRegisterLocation::Kind::kInRegister:
- case DexRegisterLocation::Kind::kInRegisterHigh:
- case DexRegisterLocation::Kind::kInFpuRegister:
- case DexRegisterLocation::Kind::kInFpuRegisterHigh:
- return true;
-
- case DexRegisterLocation::Kind::kConstant:
- return IsShortConstantValue(location.GetValue());
-
- case DexRegisterLocation::Kind::kConstantLargeValue:
- case DexRegisterLocation::Kind::kInStackLargeOffset:
- case DexRegisterLocation::Kind::kNone:
- LOG(FATAL) << "Unexpected location kind " << kind;
- }
- UNREACHABLE();
- }
-
- static size_t EntrySize(const DexRegisterLocation& location) {
- return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
- }
-
- static size_t SingleShortEntrySize() {
- return sizeof(ShortLocation);
- }
-
- static size_t SingleLargeEntrySize() {
- return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
- }
-
- size_t Size() const {
- return region_.size();
- }
-
- void Dump(VariableIndentationOutputStream* vios,
- const CodeInfo& code_info);
-
- // Special (invalid) Dex register location catalog entry index meaning
- // that there is no location for a given Dex register (i.e., it is
- // mapped to a DexRegisterLocation::Kind::kNone location).
- static constexpr size_t kNoLocationEntryIndex = -1;
-
- private:
- static constexpr int kFixedSize = 0;
-
- // Width of the kind "field" in a short location, in bits.
- static constexpr size_t kKindBits = 3;
- // Width of the value "field" in a short location, in bits.
- static constexpr size_t kValueBits = 5;
-
- static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
- static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
- static constexpr size_t kKindOffset = 0;
- static constexpr size_t kValueOffset = kKindBits;
-
- static bool IsShortStackOffsetValue(int32_t value) {
- DCHECK_EQ(value % kFrameSlotSize, 0);
- return IsShortValue(value / kFrameSlotSize);
+ DexRegisterLocation* data() {
+ return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data();
}
- static bool IsShortConstantValue(int32_t value) {
- return IsShortValue(value);
- }
+ size_t size() const { return count_; }
- static bool IsShortValue(int32_t value) {
- return IsUint<kValueBits>(value);
- }
+ bool IsValid() const { return count_ != 0; }
- static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
- uint8_t kind_integer_value = static_cast<uint8_t>(kind);
- DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
- DCHECK(IsShortValue(value)) << value;
- return (kind_integer_value & kKindMask) << kKindOffset
- | (value & kValueMask) << kValueOffset;
+ DexRegisterLocation Get(size_t index) const {
+ DCHECK_LT(index, count_);
+ return count_ <= kSmallCount ? regs_small_[index] : regs_large_[index];
}
- static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
- uint8_t kind = (location >> kKindOffset) & kKindMask;
- DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
- // We do not encode kNone locations in the stack map.
- DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
- return static_cast<DexRegisterLocation::Kind>(kind);
+ DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number) const {
+ return Get(dex_register_number).GetKind();
}
- static int32_t ExtractValueFromShortLocation(ShortLocation location) {
- return (location >> kValueOffset) & kValueMask;
+ // TODO: Remove.
+ DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number) const {
+ return Get(dex_register_number).GetKind();
}
- // Extract a location kind from the byte at position `offset`.
- DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
- ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
- return ExtractKindFromShortLocation(first_byte);
+ DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number) const {
+ return Get(dex_register_number);
}
- MemoryRegion region_;
-
- friend class CodeInfo;
- friend class StackMapStream;
-};
-
-/* Information on Dex register locations for a specific PC, mapping a
- * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
- * The information is of the form:
- *
- * [live_bit_mask, entries*]
- *
- * where entries are concatenated unsigned integer values encoded on a number
- * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
- * on the number of entries in the Dex register location catalog
- * (see DexRegisterMap::SingleEntrySizeInBits). The map is 1-byte aligned.
- */
-class DexRegisterMap {
- public:
- explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
- DexRegisterMap() {}
-
- bool IsValid() const { return region_.IsValid(); }
-
- // Get the surface kind of Dex register `dex_register_number`.
- DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- return DexRegisterLocation::ConvertToSurfaceKind(
- GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info));
- }
-
- // Get the internal kind of Dex register `dex_register_number`.
- DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const;
-
- // Get the Dex register location `dex_register_number`.
- DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const;
-
- int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
+ int32_t GetStackOffsetInBytes(uint16_t dex_register_number) const {
+ DexRegisterLocation location = Get(dex_register_number);
DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
- // GetDexRegisterLocation returns the offset in bytes.
return location.GetValue();
}
- int32_t GetConstant(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
- DCHECK_EQ(location.GetKind(), DexRegisterLocation::Kind::kConstant);
+ int32_t GetConstant(uint16_t dex_register_number) const {
+ DexRegisterLocation location = Get(dex_register_number);
+ DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
return location.GetValue();
}
- int32_t GetMachineRegister(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- const CodeInfo& code_info) const {
- DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
- DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister ||
- location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
- location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister ||
- location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh)
- << location.GetInternalKind();
+ int32_t GetMachineRegister(uint16_t dex_register_number) const {
+ DexRegisterLocation location = Get(dex_register_number);
+ DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInRegister ||
+ location.GetKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
+ location.GetKind() == DexRegisterLocation::Kind::kInFpuRegister ||
+ location.GetKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh);
return location.GetValue();
}
- // Get the index of the entry in the Dex register location catalog
- // corresponding to `dex_register_number`.
- size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
- uint16_t number_of_dex_registers,
- size_t number_of_location_catalog_entries) const {
- if (!IsDexRegisterLive(dex_register_number)) {
- return DexRegisterLocationCatalog::kNoLocationEntryIndex;
- }
-
- if (number_of_location_catalog_entries == 1) {
- // We do not allocate space for location maps in the case of a
- // single-entry location catalog, as it is useless. The only valid
- // entry index is 0;
- return 0;
- }
-
- // The bit offset of the beginning of the map locations.
- size_t map_locations_offset_in_bits =
- GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
- size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
- DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
- // The bit size of an entry.
- size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
- // The bit offset where `index_in_dex_register_map` is located.
- size_t entry_offset_in_bits =
- map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
- size_t location_catalog_entry_index =
- region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
- DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
- return location_catalog_entry_index;
- }
-
- // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
- void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
- size_t location_catalog_entry_index,
- uint16_t number_of_dex_registers,
- size_t number_of_location_catalog_entries) {
- DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
- DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
-
- if (number_of_location_catalog_entries == 1) {
- // We do not allocate space for location maps in the case of a
- // single-entry location catalog, as it is useless.
- return;
- }
-
- // The bit offset of the beginning of the map locations.
- size_t map_locations_offset_in_bits =
- GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
- // The bit size of an entry.
- size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
- // The bit offset where `index_in_dex_register_map` is located.
- size_t entry_offset_in_bits =
- map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
- region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
- }
-
- void SetLiveBitMask(uint16_t number_of_dex_registers,
- const BitVector& live_dex_registers_mask) {
- size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
- for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
- region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
- }
- }
-
ALWAYS_INLINE bool IsDexRegisterLive(uint16_t dex_register_number) const {
- size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
- return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
+ return Get(dex_register_number).IsLive();
}
- size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
+ size_t GetNumberOfLiveDexRegisters() const {
size_t number_of_live_dex_registers = 0;
- for (size_t i = 0; i < number_of_dex_registers; ++i) {
+ for (size_t i = 0; i < count_; ++i) {
if (IsDexRegisterLive(i)) {
++number_of_live_dex_registers;
}
@@ -581,70 +119,22 @@ class DexRegisterMap {
return number_of_live_dex_registers;
}
- static size_t GetLiveBitMaskOffset() {
- return kFixedSize;
- }
-
- // Compute the size of the live register bit mask (in bytes), for a
- // method having `number_of_dex_registers` Dex registers.
- static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
- return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
- }
-
- static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
- return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
- }
-
- size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
- size_t number_of_location_catalog_entries) const {
- size_t location_mapping_data_size_in_bits =
- GetNumberOfLiveDexRegisters(number_of_dex_registers)
- * SingleEntrySizeInBits(number_of_location_catalog_entries);
- return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
- }
-
- // Return the size of a map entry in bits. Note that if
- // `number_of_location_catalog_entries` equals 1, this function returns 0,
- // which is fine, as there is no need to allocate a map for a
- // single-entry location catalog; the only valid location catalog entry index
- // for a live register in this case is 0 and there is no need to
- // store it.
- static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
- // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
- return number_of_location_catalog_entries == 0
- ? 0u
- : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
- }
-
- // Return the size of the DexRegisterMap object, in bytes.
- size_t Size() const {
- return BitsToBytesRoundUp(region_.size_in_bits());
- }
-
- void Dump(VariableIndentationOutputStream* vios,
- const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
-
- private:
- // Return the index in the Dex register map corresponding to the Dex
- // register number `dex_register_number`.
- size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
- if (!IsDexRegisterLive(dex_register_number)) {
- return kInvalidIndexInDexRegisterMap;
+ bool HasAnyLiveDexRegisters() const {
+ for (size_t i = 0; i < count_; ++i) {
+ if (IsDexRegisterLive(i)) {
+ return true;
+ }
}
- return GetNumberOfLiveDexRegisters(dex_register_number);
+ return false;
}
- // Special (invalid) Dex register map entry index meaning that there
- // is no index in the map for a given Dex register (i.e., it must
- // have been mapped to a DexRegisterLocation::Kind::kNone location).
- static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
-
- static constexpr int kFixedSize = 0;
-
- BitMemoryRegion region_;
-
- friend class CodeInfo;
- friend class StackMapStream;
+ private:
+ // Store the data inline if the number of registers is small to avoid memory allocations.
+ // If count_ <= kSmallCount, we use the regs_small_ array, and regs_large_ otherwise.
+ static constexpr size_t kSmallCount = 16;
+ size_t count_;
+ std::array<DexRegisterLocation, kSmallCount> regs_small_;
+ dchecked_vector<DexRegisterLocation> regs_large_;
};
/**
@@ -655,15 +145,16 @@ class DexRegisterMap {
* - Knowing the inlining information,
* - Knowing the values of dex registers.
*/
-class StackMap : public BitTable<6>::Accessor {
+class StackMap : public BitTable<7>::Accessor {
public:
enum Field {
- kNativePcOffset,
+ kPackedNativePc,
kDexPc,
- kDexRegisterMapOffset,
- kInlineInfoIndex,
kRegisterMaskIndex,
kStackMaskIndex,
+ kInlineInfoIndex,
+ kDexRegisterMaskIndex,
+ kDexRegisterMapIndex,
kCount,
};
@@ -672,14 +163,15 @@ class StackMap : public BitTable<6>::Accessor {
: BitTable<kCount>::Accessor(table, row) {}
ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
- CodeOffset offset(CodeOffset::FromCompressedOffset(Get<kNativePcOffset>()));
- return offset.Uint32Value(instruction_set);
+ return UnpackNativePc(Get<kPackedNativePc>(), instruction_set);
}
uint32_t GetDexPc() const { return Get<kDexPc>(); }
- uint32_t GetDexRegisterMapOffset() const { return Get<kDexRegisterMapOffset>(); }
- bool HasDexRegisterMap() const { return GetDexRegisterMapOffset() != kNoValue; }
+ uint32_t GetDexRegisterMaskIndex() const { return Get<kDexRegisterMaskIndex>(); }
+
+ uint32_t GetDexRegisterMapIndex() const { return Get<kDexRegisterMapIndex>(); }
+ bool HasDexRegisterMap() const { return GetDexRegisterMapIndex() != kNoValue; }
uint32_t GetInlineInfoIndex() const { return Get<kInlineInfoIndex>(); }
bool HasInlineInfo() const { return GetInlineInfoIndex() != kNoValue; }
@@ -688,14 +180,23 @@ class StackMap : public BitTable<6>::Accessor {
uint32_t GetStackMaskIndex() const { return Get<kStackMaskIndex>(); }
- static void DumpEncoding(const BitTable<6>& table, VariableIndentationOutputStream* vios);
+ static uint32_t PackNativePc(uint32_t native_pc, InstructionSet isa) {
+ DCHECK_ALIGNED_PARAM(native_pc, GetInstructionSetInstructionAlignment(isa));
+ return native_pc / GetInstructionSetInstructionAlignment(isa);
+ }
+
+ static uint32_t UnpackNativePc(uint32_t packed_native_pc, InstructionSet isa) {
+ uint32_t native_pc = packed_native_pc * GetInstructionSetInstructionAlignment(isa);
+ DCHECK_EQ(native_pc / GetInstructionSetInstructionAlignment(isa), packed_native_pc);
+ return native_pc;
+ }
+
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
const MethodInfo& method_info,
uint32_t code_offset,
uint16_t number_of_dex_registers,
- InstructionSet instruction_set,
- const std::string& header_suffix = "") const;
+ InstructionSet instruction_set) const;
};
/**
@@ -703,14 +204,16 @@ class StackMap : public BitTable<6>::Accessor {
* The row referenced from the StackMap holds information at depth 0.
* Following rows hold information for further depths.
*/
-class InlineInfo : public BitTable<5>::Accessor {
+class InlineInfo : public BitTable<7>::Accessor {
public:
enum Field {
kIsLast, // Determines if there are further rows for further depths.
- kMethodIndexIdx, // Method index or ArtMethod high bits.
kDexPc,
- kExtraData, // ArtMethod low bits or 1.
- kDexRegisterMapOffset,
+ kMethodIndexIdx,
+ kArtMethodHi, // High bits of ArtMethod*.
+ kArtMethodLo, // Low bits of ArtMethod*.
+ kDexRegisterMaskIndex,
+ kDexRegisterMapIndex,
kCount,
};
static constexpr uint32_t kLast = -1;
@@ -743,30 +246,26 @@ class InlineInfo : public BitTable<5>::Accessor {
}
bool EncodesArtMethodAtDepth(uint32_t depth) const {
- return (AtDepth(depth).Get<kExtraData>() & 1) == 0;
+ return AtDepth(depth).Get<kArtMethodLo>() != kNoValue;
}
ArtMethod* GetArtMethodAtDepth(uint32_t depth) const {
- uint32_t low_bits = AtDepth(depth).Get<kExtraData>();
- uint32_t high_bits = AtDepth(depth).Get<kMethodIndexIdx>();
- if (high_bits == 0) {
- return reinterpret_cast<ArtMethod*>(low_bits);
- } else {
- uint64_t address = high_bits;
- address = address << 32;
- return reinterpret_cast<ArtMethod*>(address | low_bits);
- }
+ uint64_t lo = AtDepth(depth).Get<kArtMethodLo>();
+ uint64_t hi = AtDepth(depth).Get<kArtMethodHi>();
+ return reinterpret_cast<ArtMethod*>((hi << 32) | lo);
}
- uint32_t GetDexRegisterMapOffsetAtDepth(uint32_t depth) const {
- return AtDepth(depth).Get<kDexRegisterMapOffset>();
+ uint32_t GetDexRegisterMaskIndexAtDepth(uint32_t depth) const {
+ return AtDepth(depth).Get<kDexRegisterMaskIndex>();
}
+ uint32_t GetDexRegisterMapIndexAtDepth(uint32_t depth) const {
+ return AtDepth(depth).Get<kDexRegisterMapIndex>();
+ }
bool HasDexRegisterMapAtDepth(uint32_t depth) const {
- return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoValue;
+ return GetDexRegisterMapIndexAtDepth(depth) != kNoValue;
}
- static void DumpEncoding(const BitTable<5>& table, VariableIndentationOutputStream* vios);
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& info,
const MethodInfo& method_info,
@@ -776,7 +275,7 @@ class InlineInfo : public BitTable<5>::Accessor {
class InvokeInfo : public BitTable<3>::Accessor {
public:
enum Field {
- kNativePcOffset,
+ kPackedNativePc,
kInvokeType,
kMethodIndexIdx,
kCount,
@@ -786,8 +285,7 @@ class InvokeInfo : public BitTable<3>::Accessor {
: BitTable<kCount>::Accessor(table, row) {}
ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
- CodeOffset offset(CodeOffset::FromCompressedOffset(Get<kNativePcOffset>()));
- return offset.Uint32Value(instruction_set);
+ return StackMap::UnpackNativePc(Get<kPackedNativePc>(), instruction_set);
}
uint32_t GetInvokeType() const { return Get<kInvokeType>(); }
@@ -799,13 +297,61 @@ class InvokeInfo : public BitTable<3>::Accessor {
}
};
+class DexRegisterInfo : public BitTable<2>::Accessor {
+ public:
+ enum Field {
+ kKind,
+ kPackedValue,
+ kCount,
+ };
+
+ DexRegisterInfo(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
+
+ ALWAYS_INLINE DexRegisterLocation GetLocation() const {
+ DexRegisterLocation::Kind kind = static_cast<DexRegisterLocation::Kind>(Get<kKind>());
+ return DexRegisterLocation(kind, UnpackValue(kind, Get<kPackedValue>()));
+ }
+
+ static uint32_t PackValue(DexRegisterLocation::Kind kind, uint32_t value) {
+ uint32_t packed_value = value;
+ if (kind == DexRegisterLocation::Kind::kInStack) {
+ DCHECK(IsAligned<kFrameSlotSize>(packed_value));
+ packed_value /= kFrameSlotSize;
+ }
+ return packed_value;
+ }
+
+ static uint32_t UnpackValue(DexRegisterLocation::Kind kind, uint32_t packed_value) {
+ uint32_t value = packed_value;
+ if (kind == DexRegisterLocation::Kind::kInStack) {
+ value *= kFrameSlotSize;
+ }
+ return value;
+ }
+};
+
+// Register masks tend to have many trailing zero bits (caller-saves are usually not encoded),
+// therefore it is worth encoding the mask as value+shift.
+class RegisterMask : public BitTable<2>::Accessor {
+ public:
+ enum Field {
+ kValue,
+ kShift,
+ kCount,
+ };
+
+ RegisterMask(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
+
+ ALWAYS_INLINE uint32_t GetMask() const {
+ return Get<kValue>() << Get<kShift>();
+ }
+};
+
/**
* Wrapper around all compiler information collected for a method.
- * The information is of the form:
- *
- * [BitTable<Header>, BitTable<StackMap>, BitTable<RegisterMask>, BitTable<InlineInfo>,
- * BitTable<InvokeInfo>, BitTable<StackMask>, DexRegisterMap, DexLocationCatalog]
- *
+ * See the Decode method at the end for the precise binary format.
*/
class CodeInfo {
public:
@@ -826,15 +372,7 @@ class CodeInfo {
}
bool HasInlineInfo() const {
- return stack_maps_.NumColumnBits(StackMap::kInlineInfoIndex) != 0;
- }
-
- DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
- return DexRegisterLocationCatalog(location_catalog_);
- }
-
- ALWAYS_INLINE size_t GetNumberOfStackMaskBits() const {
- return stack_mask_bits_;
+ return inline_infos_.NumRows() > 0;
}
ALWAYS_INLINE StackMap GetStackMapAt(size_t index) const {
@@ -842,23 +380,25 @@ class CodeInfo {
}
BitMemoryRegion GetStackMask(size_t index) const {
- return stack_masks_.Subregion(index * stack_mask_bits_, stack_mask_bits_);
+ return stack_masks_.GetBitMemoryRegion(index);
}
BitMemoryRegion GetStackMaskOf(const StackMap& stack_map) const {
- return GetStackMask(stack_map.GetStackMaskIndex());
+ uint32_t index = stack_map.GetStackMaskIndex();
+ return (index == StackMap::kNoValue) ? BitMemoryRegion() : GetStackMask(index);
}
uint32_t GetRegisterMaskOf(const StackMap& stack_map) const {
- return register_masks_.Get(stack_map.GetRegisterMaskIndex());
+ uint32_t index = stack_map.GetRegisterMaskIndex();
+ return (index == StackMap::kNoValue) ? 0 : RegisterMask(&register_masks_, index).GetMask();
}
uint32_t GetNumberOfLocationCatalogEntries() const {
- return location_catalog_entries_;
+ return dex_register_catalog_.NumRows();
}
- uint32_t GetDexRegisterLocationCatalogSize() const {
- return location_catalog_.size();
+ ALWAYS_INLINE DexRegisterLocation GetDexRegisterCatalogEntry(size_t index) const {
+ return DexRegisterInfo(&dex_register_catalog_, index).GetLocation();
}
uint32_t GetNumberOfStackMaps() const {
@@ -869,37 +409,19 @@ class CodeInfo {
return InvokeInfo(&invoke_infos_, index);
}
- DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
- size_t number_of_dex_registers) const {
- if (!stack_map.HasDexRegisterMap()) {
- return DexRegisterMap();
- }
- const uint32_t offset = stack_map.GetDexRegisterMapOffset();
- size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
- return DexRegisterMap(dex_register_maps_.Subregion(offset, size));
+ ALWAYS_INLINE DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
+ size_t num_dex_registers) const {
+ return DecodeDexRegisterMap(stack_map.GetDexRegisterMaskIndex(),
+ stack_map.GetDexRegisterMapIndex(),
+ num_dex_registers);
}
- size_t GetDexRegisterMapsSize(uint32_t number_of_dex_registers) const {
- size_t total = 0;
- for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
- StackMap stack_map = GetStackMapAt(i);
- DexRegisterMap map(GetDexRegisterMapOf(stack_map, number_of_dex_registers));
- total += map.Size();
- }
- return total;
- }
-
- // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
- DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
- InlineInfo inline_info,
- uint32_t number_of_dex_registers) const {
- if (!inline_info.HasDexRegisterMapAtDepth(depth)) {
- return DexRegisterMap();
- } else {
- uint32_t offset = inline_info.GetDexRegisterMapOffsetAtDepth(depth);
- size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
- return DexRegisterMap(dex_register_maps_.Subregion(offset, size));
- }
+ ALWAYS_INLINE DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
+ InlineInfo inline_info,
+ size_t num_dex_registers) const {
+ return DecodeDexRegisterMap(inline_info.GetDexRegisterMaskIndexAtDepth(depth),
+ inline_info.GetDexRegisterMapIndexAtDepth(depth),
+ num_dex_registers);
}
InlineInfo GetInlineInfo(size_t index) const {
@@ -949,8 +471,8 @@ class CodeInfo {
if (other.GetDexPc() == dex_pc &&
other.GetNativePcOffset(kRuntimeISA) ==
stack_map.GetNativePcOffset(kRuntimeISA)) {
- DCHECK_EQ(other.GetDexRegisterMapOffset(),
- stack_map.GetDexRegisterMapOffset());
+ DCHECK_EQ(other.GetDexRegisterMapIndex(),
+ stack_map.GetDexRegisterMapIndex());
DCHECK(!stack_map.HasInlineInfo());
if (i < e - 2) {
// Make sure there are not three identical stack maps following each other.
@@ -988,77 +510,59 @@ class CodeInfo {
return InvokeInfo(&invoke_infos_, -1);
}
- // Dump this CodeInfo object on `os`. `code_offset` is the (absolute)
- // native PC of the compiled method and `number_of_dex_registers` the
- // number of Dex virtual registers used in this method. If
- // `dump_stack_maps` is true, also dump the stack maps and the
- // associated Dex register maps.
+ // Dump this CodeInfo object on `vios`.
+ // `code_offset` is the (absolute) native PC of the compiled method.
void Dump(VariableIndentationOutputStream* vios,
uint32_t code_offset,
uint16_t number_of_dex_registers,
- bool dump_stack_maps,
+ bool verbose,
InstructionSet instruction_set,
const MethodInfo& method_info) const;
private:
- // Compute the size of the Dex register map associated to the stack map at
- // `dex_register_map_offset_in_code_info`.
- size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset,
- uint16_t number_of_dex_registers) const {
- // Offset where the actual mapping data starts within art::DexRegisterMap.
- size_t location_mapping_data_offset_in_dex_register_map =
- DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
- // Create a temporary art::DexRegisterMap to be able to call
- // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
- DexRegisterMap dex_register_map_without_locations(
- MemoryRegion(dex_register_maps_.Subregion(dex_register_map_offset,
- location_mapping_data_offset_in_dex_register_map)));
- size_t number_of_live_dex_registers =
- dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
- size_t location_mapping_data_size_in_bits =
- DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries())
- * number_of_live_dex_registers;
- size_t location_mapping_data_size_in_bytes =
- RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
- size_t dex_register_map_size =
- location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
- return dex_register_map_size;
- }
-
- MemoryRegion DecodeMemoryRegion(MemoryRegion& region, size_t* bit_offset) {
- size_t length = DecodeVarintBits(BitMemoryRegion(region), bit_offset);
- size_t offset = BitsToBytesRoundUp(*bit_offset);;
- *bit_offset = (offset + length) * kBitsPerByte;
- return region.Subregion(offset, length);
+ ALWAYS_INLINE DexRegisterMap DecodeDexRegisterMap(uint32_t mask_index,
+ uint32_t map_index,
+ uint32_t num_dex_registers) const {
+ DexRegisterMap map(map_index == StackMap::kNoValue ? 0 : num_dex_registers);
+ if (mask_index != StackMap::kNoValue) {
+ BitMemoryRegion mask = dex_register_masks_.GetBitMemoryRegion(mask_index);
+ num_dex_registers = std::min<uint32_t>(num_dex_registers, mask.size_in_bits());
+ DexRegisterLocation* regs = map.data();
+ for (uint32_t r = 0; r < mask.size_in_bits(); r++) {
+ if (mask.LoadBit(r) /* is_live */) {
+ DCHECK_LT(r, map.size());
+ regs[r] = GetDexRegisterCatalogEntry(dex_register_maps_.Get(map_index++));
+ }
+ }
+ }
+ return map;
}
void Decode(const uint8_t* data) {
size_t non_header_size = DecodeUnsignedLeb128(&data);
- MemoryRegion region(const_cast<uint8_t*>(data), non_header_size);
- BitMemoryRegion bit_region(region);
+ BitMemoryRegion region(MemoryRegion(const_cast<uint8_t*>(data), non_header_size));
size_t bit_offset = 0;
size_ = UnsignedLeb128Size(non_header_size) + non_header_size;
- dex_register_maps_ = DecodeMemoryRegion(region, &bit_offset);
- location_catalog_entries_ = DecodeVarintBits(bit_region, &bit_offset);
- location_catalog_ = DecodeMemoryRegion(region, &bit_offset);
- stack_maps_.Decode(bit_region, &bit_offset);
- invoke_infos_.Decode(bit_region, &bit_offset);
- inline_infos_.Decode(bit_region, &bit_offset);
- register_masks_.Decode(bit_region, &bit_offset);
- stack_mask_bits_ = DecodeVarintBits(bit_region, &bit_offset);
- stack_masks_ = bit_region.Subregion(bit_offset, non_header_size * kBitsPerByte - bit_offset);
+ stack_maps_.Decode(region, &bit_offset);
+ register_masks_.Decode(region, &bit_offset);
+ stack_masks_.Decode(region, &bit_offset);
+ invoke_infos_.Decode(region, &bit_offset);
+ inline_infos_.Decode(region, &bit_offset);
+ dex_register_masks_.Decode(region, &bit_offset);
+ dex_register_maps_.Decode(region, &bit_offset);
+ dex_register_catalog_.Decode(region, &bit_offset);
+ CHECK_EQ(non_header_size, BitsToBytesRoundUp(bit_offset)) << "Invalid CodeInfo";
}
size_t size_;
- MemoryRegion dex_register_maps_;
- uint32_t location_catalog_entries_;
- MemoryRegion location_catalog_;
BitTable<StackMap::Field::kCount> stack_maps_;
+ BitTable<RegisterMask::Field::kCount> register_masks_;
+ BitTable<1> stack_masks_;
BitTable<InvokeInfo::Field::kCount> invoke_infos_;
BitTable<InlineInfo::Field::kCount> inline_infos_;
- BitTable<1> register_masks_;
- uint32_t stack_mask_bits_ = 0;
- BitMemoryRegion stack_masks_;
+ BitTable<1> dex_register_masks_;
+ BitTable<1> dex_register_maps_;
+ BitTable<DexRegisterInfo::Field::kCount> dex_register_catalog_;
friend class OatDumper;
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 5a80929350..a8133a1fda 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -47,6 +47,7 @@
#include "base/to_str.h"
#include "base/utils.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "debugger.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
@@ -490,7 +491,7 @@ Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
jobject java_thread) {
- return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread).Ptr());
+ return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread));
}
static size_t FixStackSize(size_t stack_size) {
@@ -2460,7 +2461,7 @@ class FetchStackTraceVisitor : public StackVisitor {
// save frame)
ArtMethod* m = GetMethod();
if (skipping_ && !m->IsRuntimeMethod() &&
- !mirror::Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) {
+ !GetClassRoot<mirror::Throwable>()->IsAssignableFrom(m->GetDeclaringClass())) {
skipping_ = false;
}
if (!skipping_) {
@@ -2510,7 +2511,8 @@ class BuildInternalStackTraceVisitor : public StackVisitor {
// class of the ArtMethod pointers.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(self_);
- ObjPtr<mirror::Class> array_class = class_linker->GetClassRoot(ClassLinker::kObjectArrayClass);
+ ObjPtr<mirror::Class> array_class =
+ GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker);
// The first element is the methods and dex pc array, the other elements are declaring classes
// for the methods to ensure classes in the stack trace don't get unloaded.
Handle<mirror::ObjectArray<mirror::Object>> trace(
@@ -2726,7 +2728,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(
depth = std::min(depth, traces_length);
} else {
// Create java_trace array and place in local reference table
- mirror::ObjectArray<mirror::StackTraceElement>* java_traces =
+ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> java_traces =
class_linker->AllocStackTraceElementArray(soa.Self(), depth);
if (java_traces == nullptr) {
return nullptr;
@@ -2860,27 +2862,18 @@ jobjectArray Thread::CreateAnnotatedStackTrace(const ScopedObjectAccessAlreadyRu
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<6> hs(soa.Self());
- mirror::Class* aste_array_class = class_linker->FindClass(
+ Handle<mirror::Class> h_aste_array_class = hs.NewHandle(class_linker->FindSystemClass(
soa.Self(),
- "[Ldalvik/system/AnnotatedStackTraceElement;",
- ScopedNullHandle<mirror::ClassLoader>());
- if (aste_array_class == nullptr) {
+ "[Ldalvik/system/AnnotatedStackTraceElement;"));
+ if (h_aste_array_class == nullptr) {
return nullptr;
}
- Handle<mirror::Class> h_aste_array_class(hs.NewHandle<mirror::Class>(aste_array_class));
+ Handle<mirror::Class> h_aste_class = hs.NewHandle(h_aste_array_class->GetComponentType());
- mirror::Class* o_array_class = class_linker->FindClass(soa.Self(),
- "[Ljava/lang/Object;",
- ScopedNullHandle<mirror::ClassLoader>());
- if (o_array_class == nullptr) {
- // This should not fail in a healthy runtime.
- soa.Self()->AssertPendingException();
- return nullptr;
- }
- Handle<mirror::Class> h_o_array_class(hs.NewHandle<mirror::Class>(o_array_class));
+ Handle<mirror::Class> h_o_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker));
+ DCHECK(h_o_array_class != nullptr); // Class roots must be already initialized.
- Handle<mirror::Class> h_aste_class(hs.NewHandle<mirror::Class>(
- h_aste_array_class->GetComponentType()));
// Make sure the AnnotatedStackTraceElement.class is initialized, b/76208924 .
class_linker->EnsureInitialized(soa.Self(),
@@ -2904,7 +2897,7 @@ jobjectArray Thread::CreateAnnotatedStackTrace(const ScopedObjectAccessAlreadyRu
size_t length = dumper.stack_trace_elements_.size();
ObjPtr<mirror::ObjectArray<mirror::Object>> array =
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), aste_array_class, length);
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), h_aste_array_class.Get(), length);
if (array == nullptr) {
soa.Self()->AssertPendingOOMException();
return nullptr;
@@ -3566,9 +3559,8 @@ class ReferenceMapVisitor : public StackVisitor {
T vreg_info(m, code_info, map, visitor_);
// Visit stack entries that hold pointers.
- const size_t number_of_bits = code_info.GetNumberOfStackMaskBits();
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(map);
- for (size_t i = 0; i < number_of_bits; ++i) {
+ for (size_t i = 0; i < stack_mask.size_in_bits(); ++i) {
if (stack_mask.LoadBit(i)) {
StackReference<mirror::Object>* ref_addr = vreg_base + i;
mirror::Object* ref = ref_addr->AsMirrorPtr();
@@ -3678,8 +3670,7 @@ class ReferenceMapVisitor : public StackVisitor {
REQUIRES_SHARED(Locks::mutator_lock_) {
bool found = false;
for (size_t dex_reg = 0; dex_reg != number_of_dex_registers; ++dex_reg) {
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
- dex_reg, number_of_dex_registers, code_info);
+ DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(dex_reg);
if (location.GetKind() == kind && static_cast<size_t>(location.GetValue()) == index) {
visitor(ref, dex_reg, stack_visitor);
found = true;
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 02e61d76a1..370a619820 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -506,7 +506,7 @@ TEST_F(TransactionTest, ResolveString) {
class_linker_->LookupString(string_idx, h_dex_cache.Get());
ASSERT_TRUE(s != nullptr);
EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
- EXPECT_EQ(s.Ptr(), h_dex_cache->GetResolvedString(string_idx));
+ EXPECT_OBJ_PTR_EQ(s, h_dex_cache->GetResolvedString(string_idx));
}
Runtime::Current()->RollbackAndExitTransactionMode();
// Check that the string did not stay resolved.
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 838d7f14bc..32aa86dc93 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,6 +28,7 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "dex/art_dex_file_loader.h"
+#include "dex/class_accessor-inl.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/hidden_api_access_flags.h"
@@ -283,30 +284,25 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
std::unordered_set<const DexFile::CodeItem*> unquickened_code_item;
CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
quickening_info));
- for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = target_dex_file.GetClassDef(i);
- const uint8_t* class_data = target_dex_file.GetClassData(class_def);
- if (class_data != nullptr) {
- for (ClassDataItemIterator class_it(target_dex_file, class_data);
- class_it.HasNext();
- class_it.Next()) {
- if (class_it.IsAtMethod()) {
- const DexFile::CodeItem* code_item = class_it.GetMethodCodeItem();
- if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
- const uint32_t offset = accessor.GetOffset(class_it.GetMemberIndex());
- // Offset being 0 means not quickened.
- if (offset != 0u) {
- ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
- optimizer::ArtDecompileDEX(
- target_dex_file,
- *code_item,
- quicken_data,
- decompile_return_instruction);
- }
- }
+ for (ClassAccessor class_accessor : target_dex_file.GetClasses()) {
+ for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
+ const DexFile::CodeItem* code_item = method.GetCodeItem();
+ if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
+ const uint32_t offset = accessor.GetOffset(method.GetIndex());
+ // Offset being 0 means not quickened.
+ if (offset != 0u) {
+ ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
+ optimizer::ArtDecompileDEX(
+ target_dex_file,
+ *code_item,
+ quicken_data,
+ decompile_return_instruction);
}
- DexFile::UnHideAccessFlags(class_it);
}
+ method.UnHideAccessFlags();
+ }
+ for (const ClassAccessor::Field& field : class_accessor.GetFields()) {
+ field.UnHideAccessFlags();
}
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 91cec23dd5..59617481eb 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -33,7 +33,9 @@
#include "base/time_utils.h"
#include "base/utils.h"
#include "class_linker.h"
+#include "class_root.h"
#include "compiler_callbacks.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -143,7 +145,7 @@ static void SafelyMarkAllRegistersAsConflicts(MethodVerifier* verifier, Register
}
FailureKind MethodVerifier::VerifyClass(Thread* self,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
@@ -189,11 +191,6 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
error);
}
-template <bool kDirect>
-static bool HasNextMethod(ClassDataItemIterator* it) {
- return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
-}
-
static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
&& FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -206,45 +203,51 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) {
types |= fd.types;
}
-template <bool kDirect>
-MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
- ClassLinker* linker,
- const DexFile* dex_file,
- const DexFile::ClassDef& class_def,
- ClassDataItemIterator* it,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- bool need_precise_constants,
- std::string* error_string) {
- DCHECK(it != nullptr);
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
+ SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ // A class must not be abstract and final.
+ if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
+ *error = "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ": class is abstract and final.";
+ return FailureKind::kHardFailure;
+ }
+
+ ClassAccessor accessor(*dex_file, class_def);
+
+ int64_t previous_method_idx[2] = { -1, -1 };
MethodVerifier::FailureData failure_data;
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
- int64_t previous_method_idx = -1;
- while (HasNextMethod<kDirect>(it)) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
self->AllowThreadSuspension();
- uint32_t method_idx = it->GetMemberIndex();
- if (method_idx == previous_method_idx) {
+ const uint32_t method_idx = method.GetIndex();
+ if (method_idx == *previous_idx) {
// smali can create dex files with two encoded_methods sharing the same method_idx
// http://code.google.com/p/smali/issues/detail?id=119
- it->Next();
continue;
}
- previous_method_idx = method_idx;
- InvokeType type = it->GetMethodInvokeType(class_def);
- ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ *previous_idx = method_idx;
+ const InvokeType type = method.GetInvokeType(class_def.access_flags_);
+ ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
- if (method == nullptr) {
+ if (resolved_method == nullptr) {
DCHECK(self->IsExceptionPending());
// We couldn't resolve the method, but continue regardless.
self->ClearException();
} else {
- DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
+ DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
}
- StackHandleScope<1> hs(self);
std::string hard_failure_msg;
MethodVerifier::FailureData result = VerifyMethod(self,
method_idx,
@@ -252,99 +255,39 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
dex_cache,
class_loader,
class_def,
- it->GetMethodCodeItem(),
- method,
- it->GetMethodAccessFlags(),
+ method.GetCodeItem(),
+ resolved_method,
+ method.GetAccessFlags(),
callbacks,
allow_soft_failures,
log_level,
- need_precise_constants,
+ /*need_precise_constants*/ false,
&hard_failure_msg);
if (result.kind == FailureKind::kHardFailure) {
if (failure_data.kind == FailureKind::kHardFailure) {
// If we logged an error before, we need a newline.
- *error_string += "\n";
+ *error += "\n";
} else {
// If we didn't log a hard failure before, print the header of the message.
- *error_string += "Verifier rejected class ";
- *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error_string += ":";
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
}
- *error_string += " ";
- *error_string += hard_failure_msg;
+ *error += " ";
+ *error += hard_failure_msg;
}
failure_data.Merge(result);
- it->Next();
}
- return failure_data;
-}
-
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
- SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
-
- // A class must not be abstract and final.
- if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
- *error = "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ": class is abstract and final.";
- return FailureKind::kHardFailure;
- }
-
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data == nullptr) {
- // empty class, probably a marker interface
- return FailureKind::kNoFailure;
- }
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- // Direct methods.
- MethodVerifier::FailureData data1 = VerifyMethods<true>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
- // Virtual methods.
- MethodVerifier::FailureData data2 = VerifyMethods<false>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
-
- data1.Merge(data2);
-
- if (data1.kind == FailureKind::kNoFailure) {
+ if (failure_data.kind == FailureKind::kNoFailure) {
return FailureKind::kNoFailure;
} else {
- if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
+ if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
// Print a warning about expected slow-down. Use a string temporary to print one contiguous
// warning.
std::string tmp =
StringPrintf("Class %s failed lock verification and will run slower.",
- PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str());
+ PrettyDescriptor(accessor.GetDescriptor()).c_str());
if (!gPrintedDxMonitorText) {
tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
"and incorrect proguard optimizations.";
@@ -352,7 +295,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
}
LOG(WARNING) << tmp;
}
- return data1.kind;
+ return failure_data.kind;
}
}
@@ -1923,15 +1866,11 @@ bool MethodVerifier::CodeFlowVerifyMethod() {
static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx);
DCHECK(class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*class_def);
- DCHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipStaticFields();
- while (it.HasNextInstanceField()) {
- if ((it.GetFieldAccessFlags() & kAccFinal) != 0) {
- return it.GetMemberIndex();
+ ClassAccessor accessor(dex_file, *class_def);
+ for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+ if (field.IsFinal()) {
+ return field.GetIndex();
}
- it.Next();
}
return dex::kDexNoIndex;
}
@@ -2931,7 +2870,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
: called_method->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type = &FromClass(return_type_descriptor,
- return_type_class.Ptr(),
+ return_type_class,
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -3365,7 +3304,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
break;
}
- auto* klass = declaring_class.GetClass();
+ ObjPtr<mirror::Class> klass = declaring_class.GetClass();
for (uint32_t i = 0, num_fields = klass->NumInstanceFields(); i < num_fields; ++i) {
if (klass->GetInstanceField(i)->IsFinal()) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected for "
@@ -3528,7 +3467,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
ObjPtr<mirror::Class> klass =
linker->ResolveType(handler_type_idx, dex_cache_, class_loader_);
if (klass != nullptr) {
- if (klass == mirror::Throwable::GetJavaLangThrowable()) {
+ if (klass == GetClassRoot<mirror::Throwable>()) {
has_catch_all_handler = true;
}
} else {
@@ -3666,10 +3605,10 @@ const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) {
UninstantiableError(descriptor);
precise = false;
}
- result = reg_types_.FindClass(klass.Ptr(), precise);
+ result = reg_types_.FindClass(klass, precise);
if (result == nullptr) {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
- result = reg_types_.InsertClass(descriptor, klass.Ptr(), precise);
+ result = reg_types_.InsertClass(descriptor, klass, precise);
}
} else {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
@@ -3684,7 +3623,7 @@ const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) {
}
// Record result of class resolution attempt.
- VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass.Ptr());
+ VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass);
// If requested, check if access is allowed. Unresolved types are included in this check, as the
// interpreter only tests whether access is allowed when a class is not pre-verified and runs in
@@ -4206,9 +4145,11 @@ bool MethodVerifier::CheckSignaturePolymorphicMethod(ArtMethod* method) {
const char* method_name = method->GetName();
const char* expected_return_descriptor;
- if (klass == mirror::MethodHandle::StaticClass()) {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
+ if (klass == GetClassRoot<mirror::MethodHandle>(class_roots)) {
expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name);
- } else if (klass == mirror::VarHandle::StaticClass()) {
+ } else if (klass == GetClassRoot<mirror::VarHandle>(class_roots)) {
expected_return_descriptor = mirror::VarHandle::GetReturnTypeDescriptor(method_name);
} else {
Fail(VERIFY_ERROR_BAD_CLASS_HARD)
@@ -4268,12 +4209,16 @@ bool MethodVerifier::CheckSignaturePolymorphicReceiver(const Instruction* inst)
<< "invoke-polymorphic receiver has no class: "
<< this_type;
return false;
- } else if (!this_type.GetClass()->IsSubClass(mirror::MethodHandle::StaticClass()) &&
- !this_type.GetClass()->IsSubClass(mirror::VarHandle::StaticClass())) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD)
- << "invoke-polymorphic receiver is not a subclass of MethodHandle or VarHandle: "
- << this_type;
- return false;
+ } else {
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ Runtime::Current()->GetClassLinker()->GetClassRoots();
+ if (!this_type.GetClass()->IsSubClass(GetClassRoot<mirror::MethodHandle>(class_roots)) &&
+ !this_type.GetClass()->IsSubClass(GetClassRoot<mirror::VarHandle>(class_roots))) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD)
+ << "invoke-polymorphic receiver is not a subclass of MethodHandle or VarHandle: "
+ << this_type;
+ return false;
+ }
}
return true;
}
@@ -4621,9 +4566,7 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id
std::string temp;
ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
const RegType& field_klass =
- FromClass(klass->GetDescriptor(&temp),
- klass.Ptr(),
- klass->CannotBeAssignedFromOtherTypes());
+ FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
if (obj_type.IsUninitializedTypes()) {
// Field accesses through uninitialized references are only allowable for constructors where
// the field is declared in this class.
@@ -4724,7 +4667,7 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
can_load_classes_ ? field->ResolveType() : field->LookupResolvedType();
if (field_type_class != nullptr) {
field_type = &FromClass(field->GetTypeDescriptor(),
- field_type_class.Ptr(),
+ field_type_class,
field_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -4912,7 +4855,7 @@ const RegType& MethodVerifier::GetMethodReturnType() {
: method_being_verified_->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type_ = &FromClass(method_being_verified_->GetReturnTypeDescriptor(),
- return_type_class.Ptr(),
+ return_type_class,
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -4936,7 +4879,7 @@ const RegType& MethodVerifier::GetDeclaringClass() {
const char* descriptor
= dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
if (method_being_verified_ != nullptr) {
- mirror::Class* klass = method_being_verified_->GetDeclaringClass();
+ ObjPtr<mirror::Class> klass = method_being_verified_->GetDeclaringClass();
declaring_class_ = &FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes());
} else {
declaring_class_ = &reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
@@ -5038,7 +4981,7 @@ void MethodVerifier::VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
}
const RegType& MethodVerifier::FromClass(const char* descriptor,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
bool precise) {
DCHECK(klass != nullptr);
if (precise && !klass->IsInstantiable() && !klass->IsPrimitive()) {
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 531d3dabfa..9890af9d95 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -96,7 +96,7 @@ class MethodVerifier {
public:
// Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
@@ -275,23 +275,6 @@ class MethodVerifier {
void Merge(const FailureData& src);
};
- // Verify all direct or virtual methods of a class. The method assumes that the iterator is
- // positioned correctly, and the iterator will be updated.
- template <bool kDirect>
- static FailureData VerifyMethods(Thread* self,
- ClassLinker* linker,
- const DexFile* dex_file,
- const DexFile::ClassDef& class_def,
- ClassDataItemIterator* it,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- bool need_precise_constants,
- std::string* error_string)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
/*
* Perform verification on a single method.
*
@@ -691,7 +674,7 @@ class MethodVerifier {
// non-precise reference will be returned.
// Note: we reuse NO_CLASS as this will throw an exception at runtime, when the failing class is
// actually touched.
- const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
+ const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE bool FailOrAbort(bool condition, const char* error_msg, uint32_t work_insn_idx);
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index db3f093905..d1be9fa6f8 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -37,7 +37,7 @@ class MethodVerifierTest : public CommonRuntimeTest {
REQUIRES_SHARED(Locks::mutator_lock_) {
ASSERT_TRUE(descriptor != nullptr);
Thread* self = Thread::Current();
- mirror::Class* klass = class_linker_->FindSystemClass(self, descriptor.c_str());
+ ObjPtr<mirror::Class> klass = class_linker_->FindSystemClass(self, descriptor.c_str());
// Verify the class
std::string error_msg;
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index e7864a28a0..4a3f9e6365 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -54,17 +54,19 @@ const DoubleHiType* DoubleHiType::instance_ = nullptr;
const IntegerType* IntegerType::instance_ = nullptr;
const NullType* NullType::instance_ = nullptr;
-PrimitiveType::PrimitiveType(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+PrimitiveType::PrimitiveType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
CHECK(klass != nullptr);
CHECK(!descriptor.empty());
}
-Cat1Type::Cat1Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+Cat1Type::Cat1Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
}
-Cat2Type::Cat2Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+Cat2Type::Cat2Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
}
@@ -129,7 +131,7 @@ std::string IntegerType::Dump() const {
return "Integer";
}
-const DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass,
+const DoubleHiType* DoubleHiType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -144,7 +146,7 @@ void DoubleHiType::Destroy() {
}
}
-const DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass,
+const DoubleLoType* DoubleLoType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -159,14 +161,16 @@ void DoubleLoType::Destroy() {
}
}
-const LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const LongLoType* LongLoType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new LongLoType(klass, descriptor, cache_id);
return instance_;
}
-const LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const LongHiType* LongHiType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new LongHiType(klass, descriptor, cache_id);
@@ -187,7 +191,8 @@ void LongLoType::Destroy() {
}
}
-const FloatType* FloatType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const FloatType* FloatType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new FloatType(klass, descriptor, cache_id);
@@ -201,7 +206,8 @@ void FloatType::Destroy() {
}
}
-const CharType* CharType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const CharType* CharType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new CharType(klass, descriptor, cache_id);
@@ -215,7 +221,8 @@ void CharType::Destroy() {
}
}
-const ShortType* ShortType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const ShortType* ShortType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new ShortType(klass, descriptor, cache_id);
@@ -229,7 +236,8 @@ void ShortType::Destroy() {
}
}
-const ByteType* ByteType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const ByteType* ByteType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new ByteType(klass, descriptor, cache_id);
@@ -243,7 +251,8 @@ void ByteType::Destroy() {
}
}
-const IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const IntegerType* IntegerType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new IntegerType(klass, descriptor, cache_id);
@@ -257,7 +266,7 @@ void IntegerType::Destroy() {
}
}
-const ConflictType* ConflictType::CreateInstance(mirror::Class* klass,
+const ConflictType* ConflictType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -272,8 +281,9 @@ void ConflictType::Destroy() {
}
}
-const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
- uint16_t cache_id) {
+const BooleanType* BooleanType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id) {
CHECK(BooleanType::instance_ == nullptr);
instance_ = new BooleanType(klass, descriptor, cache_id);
return BooleanType::instance_;
@@ -290,7 +300,7 @@ std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
return "Undefined";
}
-const UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass,
+const UndefinedType* UndefinedType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -305,7 +315,8 @@ void UndefinedType::Destroy() {
}
}
-PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+PreciseReferenceType::PreciseReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
// Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
@@ -505,7 +516,7 @@ bool UnresolvedType::IsNonZeroReferenceTypes() const {
const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
if (!IsUnresolvedTypes()) {
- mirror::Class* super_klass = GetClass()->GetSuperClass();
+ ObjPtr<mirror::Class> super_klass = GetClass()->GetSuperClass();
if (super_klass != nullptr) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
@@ -543,7 +554,7 @@ bool RegType::IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
return descriptor_[0] == '[';
} else if (HasClass()) {
- mirror::Class* type = GetClass();
+ ObjPtr<mirror::Class> type = GetClass();
return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
} else {
return false;
@@ -569,7 +580,7 @@ bool RegType::IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
bool RegType::IsJavaLangObjectArray() const {
if (HasClass()) {
- mirror::Class* type = GetClass();
+ ObjPtr<mirror::Class> type = GetClass();
return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
}
return false;
@@ -712,11 +723,10 @@ const RegType& RegType::Merge(const RegType& incoming_type,
// mechanics to continue.
return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
} else { // Two reference types, compute Join
- mirror::Class* c1 = GetClass();
- mirror::Class* c2 = incoming_type.GetClass();
- DCHECK(c1 != nullptr && !c1->IsPrimitive());
- DCHECK(c2 != nullptr && !c2->IsPrimitive());
- mirror::Class* join_class = ClassJoin(c1, c2);
+ // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
+ DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
+ DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
+ ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(), incoming_type.GetClass());
if (UNLIKELY(join_class == nullptr)) {
// Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
// We cannot report an unresolved merge type, as that will attempt to merge the resolved
@@ -731,30 +741,37 @@ const RegType& RegType::Merge(const RegType& incoming_type,
// (In that case, it is likely a misconfiguration of dex2oat.)
if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) {
LOG(FATAL) << "Could not create class join of "
- << c1->PrettyClass()
+ << GetClass()->PrettyClass()
<< " & "
- << c2->PrettyClass();
+ << incoming_type.GetClass()->PrettyClass();
UNREACHABLE();
}
return reg_types->MakeUnresolvedReference();
}
- // Record the dependency that both `c1` and `c2` are assignable to `join_class`.
- // The `verifier` is null during unit tests.
+ // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
+ // are assignable to `join_class`. The `verifier` is null during unit tests.
if (verifier != nullptr) {
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), join_class, c1, true /* strict */, true /* is_assignable */);
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), join_class, c2, true /* strict */, true /* is_assignable */);
+ VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ join_class,
+ GetClass(),
+ /* strict */ true,
+ /* is_assignable */ true);
+ VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ join_class,
+ incoming_type.GetClass(),
+ /* strict */ true,
+ /* is_assignable */ true);
}
- if (c1 == join_class && !IsPreciseReference()) {
+ if (GetClass() == join_class && !IsPreciseReference()) {
return *this;
- } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
+ } else if (incoming_type.GetClass() == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
std::string temp;
- return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
+ const char* descriptor = join_class->GetDescriptor(&temp);
+ return reg_types->FromClass(descriptor, join_class, /* precise */ false);
}
}
} else {
@@ -763,7 +780,7 @@ const RegType& RegType::Merge(const RegType& incoming_type,
}
// See comment in reg_type.h
-mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
+ObjPtr<mirror::Class> RegType::ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
DCHECK(!s->IsPrimitive()) << s->PrettyClass();
DCHECK(!t->IsPrimitive()) << t->PrettyClass();
if (s == t) {
@@ -773,12 +790,12 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
} else if (t->IsAssignableFrom(s)) {
return t;
} else if (s->IsArrayClass() && t->IsArrayClass()) {
- mirror::Class* s_ct = s->GetComponentType();
- mirror::Class* t_ct = t->GetComponentType();
+ ObjPtr<mirror::Class> s_ct = s->GetComponentType();
+ ObjPtr<mirror::Class> t_ct = t->GetComponentType();
if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
// Given the types aren't the same, if either array is of primitive types then the only
// common parent is java.lang.Object
- mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
+ ObjPtr<mirror::Class> result = s->GetSuperClass(); // short-cut to java.lang.Object
DCHECK(result->IsObjectClass());
return result;
}
@@ -788,8 +805,9 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
self->AssertPendingException();
return nullptr;
}
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* array_class = class_linker->FindArrayClass(self, &common_elem);
+ // Note: The following lookup invalidates existing ObjPtr<>s.
+ ObjPtr<mirror::Class> array_class =
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
if (UNLIKELY(array_class == nullptr)) {
self->AssertPendingException();
return nullptr;
@@ -971,7 +989,7 @@ bool RegType::CanAssignArray(const RegType& src,
return cmp1.CanAssignArray(cmp2, reg_types, class_loader, verifier, soft_error);
}
-const NullType* NullType::CreateInstance(mirror::Class* klass,
+const NullType* NullType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 3e994074a1..29da376091 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -191,7 +191,7 @@ class RegType {
!IsUnresolvedSuperClass()));
return descriptor_;
}
- mirror::Class* GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::Class> GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!IsUnresolvedReference());
DCHECK(!klass_.IsNull()) << Dump();
DCHECK(HasClass());
@@ -318,7 +318,7 @@ class RegType {
}
protected:
- RegType(mirror::Class* klass,
+ RegType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: descriptor_(descriptor),
@@ -365,7 +365,7 @@ class RegType {
*
* [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
*/
- static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
+ static ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
REQUIRES_SHARED(Locks::mutator_lock_);
static bool AssignableFrom(const RegType& lhs,
@@ -388,7 +388,7 @@ class ConflictType FINAL : public RegType {
static const ConflictType* GetInstance() PURE;
// Create the singleton instance.
- static const ConflictType* CreateInstance(mirror::Class* klass,
+ static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -401,7 +401,8 @@ class ConflictType FINAL : public RegType {
}
private:
- ConflictType(mirror::Class* klass, const StringPiece& descriptor,
+ ConflictType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -423,7 +424,7 @@ class UndefinedType FINAL : public RegType {
static const UndefinedType* GetInstance() PURE;
// Create the singleton instance.
- static const UndefinedType* CreateInstance(mirror::Class* klass,
+ static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -436,7 +437,8 @@ class UndefinedType FINAL : public RegType {
}
private:
- UndefinedType(mirror::Class* klass, const StringPiece& descriptor,
+ UndefinedType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -447,7 +449,8 @@ class UndefinedType FINAL : public RegType {
class PrimitiveType : public RegType {
public:
- PrimitiveType(mirror::Class* klass, const StringPiece& descriptor,
+ PrimitiveType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
bool HasClassVirtual() const OVERRIDE { return true; }
@@ -455,7 +458,7 @@ class PrimitiveType : public RegType {
class Cat1Type : public PrimitiveType {
public:
- Cat1Type(mirror::Class* klass, const StringPiece& descriptor,
+ Cat1Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -463,7 +466,7 @@ class IntegerType FINAL : public Cat1Type {
public:
bool IsInteger() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const IntegerType* CreateInstance(mirror::Class* klass,
+ static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -475,7 +478,8 @@ class IntegerType FINAL : public Cat1Type {
}
private:
- IntegerType(mirror::Class* klass, const StringPiece& descriptor,
+ IntegerType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -487,7 +491,7 @@ class BooleanType FINAL : public Cat1Type {
public:
bool IsBoolean() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const BooleanType* CreateInstance(mirror::Class* klass,
+ static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -499,7 +503,8 @@ class BooleanType FINAL : public Cat1Type {
}
private:
- BooleanType(mirror::Class* klass, const StringPiece& descriptor,
+ BooleanType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -512,7 +517,7 @@ class ByteType FINAL : public Cat1Type {
public:
bool IsByte() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const ByteType* CreateInstance(mirror::Class* klass,
+ static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -524,7 +529,8 @@ class ByteType FINAL : public Cat1Type {
}
private:
- ByteType(mirror::Class* klass, const StringPiece& descriptor,
+ ByteType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -536,7 +542,7 @@ class ShortType FINAL : public Cat1Type {
public:
bool IsShort() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const ShortType* CreateInstance(mirror::Class* klass,
+ static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -548,7 +554,7 @@ class ShortType FINAL : public Cat1Type {
}
private:
- ShortType(mirror::Class* klass, const StringPiece& descriptor,
+ ShortType(ObjPtr<mirror::Class> klass, const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -560,7 +566,7 @@ class CharType FINAL : public Cat1Type {
public:
bool IsChar() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const CharType* CreateInstance(mirror::Class* klass,
+ static const CharType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -572,7 +578,8 @@ class CharType FINAL : public Cat1Type {
}
private:
- CharType(mirror::Class* klass, const StringPiece& descriptor,
+ CharType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -584,7 +591,7 @@ class FloatType FINAL : public Cat1Type {
public:
bool IsFloat() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const FloatType* CreateInstance(mirror::Class* klass,
+ static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -596,7 +603,8 @@ class FloatType FINAL : public Cat1Type {
}
private:
- FloatType(mirror::Class* klass, const StringPiece& descriptor,
+ FloatType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -606,7 +614,8 @@ class FloatType FINAL : public Cat1Type {
class Cat2Type : public PrimitiveType {
public:
- Cat2Type(mirror::Class* klass, const StringPiece& descriptor,
+ Cat2Type(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -615,7 +624,7 @@ class LongLoType FINAL : public Cat2Type {
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongLo() const OVERRIDE { return true; }
bool IsLong() const OVERRIDE { return true; }
- static const LongLoType* CreateInstance(mirror::Class* klass,
+ static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -627,7 +636,8 @@ class LongLoType FINAL : public Cat2Type {
}
private:
- LongLoType(mirror::Class* klass, const StringPiece& descriptor,
+ LongLoType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -639,7 +649,7 @@ class LongHiType FINAL : public Cat2Type {
public:
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongHi() const OVERRIDE { return true; }
- static const LongHiType* CreateInstance(mirror::Class* klass,
+ static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -651,7 +661,8 @@ class LongHiType FINAL : public Cat2Type {
}
private:
- LongHiType(mirror::Class* klass, const StringPiece& descriptor,
+ LongHiType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -664,7 +675,7 @@ class DoubleLoType FINAL : public Cat2Type {
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsDoubleLo() const OVERRIDE { return true; }
bool IsDouble() const OVERRIDE { return true; }
- static const DoubleLoType* CreateInstance(mirror::Class* klass,
+ static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -676,7 +687,8 @@ class DoubleLoType FINAL : public Cat2Type {
}
private:
- DoubleLoType(mirror::Class* klass, const StringPiece& descriptor,
+ DoubleLoType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -688,9 +700,9 @@ class DoubleHiType FINAL : public Cat2Type {
public:
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
virtual bool IsDoubleHi() const OVERRIDE { return true; }
- static const DoubleHiType* CreateInstance(mirror::Class* klass,
- const StringPiece& descriptor,
- uint16_t cache_id)
+ static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
static const DoubleHiType* GetInstance() PURE;
static void Destroy();
@@ -700,7 +712,8 @@ class DoubleHiType FINAL : public Cat2Type {
}
private:
- DoubleHiType(mirror::Class* klass, const StringPiece& descriptor,
+ DoubleHiType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -872,7 +885,7 @@ class NullType FINAL : public RegType {
static const NullType* GetInstance() PURE;
// Create the singleton instance.
- static const NullType* CreateInstance(mirror::Class* klass,
+ static const NullType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -892,7 +905,7 @@ class NullType FINAL : public RegType {
}
private:
- NullType(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+ NullType(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -906,8 +919,10 @@ class NullType FINAL : public RegType {
// instructions and must be passed to a constructor.
class UninitializedType : public RegType {
public:
- UninitializedType(mirror::Class* klass, const StringPiece& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
+ UninitializedType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint32_t allocation_pc,
+ uint16_t cache_id)
: RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {}
bool IsUninitializedTypes() const OVERRIDE;
@@ -929,9 +944,10 @@ class UninitializedType : public RegType {
// Similar to ReferenceType but not yet having been passed to a constructor.
class UninitializedReferenceType FINAL : public UninitializedType {
public:
- UninitializedReferenceType(mirror::Class* klass,
+ UninitializedReferenceType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
+ uint32_t allocation_pc,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
: UninitializedType(klass, descriptor, allocation_pc, cache_id) {
CheckConstructorInvariants(this);
@@ -969,7 +985,7 @@ class UnresolvedUninitializedRefType FINAL : public UninitializedType {
// of a constructor.
class UninitializedThisReferenceType FINAL : public UninitializedType {
public:
- UninitializedThisReferenceType(mirror::Class* klass,
+ UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -1010,7 +1026,8 @@ class UnresolvedUninitializedThisRefType FINAL : public UninitializedType {
// sub-class.
class ReferenceType FINAL : public RegType {
public:
- ReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+ ReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -1034,7 +1051,8 @@ class ReferenceType FINAL : public RegType {
// type.
class PreciseReferenceType FINAL : public RegType {
public:
- PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+ PreciseReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index 61f34afdac..9f87adfa31 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
#include "class_linker.h"
+#include "class_root.h"
#include "mirror/class-inl.h"
#include "mirror/method_handle_impl.h"
#include "mirror/method_type.h"
@@ -123,36 +124,42 @@ inline const ImpreciseConstType& RegTypeCache::PosShortConstant() {
}
inline const PreciseReferenceType& RegTypeCache::JavaLangClass() {
- const RegType* result = &FromClass("Ljava/lang/Class;", mirror::Class::GetJavaLangClass(), true);
+ const RegType* result = &FromClass("Ljava/lang/Class;",
+ GetClassRoot<mirror::Class>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangString() {
// String is final and therefore always precise.
- const RegType* result = &FromClass("Ljava/lang/String;", mirror::String::GetJavaLangString(),
- true);
+ const RegType* result = &FromClass("Ljava/lang/String;",
+ GetClassRoot<mirror::String>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodHandle() {
const RegType* result = &FromClass("Ljava/lang/invoke/MethodHandle;",
- mirror::MethodHandle::StaticClass(), true);
+ GetClassRoot<mirror::MethodHandle>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodType() {
const RegType* result = &FromClass("Ljava/lang/invoke/MethodType;",
- mirror::MethodType::StaticClass(), true);
+ GetClassRoot<mirror::MethodType>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const RegType& RegTypeCache::JavaLangThrowable(bool precise) {
const RegType* result = &FromClass("Ljava/lang/Throwable;",
- mirror::Throwable::GetJavaLangThrowable(), precise);
+ GetClassRoot<mirror::Throwable>(),
+ precise);
if (precise) {
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
@@ -163,8 +170,7 @@ inline const RegType& RegTypeCache::JavaLangThrowable(bool precise) {
}
inline const RegType& RegTypeCache::JavaLangObject(bool precise) {
- const RegType* result = &FromClass("Ljava/lang/Object;",
- mirror::Class::GetJavaLangClass()->GetSuperClass(), precise);
+ const RegType* result = &FromClass("Ljava/lang/Object;", GetClassRoot<mirror::Object>(), precise);
if (precise) {
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
@@ -179,7 +185,7 @@ inline RegTypeType& RegTypeCache::AddEntry(RegTypeType* new_entry) {
DCHECK(new_entry != nullptr);
entries_.push_back(new_entry);
if (new_entry->HasClass()) {
- mirror::Class* klass = new_entry->GetClass();
+ ObjPtr<mirror::Class> klass = new_entry->GetClass();
DCHECK(!klass->IsPrimitive());
klass_entries_.push_back(std::make_pair(GcRoot<mirror::Class>(klass), new_entry));
}
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 87fc60bd23..f1f3488a3c 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -77,7 +77,7 @@ void RegTypeCache::FillPrimitiveAndSmallConstantTypes() {
DCHECK_EQ(entries_.size(), primitive_count_);
}
-const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader,
+const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader,
const char* descriptor,
bool precise) {
DCHECK(RegTypeCache::primitive_initialized_);
@@ -149,14 +149,15 @@ bool RegTypeCache::MatchDescriptor(size_t idx, const StringPiece& descriptor, bo
return true;
}
-mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) {
+ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor,
+ ObjPtr<mirror::ClassLoader> loader) {
// Class was not found, must create new type.
// Try resolving class
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader));
- mirror::Class* klass = nullptr;
+ ObjPtr<mirror::Class> klass = nullptr;
if (can_load_classes_) {
klass = class_linker->FindClass(self, descriptor, class_loader);
} else {
@@ -175,7 +176,7 @@ StringPiece RegTypeCache::AddString(const StringPiece& string_piece) {
return StringPiece(ptr, string_piece.length());
}
-const RegType& RegTypeCache::From(mirror::ClassLoader* loader,
+const RegType& RegTypeCache::From(ObjPtr<mirror::ClassLoader> loader,
const char* descriptor,
bool precise) {
StringPiece sp_descriptor(descriptor);
@@ -188,7 +189,7 @@ const RegType& RegTypeCache::From(mirror::ClassLoader* loader,
}
// Class not found in the cache, will create a new type for that.
// Try resolving class.
- mirror::Class* klass = ResolveClass(descriptor, loader);
+ ObjPtr<mirror::Class> klass = ResolveClass(descriptor, loader);
if (klass != nullptr) {
// Class resolved, first look for the class in the list of entries
// Class was not found, must create new type.
@@ -234,7 +235,7 @@ const RegType& RegTypeCache::MakeUnresolvedReference() {
return AddEntry(new (&allocator_) UnresolvedReferenceType(AddString("a"), entries_.size()));
}
-const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const {
+const RegType* RegTypeCache::FindClass(ObjPtr<mirror::Class> klass, bool precise) const {
DCHECK(klass != nullptr);
if (klass->IsPrimitive()) {
// Note: precise isn't used for primitive classes. A char is assignable to an int. All
@@ -242,7 +243,7 @@ const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const
return &RegTypeFromPrimitiveType(klass->GetPrimitiveType());
}
for (auto& pair : klass_entries_) {
- mirror::Class* const reg_klass = pair.first.Read();
+ ObjPtr<mirror::Class> const reg_klass = pair.first.Read();
if (reg_klass == klass) {
const RegType* reg_type = pair.second;
if (MatchingPrecisionForClass(reg_type, precise)) {
@@ -254,7 +255,7 @@ const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const
}
const RegType* RegTypeCache::InsertClass(const StringPiece& descriptor,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
bool precise) {
// No reference to the class was found, create new reference.
DCHECK(FindClass(klass, precise) == nullptr);
@@ -265,7 +266,9 @@ const RegType* RegTypeCache::InsertClass(const StringPiece& descriptor,
return &AddEntry(reg_type);
}
-const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
+const RegType& RegTypeCache::FromClass(const char* descriptor,
+ ObjPtr<mirror::Class> klass,
+ bool precise) {
DCHECK(klass != nullptr);
const RegType* reg_type = FindClass(klass, precise);
if (reg_type == nullptr) {
@@ -342,7 +345,7 @@ void RegTypeCache::CreatePrimitiveAndSmallConstantTypes() {
// code cannot leak to other users.
auto create_primitive_type_instance = [&](auto type) REQUIRES_SHARED(Locks::mutator_lock_) {
using Type = typename decltype(type)::type;
- mirror::Class* klass = nullptr;
+ ObjPtr<mirror::Class> klass = nullptr;
// Try loading the class from linker.
DCHECK(type.descriptor != nullptr);
if (strlen(type.descriptor) > 0) {
@@ -500,7 +503,7 @@ const UninitializedType& RegTypeCache::Uninitialized(const RegType& type, uint32
allocation_pc,
entries_.size());
} else {
- mirror::Class* klass = type.GetClass();
+ ObjPtr<mirror::Class> klass = type.GetClass();
for (size_t i = primitive_count_; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedReference() &&
@@ -532,7 +535,7 @@ const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
}
entry = new (&allocator_) UnresolvedReferenceType(descriptor, entries_.size());
} else {
- mirror::Class* klass = uninit_type.GetClass();
+ ObjPtr<mirror::Class> klass = uninit_type.GetClass();
if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
// For uninitialized "this reference" look for reference types that are not precise.
for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -583,7 +586,7 @@ const UninitializedType& RegTypeCache::UninitializedThisArgument(const RegType&
}
entry = new (&allocator_) UnresolvedUninitializedThisRefType(descriptor, entries_.size());
} else {
- mirror::Class* klass = type.GetClass();
+ ObjPtr<mirror::Class> klass = type.GetClass();
for (size_t i = primitive_count_; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
@@ -647,7 +650,8 @@ const ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
return AddEntry(entry);
}
-const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
+const RegType& RegTypeCache::GetComponentType(const RegType& array,
+ ObjPtr<mirror::ClassLoader> loader) {
if (!array.IsArrayTypes()) {
return Conflict();
} else if (array.IsUnresolvedTypes()) {
@@ -655,7 +659,7 @@ const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::Clas
const std::string descriptor(array.GetDescriptor().as_string());
return FromDescriptor(loader, descriptor.c_str() + 1, false);
} else {
- mirror::Class* klass = array.GetClass()->GetComponentType();
+ ObjPtr<mirror::Class> klass = array.GetClass()->GetComponentType();
std::string temp;
const char* descriptor = klass->GetDescriptor(&temp);
if (klass->IsErroneous()) {
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index b32dc115a7..d668222901 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -74,16 +74,18 @@ class RegTypeCache {
}
static void ShutDown();
const art::verifier::RegType& GetFromId(uint16_t id) const;
- const RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise)
+ const RegType& From(ObjPtr<mirror::ClassLoader> loader, const char* descriptor, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
// Find a RegType, returns null if not found.
- const RegType* FindClass(mirror::Class* klass, bool precise) const
+ const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Insert a new class with a specified descriptor, must not already be in the cache.
- const RegType* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool precise)
+ const RegType* InsertClass(const StringPiece& descriptor,
+ ObjPtr<mirror::Class> klass,
+ bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get or insert a reg type for a description, klass, and precision.
- const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
+ const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
const ConstantType& FromCat1Const(int32_t value, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -91,7 +93,9 @@ class RegTypeCache {
REQUIRES_SHARED(Locks::mutator_lock_);
const ConstantType& FromCat2ConstHi(int32_t value, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
- const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
+ const RegType& FromDescriptor(ObjPtr<mirror::ClassLoader> loader,
+ const char* descriptor,
+ bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
const RegType& FromUnresolvedMerge(const RegType& left,
const RegType& right,
@@ -146,7 +150,7 @@ class RegTypeCache {
const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_);
const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_);
const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_);
- const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader)
+ const RegType& GetComponentType(const RegType& array, ObjPtr<mirror::ClassLoader> loader)
REQUIRES_SHARED(Locks::mutator_lock_);
void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_);
const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
@@ -158,7 +162,7 @@ class RegTypeCache {
private:
void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
+ ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader)
REQUIRES_SHARED(Locks::mutator_lock_);
bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index fe839f7312..fb91976781 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -77,8 +77,8 @@ const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex
static constexpr uint32_t kAccVdexAccessFlags =
kAccPublic | kAccPrivate | kAccProtected | kAccStatic | kAccInterface;
-template <typename T>
-uint16_t VerifierDeps::GetAccessFlags(T* element) {
+template <typename Ptr>
+uint16_t VerifierDeps::GetAccessFlags(Ptr element) {
static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
if (element == nullptr) {
return VerifierDeps::kUnresolvedMarker;
@@ -277,7 +277,7 @@ bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) const {
void VerifierDeps::AddClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass) {
+ ObjPtr<mirror::Class> klass) {
DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
if (dex_deps == nullptr) {
// This invocation is from verification of a dex file which is not being compiled.
@@ -336,12 +336,13 @@ void VerifierDeps::AddMethodResolution(const DexFile& dex_file,
dex_deps->methods_.insert(method_tuple);
}
-mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class* destination,
- mirror::Class* source) const {
+ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface(
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source) const {
DCHECK(destination->IsInterface());
DCHECK(IsInClassPath(destination));
Thread* thread = Thread::Current();
- mirror::Class* current = source;
+ ObjPtr<mirror::Class> current = source;
// Record the classes that are at the boundary between the compiled DEX files and
// the classpath. We will check those classes later to find one class that inherits
// `destination`.
@@ -367,7 +368,7 @@ mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class*
int32_t iftable_count = source->GetIfTableCount();
ObjPtr<mirror::IfTable> iftable = source->GetIfTable();
for (int32_t i = 0; i < iftable_count; ++i) {
- mirror::Class* itf = iftable->GetInterface(i);
+ ObjPtr<mirror::Class> itf = iftable->GetInterface(i);
if (!IsInClassPath(itf)) {
for (size_t j = 0; j < itf->NumDirectInterfaces(); ++j) {
ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, itf, j);
@@ -383,7 +384,7 @@ mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class*
// Find a boundary making `source` inherit from `destination`. We must find one.
for (const ObjPtr<mirror::Class>& boundary : boundaries) {
if (destination->IsAssignableFrom(boundary)) {
- return boundary.Ptr();
+ return boundary;
}
}
LOG(FATAL) << "Should have found a classpath boundary";
@@ -391,8 +392,8 @@ mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class*
}
void VerifierDeps::AddAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable) {
// Test that the method is only called on reference types.
@@ -429,8 +430,8 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file,
// Both types are arrays. Break down to component types and add recursively.
// This helps filter out destinations from compiled DEX files (see below)
// and deduplicate entries with the same canonical component type.
- mirror::Class* destination_component = destination->GetComponentType();
- mirror::Class* source_component = source->GetComponentType();
+ ObjPtr<mirror::Class> destination_component = destination->GetComponentType();
+ ObjPtr<mirror::Class> source_component = source->GetComponentType();
// Only perform the optimization if both types are resolved which guarantees
// that they linked successfully, as required at the top of this method.
@@ -511,7 +512,7 @@ void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass) {
+ ObjPtr<mirror::Class> klass) {
VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
if (thread_deps != nullptr) {
thread_deps->AddClassResolution(dex_file, type_idx, klass);
@@ -537,8 +538,8 @@ void VerifierDeps::MaybeRecordMethodResolution(const DexFile& dex_file,
}
void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable) {
VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
@@ -858,12 +859,12 @@ bool VerifierDeps::ValidateDependencies(Handle<mirror::ClassLoader> class_loader
// TODO: share that helper with other parts of the compiler that have
// the same lookup pattern.
-static mirror::Class* FindClassAndClearException(ClassLinker* class_linker,
- Thread* self,
- const char* name,
- Handle<mirror::ClassLoader> class_loader)
+static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
+ Thread* self,
+ const char* name,
+ Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* result = class_linker->FindClass(self, name, class_loader);
+ ObjPtr<mirror::Class> result = class_linker->FindClass(self, name, class_loader);
if (result == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
@@ -971,7 +972,7 @@ bool VerifierDeps::VerifyFields(Handle<mirror::ClassLoader> class_loader,
std::string expected_decl_klass = entry.IsResolved()
? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
: dex_file.StringByTypeIdx(field_id.class_idx_);
- mirror::Class* cls = FindClassAndClearException(
+ ObjPtr<mirror::Class> cls = FindClassAndClearException(
class_linker, self, expected_decl_klass.c_str(), class_loader);
if (cls == nullptr) {
LOG(INFO) << "VerifierDeps: Could not resolve class " << expected_decl_klass;
@@ -1034,7 +1035,7 @@ bool VerifierDeps::VerifyMethods(Handle<mirror::ClassLoader> class_loader,
? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
: dex_file.StringByTypeIdx(method_id.class_idx_);
- mirror::Class* cls = FindClassAndClearException(
+ ObjPtr<mirror::Class> cls = FindClassAndClearException(
class_linker, self, expected_decl_klass.c_str(), class_loader);
if (cls == nullptr) {
LOG(INFO) << "VerifierDeps: Could not resolve class " << expected_decl_klass;
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 94441da7e2..0146b17020 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -75,7 +75,7 @@ class VerifierDeps {
// If `klass` is null, the class is assumed unresolved.
static void MaybeRecordClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass)
+ ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::verifier_deps_lock_);
@@ -99,8 +99,8 @@ class VerifierDeps {
// to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
// owner of the method for which MethodVerifier performed the assignability test.
static void MaybeRecordAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -218,8 +218,8 @@ class VerifierDeps {
// Finds the class in the classpath that makes `source` inherit` from `destination`.
// Returns null if a class defined in the compiled DEX files, and assignable to
// `source`, direclty inherits from `destination`.
- mirror::Class* FindOneClassPathBoundaryForInterface(mirror::Class* destination,
- mirror::Class* source) const
+ ObjPtr<mirror::Class> FindOneClassPathBoundaryForInterface(ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
@@ -234,8 +234,8 @@ class VerifierDeps {
// Returns the bytecode access flags of `element` (bottom 16 bits), or
// `kUnresolvedMarker` if `element` is null.
- template <typename T>
- static uint16_t GetAccessFlags(T* element)
+ template <typename Ptr>
+ static uint16_t GetAccessFlags(Ptr element)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a string ID of the descriptor of the declaring class of `element`,
@@ -256,7 +256,7 @@ class VerifierDeps {
void AddClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass)
+ ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::verifier_deps_lock_);
@@ -273,8 +273,8 @@ class VerifierDeps {
REQUIRES(!Locks::verifier_deps_lock_);
void AddAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index f7cdf3920a..c64e7bbca1 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -55,8 +55,6 @@ jclass WellKnownClasses::java_lang_ClassLoader;
jclass WellKnownClasses::java_lang_ClassNotFoundException;
jclass WellKnownClasses::java_lang_Daemons;
jclass WellKnownClasses::java_lang_Error;
-jclass WellKnownClasses::java_lang_invoke_MethodHandle;
-jclass WellKnownClasses::java_lang_invoke_VarHandle;
jclass WellKnownClasses::java_lang_IllegalAccessError;
jclass WellKnownClasses::java_lang_NoClassDefFoundError;
jclass WellKnownClasses::java_lang_Object;
@@ -74,7 +72,6 @@ jclass WellKnownClasses::java_lang_ThreadGroup;
jclass WellKnownClasses::java_lang_Throwable;
jclass WellKnownClasses::java_nio_ByteBuffer;
jclass WellKnownClasses::java_nio_DirectByteBuffer;
-jclass WellKnownClasses::java_util_ArrayList;
jclass WellKnownClasses::java_util_Collections;
jclass WellKnownClasses::java_util_function_Consumer;
jclass WellKnownClasses::libcore_reflect_AnnotationFactory;
@@ -90,14 +87,11 @@ jmethodID WellKnownClasses::java_lang_Byte_valueOf;
jmethodID WellKnownClasses::java_lang_Character_valueOf;
jmethodID WellKnownClasses::java_lang_ClassLoader_loadClass;
jmethodID WellKnownClasses::java_lang_ClassNotFoundException_init;
-jmethodID WellKnownClasses::java_lang_Daemons_requestHeapTrim;
jmethodID WellKnownClasses::java_lang_Daemons_start;
jmethodID WellKnownClasses::java_lang_Daemons_stop;
jmethodID WellKnownClasses::java_lang_Double_valueOf;
jmethodID WellKnownClasses::java_lang_Float_valueOf;
jmethodID WellKnownClasses::java_lang_Integer_valueOf;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandle_invoke;
-jmethodID WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact;
jmethodID WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
jmethodID WellKnownClasses::java_lang_invoke_MethodHandles_Lookup_findConstructor;
jmethodID WellKnownClasses::java_lang_Long_valueOf;
@@ -108,7 +102,6 @@ jmethodID WellKnownClasses::java_lang_reflect_Proxy_invoke;
jmethodID WellKnownClasses::java_lang_Runtime_nativeLoad;
jmethodID WellKnownClasses::java_lang_Short_valueOf;
jmethodID WellKnownClasses::java_lang_String_charAt;
-jmethodID WellKnownClasses::java_lang_System_runFinalization = nullptr;
jmethodID WellKnownClasses::java_lang_Thread_dispatchUncaughtException;
jmethodID WellKnownClasses::java_lang_Thread_init;
jmethodID WellKnownClasses::java_lang_Thread_run;
@@ -144,7 +137,6 @@ jfieldID WellKnownClasses::java_lang_Throwable_detailMessage;
jfieldID WellKnownClasses::java_lang_Throwable_stackTrace;
jfieldID WellKnownClasses::java_lang_Throwable_stackState;
jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
-jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
jfieldID WellKnownClasses::java_nio_ByteBuffer_address;
jfieldID WellKnownClasses::java_nio_ByteBuffer_hb;
jfieldID WellKnownClasses::java_nio_ByteBuffer_isReadOnly;
@@ -152,8 +144,6 @@ jfieldID WellKnownClasses::java_nio_ByteBuffer_limit;
jfieldID WellKnownClasses::java_nio_ByteBuffer_offset;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
-jfieldID WellKnownClasses::java_util_ArrayList_array;
-jfieldID WellKnownClasses::java_util_ArrayList_size;
jfieldID WellKnownClasses::java_util_Collections_EMPTY_LIST;
jfieldID WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT;
jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data;
@@ -323,8 +313,6 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_OutOfMemoryError = CacheClass(env, "java/lang/OutOfMemoryError");
java_lang_Error = CacheClass(env, "java/lang/Error");
java_lang_IllegalAccessError = CacheClass(env, "java/lang/IllegalAccessError");
- java_lang_invoke_MethodHandle = CacheClass(env, "java/lang/invoke/MethodHandle");
- java_lang_invoke_VarHandle = CacheClass(env, "java/lang/invoke/VarHandle");
java_lang_NoClassDefFoundError = CacheClass(env, "java/lang/NoClassDefFoundError");
java_lang_reflect_Parameter = CacheClass(env, "java/lang/reflect/Parameter");
java_lang_reflect_Parameter__array = CacheClass(env, "[Ljava/lang/reflect/Parameter;");
@@ -339,7 +327,6 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Throwable = CacheClass(env, "java/lang/Throwable");
java_nio_ByteBuffer = CacheClass(env, "java/nio/ByteBuffer");
java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer");
- java_util_ArrayList = CacheClass(env, "java/util/ArrayList");
java_util_Collections = CacheClass(env, "java/util/Collections");
java_util_function_Consumer = CacheClass(env, "java/util/function/Consumer");
libcore_reflect_AnnotationFactory = CacheClass(env, "libcore/reflect/AnnotationFactory");
@@ -353,11 +340,8 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_ClassNotFoundException_init = CacheMethod(env, java_lang_ClassNotFoundException, false, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
java_lang_ClassLoader_loadClass = CacheMethod(env, java_lang_ClassLoader, false, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
- java_lang_Daemons_requestHeapTrim = CacheMethod(env, java_lang_Daemons, true, "requestHeapTrim", "()V");
java_lang_Daemons_start = CacheMethod(env, java_lang_Daemons, true, "start", "()V");
java_lang_Daemons_stop = CacheMethod(env, java_lang_Daemons, true, "stop", "()V");
- java_lang_invoke_MethodHandle_invoke = CacheMethod(env, java_lang_invoke_MethodHandle, false, "invoke", "([Ljava/lang/Object;)Ljava/lang/Object;");
- java_lang_invoke_MethodHandle_invokeExact = CacheMethod(env, java_lang_invoke_MethodHandle, false, "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;");
java_lang_invoke_MethodHandles_lookup = CacheMethod(env, "java/lang/invoke/MethodHandles", true, "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;");
java_lang_invoke_MethodHandles_Lookup_findConstructor = CacheMethod(env, "java/lang/invoke/MethodHandles$Lookup", false, "findConstructor", "(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;");
@@ -408,8 +392,6 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_nio_ByteBuffer_offset = CacheField(env, java_nio_ByteBuffer, false, "offset", "I");
java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "address", "J");
- java_util_ArrayList_array = CacheField(env, java_util_ArrayList, false, "elementData", "[Ljava/lang/Object;");
- java_util_ArrayList_size = CacheField(env, java_util_ArrayList, false, "size", "I");
java_util_Collections_EMPTY_LIST = CacheField(env, java_util_Collections, true, "EMPTY_LIST", "Ljava/util/List;");
libcore_util_EmptyArray_STACK_TRACE_ELEMENT = CacheField(env, libcore_util_EmptyArray, true, "STACK_TRACE_ELEMENT", "[Ljava/lang/StackTraceElement;");
org_apache_harmony_dalvik_ddmc_Chunk_data = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "data", "[B");
@@ -440,9 +422,6 @@ void WellKnownClasses::LateInit(JNIEnv* env) {
CacheMethod(env, java_lang_reflect_Proxy, true, "invoke",
"(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;"
"[Ljava/lang/Object;)Ljava/lang/Object;");
- java_lang_reflect_Proxy_h =
- CacheField(env, java_lang_reflect_Proxy, false, "h",
- "Ljava/lang/reflect/InvocationHandler;");
}
void WellKnownClasses::Clear() {
@@ -464,8 +443,6 @@ void WellKnownClasses::Clear() {
java_lang_Daemons = nullptr;
java_lang_Error = nullptr;
java_lang_IllegalAccessError = nullptr;
- java_lang_invoke_MethodHandle = nullptr;
- java_lang_invoke_VarHandle = nullptr;
java_lang_NoClassDefFoundError = nullptr;
java_lang_Object = nullptr;
java_lang_OutOfMemoryError = nullptr;
@@ -480,7 +457,6 @@ void WellKnownClasses::Clear() {
java_lang_Thread = nullptr;
java_lang_ThreadGroup = nullptr;
java_lang_Throwable = nullptr;
- java_util_ArrayList = nullptr;
java_util_Collections = nullptr;
java_nio_ByteBuffer = nullptr;
java_nio_DirectByteBuffer = nullptr;
@@ -497,14 +473,11 @@ void WellKnownClasses::Clear() {
java_lang_Character_valueOf = nullptr;
java_lang_ClassLoader_loadClass = nullptr;
java_lang_ClassNotFoundException_init = nullptr;
- java_lang_Daemons_requestHeapTrim = nullptr;
java_lang_Daemons_start = nullptr;
java_lang_Daemons_stop = nullptr;
java_lang_Double_valueOf = nullptr;
java_lang_Float_valueOf = nullptr;
java_lang_Integer_valueOf = nullptr;
- java_lang_invoke_MethodHandle_invoke = nullptr;
- java_lang_invoke_MethodHandle_invokeExact = nullptr;
java_lang_invoke_MethodHandles_lookup = nullptr;
java_lang_invoke_MethodHandles_Lookup_findConstructor = nullptr;
java_lang_Long_valueOf = nullptr;
@@ -515,7 +488,6 @@ void WellKnownClasses::Clear() {
java_lang_Runtime_nativeLoad = nullptr;
java_lang_Short_valueOf = nullptr;
java_lang_String_charAt = nullptr;
- java_lang_System_runFinalization = nullptr;
java_lang_Thread_dispatchUncaughtException = nullptr;
java_lang_Thread_init = nullptr;
java_lang_Thread_run = nullptr;
@@ -533,7 +505,6 @@ void WellKnownClasses::Clear() {
dalvik_system_DexPathList_dexElements = nullptr;
dalvik_system_DexPathList__Element_dexFile = nullptr;
dalvik_system_VMRuntime_nonSdkApiUsageConsumer = nullptr;
- java_lang_reflect_Proxy_h = nullptr;
java_lang_Thread_daemon = nullptr;
java_lang_Thread_group = nullptr;
java_lang_Thread_lock = nullptr;
@@ -558,8 +529,6 @@ void WellKnownClasses::Clear() {
java_nio_ByteBuffer_offset = nullptr;
java_nio_DirectByteBuffer_capacity = nullptr;
java_nio_DirectByteBuffer_effectiveDirectAddress = nullptr;
- java_util_ArrayList_array = nullptr;
- java_util_ArrayList_size = nullptr;
java_util_Collections_EMPTY_LIST = nullptr;
libcore_util_EmptyArray_STACK_TRACE_ELEMENT = nullptr;
org_apache_harmony_dalvik_ddmc_Chunk_data = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index c06e4a71ce..c81062f594 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -66,8 +66,6 @@ struct WellKnownClasses {
static jclass java_lang_Daemons;
static jclass java_lang_Error;
static jclass java_lang_IllegalAccessError;
- static jclass java_lang_invoke_MethodHandle;
- static jclass java_lang_invoke_VarHandle;
static jclass java_lang_NoClassDefFoundError;
static jclass java_lang_Object;
static jclass java_lang_OutOfMemoryError;
@@ -82,7 +80,6 @@ struct WellKnownClasses {
static jclass java_lang_Thread;
static jclass java_lang_ThreadGroup;
static jclass java_lang_Throwable;
- static jclass java_util_ArrayList;
static jclass java_util_Collections;
static jclass java_util_function_Consumer;
static jclass java_nio_ByteBuffer;
@@ -100,14 +97,11 @@ struct WellKnownClasses {
static jmethodID java_lang_Character_valueOf;
static jmethodID java_lang_ClassLoader_loadClass;
static jmethodID java_lang_ClassNotFoundException_init;
- static jmethodID java_lang_Daemons_requestHeapTrim;
static jmethodID java_lang_Daemons_start;
static jmethodID java_lang_Daemons_stop;
static jmethodID java_lang_Double_valueOf;
static jmethodID java_lang_Float_valueOf;
static jmethodID java_lang_Integer_valueOf;
- static jmethodID java_lang_invoke_MethodHandle_invoke;
- static jmethodID java_lang_invoke_MethodHandle_invokeExact;
static jmethodID java_lang_invoke_MethodHandles_lookup;
static jmethodID java_lang_invoke_MethodHandles_Lookup_findConstructor;
static jmethodID java_lang_Long_valueOf;
@@ -118,7 +112,6 @@ struct WellKnownClasses {
static jmethodID java_lang_Runtime_nativeLoad;
static jmethodID java_lang_Short_valueOf;
static jmethodID java_lang_String_charAt;
- static jmethodID java_lang_System_runFinalization;
static jmethodID java_lang_Thread_dispatchUncaughtException;
static jmethodID java_lang_Thread_init;
static jmethodID java_lang_Thread_run;
@@ -137,7 +130,6 @@ struct WellKnownClasses {
static jfieldID dalvik_system_DexPathList_dexElements;
static jfieldID dalvik_system_DexPathList__Element_dexFile;
static jfieldID dalvik_system_VMRuntime_nonSdkApiUsageConsumer;
- static jfieldID java_lang_reflect_Proxy_h;
static jfieldID java_lang_Thread_daemon;
static jfieldID java_lang_Thread_group;
static jfieldID java_lang_Thread_lock;
@@ -163,8 +155,6 @@ struct WellKnownClasses {
static jfieldID java_nio_DirectByteBuffer_capacity;
static jfieldID java_nio_DirectByteBuffer_effectiveDirectAddress;
- static jfieldID java_util_ArrayList_array;
- static jfieldID java_util_ArrayList_size;
static jfieldID java_util_Collections_EMPTY_LIST;
static jfieldID libcore_util_EmptyArray_STACK_TRACE_ELEMENT;
static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_data;
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index 49db0c82b5..7ada47d304 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -56,9 +56,12 @@ static void CauseSegfault() {
extern "C" JNIEXPORT jboolean JNICALL Java_Main_sleep(JNIEnv*, jobject, jint, jboolean, jdouble) {
// Keep pausing.
+ struct timespec ts = { .tv_sec = 100, .tv_nsec = 0 };
printf("Going to sleep\n");
for (;;) {
- sleep(1);
+ // Use nanosleep since it gets to the system call quickly and doesn't
+ // have any points at which an unwind will fail.
+ nanosleep(&ts, nullptr);
}
}
diff --git a/test/166-bad-interface-super/build b/test/166-bad-interface-super/build
index d85147f17b..bba6184e16 100644
--- a/test/166-bad-interface-super/build
+++ b/test/166-bad-interface-super/build
@@ -14,7 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
+# Use the jasmin sources for JVM, otherwise the smali sources.
+extra_arg="--no-jasmin"
-./default-build "$@"
+for arg in "$@"; do
+ if [[ "$arg" == "--jvm" ]]; then
+ extra_arg="--no-smali"
+ break
+ fi
+done
+
+./default-build "$@" "$extra_arg"
diff --git a/test/476-checker-ctor-fence-redun-elim/build b/test/166-bad-interface-super/smali/BadSuper1.smali
index 10ffcc537d..6233403897 100644
--- a/test/476-checker-ctor-fence-redun-elim/build
+++ b/test/166-bad-interface-super/smali/BadSuper1.smali
@@ -1,6 +1,4 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
+# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
+.class public interface LBadSuper1;
+.super LBaseInterface;
+.source "BadSuper1.j"
diff --git a/test/458-checker-instruct-simplification/build b/test/166-bad-interface-super/smali/BadSuper2.smali
index 10ffcc537d..8e410cf1b4 100755..100644
--- a/test/458-checker-instruct-simplification/build
+++ b/test/166-bad-interface-super/smali/BadSuper2.smali
@@ -1,6 +1,4 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
+# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
+.class public interface LBadSuper2;
+.super LBaseClass;
+.source "BadSuper2.j"
diff --git a/test/450-checker-types/build b/test/450-checker-types/build
deleted file mode 100755
index 10ffcc537d..0000000000
--- a/test/450-checker-types/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/458-checker-instruct-simplification/smali/SmaliTests2.smali b/test/458-checker-instruct-simplification/smali/SmaliTests2.smali
new file mode 100644
index 0000000000..99fb049510
--- /dev/null
+++ b/test/458-checker-instruct-simplification/smali/SmaliTests2.smali
@@ -0,0 +1,305 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSmaliTests2;
+.super Ljava/lang/Object;
+
+## CHECK-START: int SmaliTests2.$noinline$XorAllOnes(int) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:i\d+>> ParameterValue
+## CHECK-DAG: <<ConstF:i\d+>> IntConstant -1
+## CHECK-DAG: <<Xor:i\d+>> Xor [<<Arg>>,<<ConstF>>]
+## CHECK-DAG: Return [<<Xor>>]
+
+## CHECK-START: int SmaliTests2.$noinline$XorAllOnes(int) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:i\d+>> ParameterValue
+## CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>]
+## CHECK-DAG: Return [<<Not>>]
+
+## CHECK-START: int SmaliTests2.$noinline$XorAllOnes(int) instruction_simplifier (after)
+## CHECK-NOT: Xor
+
+# Original java source:
+#
+# return arg ^ -1;
+#
+.method public static $noinline$XorAllOnes(I)I
+ .registers 2
+ .param p0, "arg" # I
+
+ .prologue
+ .line 658
+ xor-int/lit8 v0, p0, -0x1
+
+ return v0
+.end method
+
+# Test simplification of the `~~var` pattern.
+# The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNot`.
+
+## CHECK-START: long SmaliTests2.$noinline$NotNot1(long) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:j\d+>> ParameterValue
+## CHECK-DAG: <<ConstNeg1:j\d+>> LongConstant -1
+## CHECK-DAG: <<Not1:j\d+>> Xor [<<Arg>>,<<ConstNeg1>>]
+## CHECK-DAG: <<Not2:j\d+>> Xor [<<Not1>>,<<ConstNeg1>>]
+## CHECK-DAG: Return [<<Not2>>]
+
+## CHECK-START: long SmaliTests2.$noinline$NotNot1(long) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:j\d+>> ParameterValue
+## CHECK-DAG: Return [<<Arg>>]
+
+## CHECK-START: long SmaliTests2.$noinline$NotNot1(long) instruction_simplifier (after)
+## CHECK-NOT: Xor
+
+# Original java source:
+#
+# return ~~arg;
+.method public static $noinline$NotNot1(J)J
+ .registers 6
+ .param p0, "arg" # J
+
+ .prologue
+ const-wide/16 v2, -0x1
+
+ .line 1001
+ xor-long v0, p0, v2
+
+ xor-long/2addr v0, v2
+
+ return-wide v0
+.end method
+
+## CHECK-START: int SmaliTests2.$noinline$NotNot2(int) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:i\d+>> ParameterValue
+## CHECK-DAG: <<ConstNeg1:i\d+>> IntConstant -1
+## CHECK-DAG: <<Not1:i\d+>> Xor [<<Arg>>,<<ConstNeg1>>]
+## CHECK-DAG: <<Not2:i\d+>> Xor [<<Not1>>,<<ConstNeg1>>]
+## CHECK-DAG: <<Add:i\d+>> Add [<<Not2>>,<<Not1>>]
+## CHECK-DAG: Return [<<Add>>]
+
+## CHECK-START: int SmaliTests2.$noinline$NotNot2(int) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:i\d+>> ParameterValue
+## CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>]
+## CHECK-DAG: <<Add:i\d+>> Add [<<Arg>>,<<Not>>]
+## CHECK-DAG: Return [<<Add>>]
+
+## CHECK-START: int SmaliTests2.$noinline$NotNot2(int) instruction_simplifier (after)
+## CHECK: Not
+## CHECK-NOT: Not
+
+## CHECK-START: int SmaliTests2.$noinline$NotNot2(int) instruction_simplifier (after)
+## CHECK-NOT: Xor
+
+# Original java source:
+#
+# int temp = ~arg;
+# return temp + ~temp;
+#
+.method public static $noinline$NotNot2(I)I
+ .registers 3
+ .param p0, "arg" # I
+
+ .prologue
+ .line 1026
+ xor-int/lit8 v0, p0, -0x1
+
+ .line 1027
+ .local v0, "temp":I
+ xor-int/lit8 v1, v0, -0x1
+
+ add-int/2addr v1, v0
+
+ return v1
+.end method
+
+# Original java source:
+#
+# return !arg;
+#
+.method public static NegateValue(Z)Z
+ .registers 2
+ .param p0, "arg" # Z
+
+ .prologue
+ .line 1216
+ if-nez p0, :cond_4
+
+ const/4 v0, 0x1
+
+ :goto_3
+ return v0
+
+ :cond_4
+ const/4 v0, 0x0
+
+ goto :goto_3
+.end method
+
+# Test simplification of double Boolean negation. Note that sometimes
+# both negations can be removed but we only expect the simplifier to
+# remove the second.
+
+## CHECK-START: boolean SmaliTests2.$noinline$NotNotBool(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 0
+## CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect method_name:SmaliTests2.NegateValue
+## CHECK-DAG: <<NotResult:z\d+>> NotEqual [<<Result>>,<<Const1>>]
+## CHECK-DAG: If [<<NotResult>>]
+
+## CHECK-START: boolean SmaliTests2.$noinline$NotNotBool(boolean) instruction_simplifier (after)
+## CHECK-NOT: NotEqual
+
+## CHECK-START: boolean SmaliTests2.$noinline$NotNotBool(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect method_name:SmaliTests2.NegateValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: Return [<<Phi>>]
+
+## CHECK-START: boolean SmaliTests2.$noinline$NotNotBool(boolean) instruction_simplifier$after_inlining (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: If [<<Arg>>]
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: Return [<<Phi>>]
+
+## CHECK-START: boolean SmaliTests2.$noinline$NotNotBool(boolean) instruction_simplifier$after_gvn (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: Return [<<Arg>>]
+
+# Original java source:
+#
+# return !(NegateValue(arg));
+#
+.method public static $noinline$NotNotBool(Z)Z
+ .registers 2
+ .param p0, "arg" # Z
+
+ .prologue
+ .line 1220
+ invoke-static {p0}, LSmaliTests2;->NegateValue(Z)Z
+
+ move-result v0
+
+ if-nez v0, :cond_8
+
+ const/4 v0, 0x1
+
+ :goto_7
+ return v0
+
+ :cond_8
+ const/4 v0, 0x0
+
+ goto :goto_7
+.end method
+
+## CHECK-START: int SmaliTests2.$noinline$bug68142795Short(short) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:s\d+>> ParameterValue
+## CHECK-DAG: <<Const:i\d+>> IntConstant 65535
+## CHECK-DAG: <<And1:i\d+>> And [<<Arg>>,<<Const>>]
+## CHECK-DAG: <<And2:i\d+>> And [<<And1>>,<<Const>>]
+## CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<And2>>]
+## CHECK-DAG: Return [<<Conv>>]
+
+## CHECK-START: int SmaliTests2.$noinline$bug68142795Short(short) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:s\d+>> ParameterValue
+## CHECK-DAG: Return [<<Arg>>]
+
+# Original java source
+#
+# return (short)(0xffff & (s & 0xffff));
+#
+.method public static $noinline$bug68142795Short(S)I
+ .registers 3
+ .param p0, "s" # S
+
+ .prologue
+ const v1, 0xffff
+
+ .line 2562
+ and-int v0, p0, v1
+
+ and-int/2addr v0, v1
+
+ int-to-short v0, v0
+
+ return v0
+.end method
+
+# Original java source
+#
+# return 255;
+#
+.method private static $inline$get255()I
+ .registers 1
+
+ .prologue
+ .line 2849
+ const/16 v0, 0xff
+
+ return v0
+.end method
+
+## CHECK-START: int SmaliTests2.$noinline$bug68142795Boolean(boolean) instruction_simplifier$after_inlining (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Const255:i\d+>> IntConstant 255
+## CHECK-DAG: If [<<Arg>>]
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: <<And:i\d+>> And [<<Const255>>,<<Phi>>]
+## CHECK-DAG: <<Conv:b\d+>> TypeConversion [<<And>>]
+## CHECK-DAG: Return [<<Conv>>]
+
+## CHECK-START: int SmaliTests2.$noinline$bug68142795Boolean(boolean) instruction_simplifier$after_gvn (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: Return [<<Arg>>]
+
+# Original java source
+#
+# int v = b ? 1 : 0; // Should be simplified to "b" after inlining.
+# return (byte)($inline$get255() & v);
+#
+.method public static $noinline$bug68142795Boolean(Z)I
+ .registers 3
+ .param p0, "b" # Z
+
+ .prologue
+ .line 2580
+ if-eqz p0, :cond_a
+
+ const/4 v0, 0x1
+
+ .line 2581
+ .local v0, "v":I
+ :goto_3
+ invoke-static {}, LSmaliTests2;->$inline$get255()I
+
+ move-result v1
+
+ and-int/2addr v1, v0
+
+ int-to-byte v1, v1
+
+ return v1
+
+ .line 2580
+ .end local v0 # "v":I
+ :cond_a
+ const/4 v0, 0x0
+
+ goto :goto_3
+.end method
diff --git a/test/458-checker-instruct-simplification/src/Main.java b/test/458-checker-instruct-simplification/src/Main.java
index b24cfcb775..40e3778109 100644
--- a/test/458-checker-instruct-simplification/src/Main.java
+++ b/test/458-checker-instruct-simplification/src/Main.java
@@ -640,24 +640,6 @@ public class Main {
return arg ^ 0;
}
- /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:i\d+>> ParameterValue
- /// CHECK-DAG: <<ConstF:i\d+>> IntConstant -1
- /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Arg>>,<<ConstF>>]
- /// CHECK-DAG: Return [<<Xor>>]
-
- /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:i\d+>> ParameterValue
- /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>]
- /// CHECK-DAG: Return [<<Not>>]
-
- /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (after)
- /// CHECK-NOT: Xor
-
- public static int $noinline$XorAllOnes(int arg) {
- return arg ^ -1;
- }
-
/**
* Test that addition or subtraction operation with both inputs negated are
* optimized to use a single negation after the operation.
@@ -978,56 +960,7 @@ public class Main {
return -temp | -temp;
}
- /**
- * Test simplification of the `~~var` pattern.
- * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNot`.
- */
-
- /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:j\d+>> ParameterValue
- /// CHECK-DAG: <<ConstNeg1:j\d+>> LongConstant -1
- /// CHECK-DAG: <<Not1:j\d+>> Xor [<<Arg>>,<<ConstNeg1>>]
- /// CHECK-DAG: <<Not2:j\d+>> Xor [<<Not1>>,<<ConstNeg1>>]
- /// CHECK-DAG: Return [<<Not2>>]
-
- /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:j\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Arg>>]
-
- /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (after)
- /// CHECK-NOT: Xor
-
- public static long $noinline$NotNot1(long arg) {
- return ~~arg;
- }
-
- /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:i\d+>> ParameterValue
- /// CHECK-DAG: <<ConstNeg1:i\d+>> IntConstant -1
- /// CHECK-DAG: <<Not1:i\d+>> Xor [<<Arg>>,<<ConstNeg1>>]
- /// CHECK-DAG: <<Not2:i\d+>> Xor [<<Not1>>,<<ConstNeg1>>]
- /// CHECK-DAG: <<Add:i\d+>> Add [<<Not2>>,<<Not1>>]
- /// CHECK-DAG: Return [<<Add>>]
-
- /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:i\d+>> ParameterValue
- /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>]
- /// CHECK-DAG: <<Add:i\d+>> Add [<<Arg>>,<<Not>>]
- /// CHECK-DAG: Return [<<Add>>]
-
- /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (after)
- /// CHECK: Not
- /// CHECK-NOT: Not
-
- /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (after)
- /// CHECK-NOT: Xor
-
- public static int $noinline$NotNot2(int arg) {
- int temp = ~arg;
- return temp + ~temp;
- }
-
- /**
+ /**
* Test the simplification of a subtraction with a negated argument.
* The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`.
*/
@@ -1176,50 +1109,6 @@ public class Main {
return (arg ? $inline$ReturnArg(0) : $inline$ReturnArg(1)) == 2;
}
- /*
- * Test simplification of double Boolean negation. Note that sometimes
- * both negations can be removed but we only expect the simplifier to
- * remove the second.
- */
-
- /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect method_name:Main.NegateValue
- /// CHECK-DAG: <<NotResult:z\d+>> NotEqual [<<Result>>,<<Const1>>]
- /// CHECK-DAG: If [<<NotResult>>]
-
- /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier (after)
- /// CHECK-NOT: NotEqual
-
- /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect method_name:Main.NegateValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier$after_inlining (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: If [<<Arg>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier$after_gvn (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Arg>>]
-
- public static boolean NegateValue(boolean arg) {
- return !arg;
- }
-
- public static boolean $noinline$NotNotBool(boolean arg) {
- return !(NegateValue(arg));
- }
-
/// CHECK-START: float Main.$noinline$Div2(float) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:f\d+>> ParameterValue
/// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2
@@ -1911,9 +1800,9 @@ public class Main {
}
}
- public static boolean $noinline$runSmaliTestBoolean(String name, boolean input) {
+ public static boolean $noinline$runSmaliTest2Boolean(String name, boolean input) {
try {
- Class<?> c = Class.forName("SmaliTests");
+ Class<?> c = Class.forName("SmaliTests2");
Method m = c.getMethod(name, boolean.class);
return (Boolean) m.invoke(null, input);
} catch (Exception ex) {
@@ -1921,9 +1810,9 @@ public class Main {
}
}
- public static int $noinline$runSmaliTestInt(String name, int arg) {
+ public static int $noinline$runSmaliTestInt(String postfix, String name, int arg) {
try {
- Class<?> c = Class.forName("SmaliTests");
+ Class<?> c = Class.forName("SmaliTests" + postfix);
Method m = c.getMethod(name, int.class);
return (Integer) m.invoke(null, arg);
} catch (Exception ex) {
@@ -1931,9 +1820,13 @@ public class Main {
}
}
- public static long $noinline$runSmaliTestLong(String name, long arg) {
+ public static int $noinline$runSmaliTestInt(String name, int arg) {
+ return $noinline$runSmaliTestInt("", name, arg);
+ }
+
+ public static long $noinline$runSmaliTest2Long(String name, long arg) {
try {
- Class<?> c = Class.forName("SmaliTests");
+ Class<?> c = Class.forName("SmaliTests2");
Method m = c.getMethod(name, long.class);
return (Long) m.invoke(null, arg);
} catch (Exception ex) {
@@ -2547,40 +2440,6 @@ public class Main {
return (byte)(0xff & (b & 0xff));
}
- /// CHECK-START: int Main.$noinline$bug68142795Short(short) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:s\d+>> ParameterValue
- /// CHECK-DAG: <<Const:i\d+>> IntConstant 65535
- /// CHECK-DAG: <<And1:i\d+>> And [<<Arg>>,<<Const>>]
- /// CHECK-DAG: <<And2:i\d+>> And [<<And1>>,<<Const>>]
- /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<And2>>]
- /// CHECK-DAG: Return [<<Conv>>]
-
- /// CHECK-START: int Main.$noinline$bug68142795Short(short) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:s\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Arg>>]
- public static int $noinline$bug68142795Short(short s) {
- return (short)(0xffff & (s & 0xffff));
- }
-
- /// CHECK-START: int Main.$noinline$bug68142795Boolean(boolean) instruction_simplifier$after_inlining (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Const255:i\d+>> IntConstant 255
- /// CHECK-DAG: If [<<Arg>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: <<And:i\d+>> And [<<Const255>>,<<Phi>>]
- /// CHECK-DAG: <<Conv:b\d+>> TypeConversion [<<And>>]
- /// CHECK-DAG: Return [<<Conv>>]
-
- /// CHECK-START: int Main.$noinline$bug68142795Boolean(boolean) instruction_simplifier$after_gvn (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: Return [<<Arg>>]
- public static int $noinline$bug68142795Boolean(boolean b) {
- int v = b ? 1 : 0; // Should be simplified to "b" after inlining.
- return (byte)($inline$get255() & v);
- }
-
/// CHECK-START: int Main.$noinline$bug68142795Elaborate(byte) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:b\d+>> ParameterValue
/// CHECK-DAG: <<Int255:i\d+>> IntConstant 255
@@ -2599,7 +2458,15 @@ public class Main {
return (byte)((int)(((long)(b & 0xff)) & 255L));
}
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
+ Class smaliTests2 = Class.forName("SmaliTests2");
+ Method $noinline$XorAllOnes = smaliTests2.getMethod("$noinline$XorAllOnes", int.class);
+ Method $noinline$NotNot1 = smaliTests2.getMethod("$noinline$NotNot1", long.class);
+ Method $noinline$NotNot2 = smaliTests2.getMethod("$noinline$NotNot2", int.class);
+ Method $noinline$NotNotBool = smaliTests2.getMethod("$noinline$NotNotBool", boolean.class);
+ Method $noinline$bug68142795Short = smaliTests2.getMethod("$noinline$bug68142795Short", short.class);
+ Method $noinline$bug68142795Boolean = smaliTests2.getMethod("$noinline$bug68142795Boolean", boolean.class);
+
int arg = 123456;
float floatArg = 123456.125f;
@@ -2624,7 +2491,7 @@ public class Main {
assertLongEquals(3, $noinline$SubSubConst(4));
assertLongEquals(arg, $noinline$UShr0(arg));
assertIntEquals(arg, $noinline$Xor0(arg));
- assertIntEquals(~arg, $noinline$XorAllOnes(arg));
+ assertIntEquals(~arg, (int)$noinline$XorAllOnes.invoke(null, arg));
assertIntEquals(-(arg + arg + 1), $noinline$AddNegs1(arg, arg + 1));
assertIntEquals(-(arg + arg + 1), $noinline$AddNegs2(arg, arg + 1));
assertLongEquals(-(2 * arg + 1), $noinline$AddNegs3(arg, arg + 1));
@@ -2635,10 +2502,10 @@ public class Main {
assertLongEquals(arg, $noinline$NegNeg3(arg));
assertIntEquals(1, $noinline$NegSub1(arg, arg + 1));
assertIntEquals(1, $noinline$NegSub2(arg, arg + 1));
- assertLongEquals(arg, $noinline$NotNot1(arg));
- assertLongEquals(arg, $noinline$runSmaliTestLong("$noinline$NotNot1", arg));
- assertIntEquals(-1, $noinline$NotNot2(arg));
- assertIntEquals(-1, $noinline$runSmaliTestInt("$noinline$NotNot2", arg));
+ assertLongEquals(arg, (long)$noinline$NotNot1.invoke(null, arg));
+ assertLongEquals(arg, $noinline$runSmaliTest2Long("$noinline$NotNot1", arg));
+ assertIntEquals(-1, (int)$noinline$NotNot2.invoke(null, arg));
+ assertIntEquals(-1, $noinline$runSmaliTestInt("2", "$noinline$NotNot2", arg));
assertIntEquals(-(arg + arg + 1), $noinline$SubNeg1(arg, arg + 1));
assertIntEquals(-(arg + arg + 1), $noinline$SubNeg2(arg, arg + 1));
assertLongEquals(-(2 * arg + 1), $noinline$SubNeg3(arg, arg + 1));
@@ -2646,10 +2513,10 @@ public class Main {
assertBooleanEquals(true, $noinline$EqualBoolVsIntConst(true));
assertBooleanEquals(false, $noinline$NotEqualBoolVsIntConst(false));
assertBooleanEquals(false, $noinline$NotEqualBoolVsIntConst(false));
- assertBooleanEquals(true, $noinline$NotNotBool(true));
- assertBooleanEquals(true, $noinline$runSmaliTestBoolean("$noinline$NotNotBool", true));
- assertBooleanEquals(false, $noinline$NotNotBool(false));
- assertBooleanEquals(false, $noinline$runSmaliTestBoolean("$noinline$NotNotBool", false));
+ assertBooleanEquals(true, (boolean)$noinline$NotNotBool.invoke(null, true));
+ assertBooleanEquals(true, $noinline$runSmaliTest2Boolean("$noinline$NotNotBool", true));
+ assertBooleanEquals(false, (boolean)$noinline$NotNotBool.invoke(null, false));
+ assertBooleanEquals(false, $noinline$runSmaliTest2Boolean("$noinline$NotNotBool", false));
assertFloatEquals(50.0f, $noinline$Div2(100.0f));
assertDoubleEquals(75.0, $noinline$Div2(150.0));
assertFloatEquals(-400.0f, $noinline$DivMP25(100.0f));
@@ -2836,17 +2703,16 @@ public class Main {
assertIntEquals(0x7f, $noinline$bug68142795Byte((byte) 0x7f));
assertIntEquals((byte) 0x80, $noinline$bug68142795Byte((byte) 0x80));
- assertIntEquals(0x7fff, $noinline$bug68142795Short((short) 0x7fff));
- assertIntEquals((short) 0x8000, $noinline$bug68142795Short((short) 0x8000));
- assertIntEquals(0, $noinline$bug68142795Boolean(false));
- assertIntEquals(1, $noinline$bug68142795Boolean(true));
+ assertIntEquals(0x7fff, (int)$noinline$bug68142795Short.invoke(null, (short) 0x7fff));
+ assertIntEquals((short) 0x8000, (int)$noinline$bug68142795Short.invoke(null, (short) 0x8000));
+ assertIntEquals(0, (int)$noinline$bug68142795Boolean.invoke(null, false));
+ assertIntEquals(1, (int)$noinline$bug68142795Boolean.invoke(null, true));
assertIntEquals(0x7f, $noinline$bug68142795Elaborate((byte) 0x7f));
assertIntEquals((byte) 0x80, $noinline$bug68142795Elaborate((byte) 0x80));
}
private static boolean $inline$true() { return true; }
private static boolean $inline$false() { return false; }
- private static int $inline$get255() { return 255; }
public static boolean booleanField;
diff --git a/test/463-checker-boolean-simplifier/build b/test/463-checker-boolean-simplifier/build
deleted file mode 100755
index 10ffcc537d..0000000000
--- a/test/463-checker-boolean-simplifier/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/463-checker-boolean-simplifier/smali/Main2.smali b/test/463-checker-boolean-simplifier/smali/Main2.smali
new file mode 100644
index 0000000000..5fc553ea36
--- /dev/null
+++ b/test/463-checker-boolean-simplifier/smali/Main2.smali
@@ -0,0 +1,308 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMain2;
+.super Ljava/lang/Object;
+.source "Main2.java"
+
+
+# direct methods
+.method constructor <init>()V
+ .registers 1
+
+ .prologue
+ .line 17
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+ return-void
+.end method
+
+# Elementary test negating a boolean. Verifies that blocks are merged and
+# empty branches removed.
+
+## CHECK-START: boolean Main2.BooleanNot(boolean) select_generator (before)
+## CHECK-DAG: <<Param:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: If [<<Param>>]
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: Return [<<Phi>>]
+
+## CHECK-START: boolean Main2.BooleanNot(boolean) select_generator (before)
+## CHECK: Goto
+## CHECK: Goto
+## CHECK: Goto
+## CHECK-NOT: Goto
+
+## CHECK-START: boolean Main2.BooleanNot(boolean) select_generator (after)
+## CHECK-DAG: <<Param:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<NotParam:i\d+>> Select [<<Const1>>,<<Const0>>,<<Param>>]
+## CHECK-DAG: Return [<<NotParam>>]
+
+## CHECK-START: boolean Main2.BooleanNot(boolean) select_generator (after)
+## CHECK-NOT: If
+## CHECK-NOT: Phi
+
+## CHECK-START: boolean Main2.BooleanNot(boolean) select_generator (after)
+## CHECK: Goto
+## CHECK-NOT: Goto
+
+# The original java source of this method:
+#
+# return !x;
+#
+.method public static BooleanNot(Z)Z
+ .registers 2
+ .param p0, "x" # Z
+
+ .prologue
+ .line 70
+ if-nez p0, :cond_4
+
+ const/4 v0, 0x1
+
+ :goto_3
+ return v0
+
+ :cond_4
+ const/4 v0, 0x0
+
+ goto :goto_3
+.end method
+
+# Program which further uses negated conditions.
+# Note that Phis are discovered retrospectively.
+
+## CHECK-START: boolean Main2.ValuesOrdered(int, int, int) select_generator (before)
+## CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+## CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+## CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<CondXY:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
+## CHECK-DAG: If [<<CondXY>>]
+## CHECK-DAG: <<CondYZ:z\d+>> GreaterThan [<<ParamY>>,<<ParamZ>>]
+## CHECK-DAG: If [<<CondYZ>>]
+## CHECK-DAG: <<CondXYZ:z\d+>> NotEqual [<<PhiXY:i\d+>>,<<PhiYZ:i\d+>>]
+## CHECK-DAG: If [<<CondXYZ>>]
+## CHECK-DAG: Return [<<PhiXYZ:i\d+>>]
+## CHECK-DAG: <<PhiXY>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: <<PhiYZ>> Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG: <<PhiXYZ>> Phi [<<Const1>>,<<Const0>>]
+
+## CHECK-START: boolean Main2.ValuesOrdered(int, int, int) select_generator (after)
+## CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+## CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+## CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<CmpXY:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
+## CHECK-DAG: <<SelXY:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXY>>]
+## CHECK-DAG: <<CmpYZ:z\d+>> GreaterThan [<<ParamY>>,<<ParamZ>>]
+## CHECK-DAG: <<SelYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpYZ>>]
+## CHECK-DAG: <<CmpXYZ:z\d+>> NotEqual [<<SelXY>>,<<SelYZ>>]
+## CHECK-DAG: <<SelXYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXYZ>>]
+## CHECK-DAG: Return [<<SelXYZ>>]
+
+# The original java source of this method:
+#
+# return (x <= y) == (y <= z);
+#
+.method public static ValuesOrdered(III)Z
+ .registers 7
+ .param p0, "x" # I
+ .param p1, "y" # I
+ .param p2, "z" # I
+
+ .prologue
+ const/4 v0, 0x1
+
+ const/4 v1, 0x0
+
+ .line 166
+ if-gt p0, p1, :cond_b
+
+ move v3, v0
+
+ :goto_5
+ if-gt p1, p2, :cond_d
+
+ move v2, v0
+
+ :goto_8
+ if-ne v3, v2, :cond_f
+
+ :goto_a
+ return v0
+
+ :cond_b
+ move v3, v1
+
+ goto :goto_5
+
+ :cond_d
+ move v2, v1
+
+ goto :goto_8
+
+ :cond_f
+ move v0, v1
+
+ goto :goto_a
+.end method
+
+## CHECK-START: int Main2.NegatedCondition(boolean) select_generator (before)
+## CHECK-DAG: <<Param:z\d+>> ParameterValue
+## CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+## CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+## CHECK-DAG: If [<<Param>>]
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const42>>,<<Const43>>]
+## CHECK-DAG: Return [<<Phi>>]
+
+## CHECK-START: int Main2.NegatedCondition(boolean) select_generator (after)
+## CHECK-DAG: <<Param:z\d+>> ParameterValue
+## CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+## CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+## CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Const42>>,<<Param>>]
+## CHECK-DAG: Return [<<Select>>]
+
+## CHECK-START: int Main2.NegatedCondition(boolean) select_generator (after)
+## CHECK-NOT: BooleanNot
+
+# The original java source of this method:
+#
+# if (x != false) {
+# return 42;
+# } else {
+# return 43;
+# }
+#
+.method public static NegatedCondition(Z)I
+ .registers 2
+ .param p0, "x" # Z
+
+ .prologue
+ .line 188
+ if-eqz p0, :cond_5
+
+ .line 189
+ const/16 v0, 0x2a
+
+ .line 191
+ :goto_4
+ return v0
+
+ :cond_5
+ const/16 v0, 0x2b
+
+ goto :goto_4
+.end method
+
+## CHECK-START: int Main2.MultiplePhis() select_generator (before)
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+## CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+## CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Const13>>,<<Const42>>]
+## CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>,<<Add>>]
+## CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
+## CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
+## CHECK-DAG: If [<<Cond>>]
+## CHECK-DAG: Return [<<PhiX>>]
+
+## CHECK-START: int Main2.MultiplePhis() select_generator (after)
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+## CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+## CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Select:i\d+>>]
+## CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>]
+## CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
+## CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
+## CHECK-DAG: <<Select>> Select [<<Const13>>,<<Const42>>,<<Cond>>]
+## CHECK-DAG: Return [<<PhiX>>]
+
+# The original java source of this method:
+#
+# int x = 0;
+# int y = 1;
+# while (y++ < 10) {
+# if (y > 1) {
+# x = 13;
+# } else {
+# x = 42;
+# }
+# }
+# return x;
+#
+.method public static MultiplePhis()I
+ .registers 4
+
+ .prologue
+ .line 290
+ const/4 v0, 0x0
+
+ .line 291
+ .local v0, "x":I
+ const/4 v1, 0x1
+
+ .local v1, "y":I
+ move v2, v1
+
+ .line 292
+ .end local v1 # "y":I
+ .local v2, "y":I
+ :goto_3
+ add-int/lit8 v1, v2, 0x1
+
+ .end local v2 # "y":I
+ .restart local v1 # "y":I
+ const/16 v3, 0xa
+
+ if-ge v2, v3, :cond_14
+
+ .line 293
+ const/4 v3, 0x1
+
+ if-le v1, v3, :cond_10
+
+ .line 294
+ const/16 v0, 0xd
+
+ move v2, v1
+
+ .end local v1 # "y":I
+ .restart local v2 # "y":I
+ goto :goto_3
+
+ .line 296
+ .end local v2 # "y":I
+ .restart local v1 # "y":I
+ :cond_10
+ const/16 v0, 0x2a
+
+ move v2, v1
+
+ .end local v1 # "y":I
+ .restart local v2 # "y":I
+ goto :goto_3
+
+ .line 299
+ .end local v2 # "y":I
+ .restart local v1 # "y":I
+ :cond_14
+ return v0
+.end method
diff --git a/test/463-checker-boolean-simplifier/src-art/Main.java b/test/463-checker-boolean-simplifier/src-art/Main.java
new file mode 100644
index 0000000000..2c759ed6f9
--- /dev/null
+++ b/test/463-checker-boolean-simplifier/src-art/Main.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+
+ // Note #1: `javac` flips the conditions of If statements.
+ // Note #2: In the optimizing compiler, the first input of Phi is always
+ // the fall-through path, i.e. the false branch.
+
+ public static void assertBoolEquals(boolean expected, boolean result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void assertIntEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ /*
+ * Program which only delegates the condition, i.e. returns 1 when True
+ * and 0 when False.
+ */
+
+ /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (before)
+ /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,<<Const1>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+
+ /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const0>>,<<Const1>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ public static boolean GreaterThan(int x, int y) {
+ return (x <= y) ? false : true;
+ }
+
+ /*
+ * Program which negates a condition, i.e. returns 0 when True
+ * and 1 when False.
+ */
+
+ /// CHECK-START: boolean Main.LessThan(int, int) select_generator (before)
+ /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+
+ /// CHECK-START: boolean Main.LessThan(int, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ public static boolean LessThan(int x, int y) {
+ return (x < y) ? true : false;
+ }
+
+ /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const42>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Add>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleTrueBlock(boolean x, int y) {
+ return x ? y + 42 : 43;
+ }
+
+ /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const43>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Add>>,<<Const42>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleFalseBlock(boolean x, int y) {
+ return x ? 42 : y + 43;
+ }
+
+ /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<AddTrue:i\d+>> Add [<<ParamY>>,<<Const42>>]
+ /// CHECK-DAG: <<AddFalse:i\d+>> Add [<<ParamZ>>,<<Const43>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<AddFalse>>,<<AddTrue>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleBothBlocks(boolean x, int y, int z) {
+ return x ? y + 42 : z + 43;
+ }
+
+ /// CHECK-START: int Main.ThreeBlocks(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Select23:i\d+>> Select [<<Const3>>,<<Const2>>,<<ParamY>>]
+ /// CHECK-DAG: <<Select123:i\d+>> Select [<<Select23>>,<<Const1>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select123>>]
+
+ public static int ThreeBlocks(boolean x, boolean y) {
+ if (x) {
+ return 1;
+ } else if (y) {
+ return 2;
+ } else {
+ return 3;
+ }
+ }
+
+ /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const2>>]
+ /// CHECK-DAG: Phi [<<Add>>,<<Const43>>]
+
+ /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int TrueBlockWithTooManyInstructions(boolean x) {
+ return x ? (read_field + 2) : 43;
+ }
+
+ /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const3>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Add>>]
+
+ /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int FalseBlockWithTooManyInstructions(boolean x) {
+ return x ? 42 : (read_field + 3);
+ }
+
+ /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const42>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
+
+ /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int TrueBlockWithSideEffects(boolean x) {
+ return x ? (write_field = 42) : 43;
+ }
+
+ /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const43>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
+
+ /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int FalseBlockWithSideEffects(boolean x) {
+ return x ? 42 : (write_field = 43);
+ }
+
+ public static void main(String[] args) throws Exception {
+ Class main2 = Class.forName("Main2");
+ Method booleanNot = main2.getMethod("BooleanNot", boolean.class);
+ Method valuesOrdered = main2.getMethod("ValuesOrdered", int.class, int.class, int.class);
+ Method negatedCondition = main2.getMethod("NegatedCondition", boolean.class);
+ Method multiplePhis = main2.getMethod("MultiplePhis");
+
+ assertBoolEquals(false, (boolean)booleanNot.invoke(null, true));
+ assertBoolEquals(true, (boolean)booleanNot.invoke(null, false));
+ assertBoolEquals(true, GreaterThan(10, 5));
+ assertBoolEquals(false, GreaterThan(10, 10));
+ assertBoolEquals(false, GreaterThan(5, 10));
+ assertBoolEquals(true, LessThan(5, 10));
+ assertBoolEquals(false, LessThan(10, 10));
+ assertBoolEquals(false, LessThan(10, 5));
+
+ assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 1, 3, 5));
+ assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 5, 3, 1));
+ assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 1, 3, 2));
+ assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 2, 3, 1));
+ assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 3, 3, 3));
+ assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 3, 3, 5));
+ assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 5, 5, 3));
+ assertIntEquals(42, (int)negatedCondition.invoke(null, true));
+ assertIntEquals(43, (int)negatedCondition.invoke(null, false));
+ assertIntEquals(46, SimpleTrueBlock(true, 4));
+ assertIntEquals(43, SimpleTrueBlock(false, 4));
+ assertIntEquals(42, SimpleFalseBlock(true, 7));
+ assertIntEquals(50, SimpleFalseBlock(false, 7));
+ assertIntEquals(48, SimpleBothBlocks(true, 6, 2));
+ assertIntEquals(45, SimpleBothBlocks(false, 6, 2));
+ assertIntEquals(1, ThreeBlocks(true, true));
+ assertIntEquals(1, ThreeBlocks(true, false));
+ assertIntEquals(2, ThreeBlocks(false, true));
+ assertIntEquals(3, ThreeBlocks(false, false));
+ assertIntEquals(13, (int)multiplePhis.invoke(null));
+
+ Main m = new Main();
+ assertIntEquals(42, m.TrueBlockWithTooManyInstructions(true));
+ assertIntEquals(43, m.TrueBlockWithTooManyInstructions(false));
+ assertIntEquals(42, m.FalseBlockWithTooManyInstructions(true));
+ assertIntEquals(43, m.FalseBlockWithTooManyInstructions(false));
+ assertIntEquals(42, m.TrueBlockWithSideEffects(true));
+ assertIntEquals(43, m.TrueBlockWithSideEffects(false));
+ assertIntEquals(42, m.FalseBlockWithSideEffects(true));
+ assertIntEquals(43, m.FalseBlockWithSideEffects(false));
+ }
+
+ // These need to be instance fields so as to not generate a LoadClass for iget/iput.
+ public int read_field = 40;
+ public int write_field = 42;
+}
diff --git a/test/463-checker-boolean-simplifier/src/Main.java b/test/463-checker-boolean-simplifier/src/Main.java
index d1d02cdfee..26d33467da 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,398 +15,8 @@
*/
public class Main {
-
- // Note #1: `javac` flips the conditions of If statements.
- // Note #2: In the optimizing compiler, the first input of Phi is always
- // the fall-through path, i.e. the false branch.
-
- public static void assertBoolEquals(boolean expected, boolean result) {
- if (expected != result) {
- throw new Error("Expected: " + expected + ", found: " + result);
- }
- }
-
- public static void assertIntEquals(int expected, int result) {
- if (expected != result) {
- throw new Error("Expected: " + expected + ", found: " + result);
- }
- }
-
- /*
- * Elementary test negating a boolean. Verifies that blocks are merged and
- * empty branches removed.
- */
-
- /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (before)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: If [<<Param>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (before)
- /// CHECK: Goto
- /// CHECK: Goto
- /// CHECK: Goto
- /// CHECK-NOT: Goto
-
- /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<NotParam:i\d+>> Select [<<Const1>>,<<Const0>>,<<Param>>]
- /// CHECK-DAG: Return [<<NotParam>>]
-
- /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
- /// CHECK-NOT: If
- /// CHECK-NOT: Phi
-
- /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
- /// CHECK: Goto
- /// CHECK-NOT: Goto
-
- public static boolean BooleanNot(boolean x) {
- return !x;
- }
-
- /*
- * Program which only delegates the condition, i.e. returns 1 when True
- * and 0 when False.
- */
-
- /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (before)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,<<Const1>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const0>>,<<Const1>>,<<Cond>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static boolean GreaterThan(int x, int y) {
- return (x <= y) ? false : true;
- }
-
- /*
- * Program which negates a condition, i.e. returns 0 when True
- * and 1 when False.
- */
-
- /// CHECK-START: boolean Main.LessThan(int, int) select_generator (before)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: boolean Main.LessThan(int, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static boolean LessThan(int x, int y) {
- return (x < y) ? true : false;
- }
-
- /*
- * Program which further uses negated conditions.
- * Note that Phis are discovered retrospectively.
- */
-
- /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) select_generator (before)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<CondXY:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: If [<<CondXY>>]
- /// CHECK-DAG: <<CondYZ:z\d+>> GreaterThan [<<ParamY>>,<<ParamZ>>]
- /// CHECK-DAG: If [<<CondYZ>>]
- /// CHECK-DAG: <<CondXYZ:z\d+>> NotEqual [<<PhiXY:i\d+>>,<<PhiYZ:i\d+>>]
- /// CHECK-DAG: If [<<CondXYZ>>]
- /// CHECK-DAG: Return [<<PhiXYZ:i\d+>>]
- /// CHECK-DAG: <<PhiXY>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: <<PhiYZ>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-DAG: <<PhiXYZ>> Phi [<<Const1>>,<<Const0>>]
-
- /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<CmpXY:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: <<SelXY:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXY>>]
- /// CHECK-DAG: <<CmpYZ:z\d+>> GreaterThan [<<ParamY>>,<<ParamZ>>]
- /// CHECK-DAG: <<SelYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpYZ>>]
- /// CHECK-DAG: <<CmpXYZ:z\d+>> NotEqual [<<SelXY>>,<<SelYZ>>]
- /// CHECK-DAG: <<SelXYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXYZ>>]
- /// CHECK-DAG: Return [<<SelXYZ>>]
-
- public static boolean ValuesOrdered(int x, int y, int z) {
- return (x <= y) == (y <= z);
- }
-
- /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (before)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: If [<<Param>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const42>>,<<Const43>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (after)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Const42>>,<<Param>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (after)
- /// CHECK-NOT: BooleanNot
-
- public static int NegatedCondition(boolean x) {
- if (x != false) {
- return 42;
- } else {
- return 43;
+ public static void main(String[] args) {
+ // This file is just for running on the RI as the test is ART specific. As successful
+ // execution for this test produces no output, there's nothing to do here.
}
- }
-
- /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const42>>]
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Add>>,<<ParamX>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
- /// CHECK-NOT: If
-
- public static int SimpleTrueBlock(boolean x, int y) {
- return x ? y + 42 : 43;
- }
-
- /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const43>>]
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Add>>,<<Const42>>,<<ParamX>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
- /// CHECK-NOT: If
-
- public static int SimpleFalseBlock(boolean x, int y) {
- return x ? 42 : y + 43;
- }
-
- /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
- /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
- /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: <<AddTrue:i\d+>> Add [<<ParamY>>,<<Const42>>]
- /// CHECK-DAG: <<AddFalse:i\d+>> Add [<<ParamZ>>,<<Const43>>]
- /// CHECK-DAG: <<Select:i\d+>> Select [<<AddFalse>>,<<AddTrue>>,<<ParamX>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
- /// CHECK-NOT: If
-
- public static int SimpleBothBlocks(boolean x, int y, int z) {
- return x ? y + 42 : z + 43;
- }
-
- /// CHECK-START: int Main.ThreeBlocks(boolean, boolean) select_generator (after)
- /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
- /// CHECK-DAG: <<ParamY:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Select23:i\d+>> Select [<<Const3>>,<<Const2>>,<<ParamY>>]
- /// CHECK-DAG: <<Select123:i\d+>> Select [<<Select23>>,<<Const1>>,<<ParamX>>]
- /// CHECK-DAG: Return [<<Select123>>]
-
- public static int ThreeBlocks(boolean x, boolean y) {
- if (x) {
- return 1;
- } else if (y) {
- return 2;
- } else {
- return 3;
- }
- }
-
- /// CHECK-START: int Main.MultiplePhis() select_generator (before)
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Const13>>,<<Const42>>]
- /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>,<<Add>>]
- /// CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
- /// CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: Return [<<PhiX>>]
-
- /// CHECK-START: int Main.MultiplePhis() select_generator (after)
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Select:i\d+>>]
- /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>]
- /// CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
- /// CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
- /// CHECK-DAG: <<Select>> Select [<<Const13>>,<<Const42>>,<<Cond>>]
- /// CHECK-DAG: Return [<<PhiX>>]
-
- public static int MultiplePhis() {
- int x = 0;
- int y = 1;
- while (y++ < 10) {
- if (y > 1) {
- x = 13;
- } else {
- x = 42;
- }
- }
- return x;
- }
-
- /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (before)
- /// CHECK-DAG: <<This:l\d+>> ParameterValue
- /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
- /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const2>>]
- /// CHECK-DAG: Phi [<<Add>>,<<Const43>>]
-
- /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (after)
- /// CHECK-NOT: Select
-
- public int TrueBlockWithTooManyInstructions(boolean x) {
- return x ? (read_field + 2) : 43;
- }
-
- /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (before)
- /// CHECK-DAG: <<This:l\d+>> ParameterValue
- /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
- /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const3>>]
- /// CHECK-DAG: Phi [<<Const42>>,<<Add>>]
-
- /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (after)
- /// CHECK-NOT: Select
-
- public int FalseBlockWithTooManyInstructions(boolean x) {
- return x ? 42 : (read_field + 3);
- }
-
- /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (before)
- /// CHECK-DAG: <<This:l\d+>> ParameterValue
- /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const42>>]
- /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
-
- /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (after)
- /// CHECK-NOT: Select
-
- public int TrueBlockWithSideEffects(boolean x) {
- return x ? (write_field = 42) : 43;
- }
-
- /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (before)
- /// CHECK-DAG: <<This:l\d+>> ParameterValue
- /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: If [<<Cond>>]
- /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const43>>]
- /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
-
- /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (after)
- /// CHECK-NOT: Select
-
- public int FalseBlockWithSideEffects(boolean x) {
- return x ? 42 : (write_field = 43);
- }
-
- public static void main(String[] args) throws Exception {
- assertBoolEquals(false, BooleanNot(true));
- assertBoolEquals(true, BooleanNot(false));
- assertBoolEquals(true, GreaterThan(10, 5));
- assertBoolEquals(false, GreaterThan(10, 10));
- assertBoolEquals(false, GreaterThan(5, 10));
- assertBoolEquals(true, LessThan(5, 10));
- assertBoolEquals(false, LessThan(10, 10));
- assertBoolEquals(false, LessThan(10, 5));
- assertBoolEquals(true, ValuesOrdered(1, 3, 5));
- assertBoolEquals(true, ValuesOrdered(5, 3, 1));
- assertBoolEquals(false, ValuesOrdered(1, 3, 2));
- assertBoolEquals(false, ValuesOrdered(2, 3, 1));
- assertBoolEquals(true, ValuesOrdered(3, 3, 3));
- assertBoolEquals(true, ValuesOrdered(3, 3, 5));
- assertBoolEquals(false, ValuesOrdered(5, 5, 3));
- assertIntEquals(42, NegatedCondition(true));
- assertIntEquals(43, NegatedCondition(false));
- assertIntEquals(46, SimpleTrueBlock(true, 4));
- assertIntEquals(43, SimpleTrueBlock(false, 4));
- assertIntEquals(42, SimpleFalseBlock(true, 7));
- assertIntEquals(50, SimpleFalseBlock(false, 7));
- assertIntEquals(48, SimpleBothBlocks(true, 6, 2));
- assertIntEquals(45, SimpleBothBlocks(false, 6, 2));
- assertIntEquals(1, ThreeBlocks(true, true));
- assertIntEquals(1, ThreeBlocks(true, false));
- assertIntEquals(2, ThreeBlocks(false, true));
- assertIntEquals(3, ThreeBlocks(false, false));
- assertIntEquals(13, MultiplePhis());
-
- Main m = new Main();
- assertIntEquals(42, m.TrueBlockWithTooManyInstructions(true));
- assertIntEquals(43, m.TrueBlockWithTooManyInstructions(false));
- assertIntEquals(42, m.FalseBlockWithTooManyInstructions(true));
- assertIntEquals(43, m.FalseBlockWithTooManyInstructions(false));
- assertIntEquals(42, m.TrueBlockWithSideEffects(true));
- assertIntEquals(43, m.TrueBlockWithSideEffects(false));
- assertIntEquals(42, m.FalseBlockWithSideEffects(true));
- assertIntEquals(43, m.FalseBlockWithSideEffects(false));
- }
-
- // These need to be instance fields so as to not generate a LoadClass for iget/iput.
- public int read_field = 40;
- public int write_field = 42;
}
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index c113042c9c..c6fd56f20d 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -52,11 +52,11 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_cloneResolvedMethods(JNIEnv* env,
uint32_t index = pair.index;
ArtMethod* method = pair.object;
if (sizeof(void*) == 4) {
- ObjPtr<mirror::IntArray> int_array = down_cast<mirror::IntArray*>(decoded_array.Ptr());
+ ObjPtr<mirror::IntArray> int_array = ObjPtr<mirror::IntArray>::DownCast(decoded_array);
int_array->Set(2u * i, index);
int_array->Set(2u * i + 1u, static_cast<jint>(reinterpret_cast<uintptr_t>(method)));
} else {
- ObjPtr<mirror::LongArray> long_array = down_cast<mirror::LongArray*>(decoded_array.Ptr());
+ ObjPtr<mirror::LongArray> long_array = ObjPtr<mirror::LongArray>::DownCast(decoded_array);
long_array->Set(2u * i, index);
long_array->Set(2u * i + 1u, reinterpret_cast64<jlong>(method));
}
diff --git a/test/530-checker-lse/build b/test/530-checker-lse/build
deleted file mode 100755
index 10ffcc537d..0000000000
--- a/test/530-checker-lse/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/530-checker-lse/smali/Main.smali b/test/530-checker-lse/smali/Main.smali
new file mode 100644
index 0000000000..267801760f
--- /dev/null
+++ b/test/530-checker-lse/smali/Main.smali
@@ -0,0 +1,260 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMain2;
+.super Ljava/lang/Object;
+.source "Main.java"
+
+# direct methods
+
+## CHECK-START: int Main2.test4(TestClass, boolean) load_store_elimination (before)
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: Return
+## CHECK: InstanceFieldSet
+
+## CHECK-START: int Main2.test4(TestClass, boolean) load_store_elimination (after)
+## CHECK: InstanceFieldSet
+## CHECK-NOT: NullCheck
+## CHECK-NOT: InstanceFieldGet
+## CHECK: Return
+## CHECK: InstanceFieldSet
+
+# Set and merge the same value in two branches.
+
+# Original java source:
+#
+# static int test4(TestClass obj, boolean b) {
+# if (b) {
+# obj.i = 1;
+# } else {
+# obj.i = 1;
+# }
+# return obj.i;
+# }
+
+.method public static test4(LTestClass;Z)I
+ .registers 3
+ .param p0, "obj" # LTestClass;
+ .param p1, "b" # Z
+
+ .prologue
+ const/4 v0, 0x1
+
+ .line 185
+ if-eqz p1, :cond_8
+
+ .line 186
+ iput v0, p0, LTestClass;->i:I
+
+ .line 190
+ :goto_5
+ iget v0, p0, LTestClass;->i:I
+
+ return v0
+
+ .line 188
+ :cond_8
+ iput v0, p0, LTestClass;->i:I
+
+ goto :goto_5
+.end method
+
+## CHECK-START: int Main2.test5(TestClass, boolean) load_store_elimination (before)
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: Return
+## CHECK: InstanceFieldSet
+
+## CHECK-START: int Main2.test5(TestClass, boolean) load_store_elimination (after)
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: Return
+## CHECK: InstanceFieldSet
+
+# Set and merge different values in two branches.
+# Original java source:
+#
+# static int test5(TestClass obj, boolean b) {
+# if (b) {
+# obj.i = 1;
+# } else {
+# obj.i = 2;
+# }
+# return obj.i;
+# }
+
+.method public static test5(LTestClass;Z)I
+ .registers 3
+ .param p0, "obj" # LTestClass;
+ .param p1, "b" # Z
+
+ .prologue
+ .line 207
+ if-eqz p1, :cond_8
+
+ .line 208
+ const/4 v0, 0x1
+
+ iput v0, p0, LTestClass;->i:I
+
+ .line 212
+ :goto_5
+ iget v0, p0, LTestClass;->i:I
+
+ return v0
+
+ .line 210
+ :cond_8
+ const/4 v0, 0x2
+
+ iput v0, p0, LTestClass;->i:I
+
+ goto :goto_5
+.end method
+
+## CHECK-START: int Main2.test23(boolean) load_store_elimination (before)
+## CHECK: NewInstance
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: Return
+## CHECK: InstanceFieldGet
+## CHECK: InstanceFieldSet
+
+## CHECK-START: int Main2.test23(boolean) load_store_elimination (after)
+## CHECK: NewInstance
+## CHECK-NOT: InstanceFieldSet
+## CHECK-NOT: InstanceFieldGet
+## CHECK: InstanceFieldSet
+## CHECK: InstanceFieldGet
+## CHECK: Return
+## CHECK-NOT: InstanceFieldGet
+## CHECK: InstanceFieldSet
+
+# Test store elimination on merging.
+
+# Original java source:
+#
+# static int test23(boolean b) {
+# TestClass obj = new TestClass();
+# obj.i = 3; // This store can be eliminated since the value flows into each branch.
+# if (b) {
+# obj.i += 1; // This store cannot be eliminated due to the merge later.
+# } else {
+# obj.i += 2; // This store cannot be eliminated due to the merge later.
+# }
+# return obj.i;
+# }
+
+.method public static test23(Z)I
+ .registers 3
+ .param p0, "b" # Z
+
+ .prologue
+ .line 582
+ new-instance v0, LTestClass;
+
+ invoke-direct {v0}, LTestClass;-><init>()V
+
+ .line 583
+ .local v0, "obj":LTestClass;
+ const/4 v1, 0x3
+
+ iput v1, v0, LTestClass;->i:I
+
+ .line 584
+ if-eqz p0, :cond_13
+
+ .line 585
+ iget v1, v0, LTestClass;->i:I
+
+ add-int/lit8 v1, v1, 0x1
+
+ iput v1, v0, LTestClass;->i:I
+
+ .line 589
+ :goto_10
+ iget v1, v0, LTestClass;->i:I
+
+ return v1
+
+ .line 587
+ :cond_13
+ iget v1, v0, LTestClass;->i:I
+
+ add-int/lit8 v1, v1, 0x2
+
+ iput v1, v0, LTestClass;->i:I
+
+ goto :goto_10
+.end method
+
+## CHECK-START: float Main2.test24() load_store_elimination (before)
+## CHECK-DAG: <<True:i\d+>> IntConstant 1
+## CHECK-DAG: <<Float8:f\d+>> FloatConstant 8
+## CHECK-DAG: <<Float42:f\d+>> FloatConstant 42
+## CHECK-DAG: <<Obj:l\d+>> NewInstance
+## CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>]
+## CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>]
+## CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>]
+## CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
+## CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>]
+## CHECK-DAG: Return [<<Select>>]
+
+## CHECK-START: float Main2.test24() load_store_elimination (after)
+## CHECK-DAG: <<True:i\d+>> IntConstant 1
+## CHECK-DAG: <<Float8:f\d+>> FloatConstant 8
+## CHECK-DAG: <<Float42:f\d+>> FloatConstant 42
+## CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>]
+## CHECK-DAG: Return [<<Select>>]
+
+# Original java source:
+#
+# static float test24() {
+# float a = 42.0f;
+# TestClass3 obj = new TestClass3();
+# if (obj.test1) {
+# a = obj.floatField;
+# }
+# return a;
+# }
+
+.method public static test24()F
+ .registers 3
+
+ .prologue
+ .line 612
+ const/high16 v0, 0x42280000 # 42.0f
+
+ .line 613
+ .local v0, "a":F
+ new-instance v1, LTestClass3;
+
+ invoke-direct {v1}, LTestClass3;-><init>()V
+
+ .line 614
+ .local v1, "obj":LTestClass3;
+ iget-boolean v2, v1, LTestClass3;->test1:Z
+
+ if-eqz v2, :cond_d
+
+ .line 615
+ iget v0, v1, LTestClass3;->floatField:F
+
+ .line 617
+ :cond_d
+ return v0
+.end method
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 93c153821b..bd1744cc5f 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import java.lang.reflect.Method;
+
class Circle {
Circle(double radius) {
this.radius = radius;
@@ -167,51 +169,6 @@ public class Main {
return obj.i + obj1.j + obj2.i + obj2.j;
}
- /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: Return
- /// CHECK: InstanceFieldSet
-
- /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet
- /// CHECK-NOT: NullCheck
- /// CHECK-NOT: InstanceFieldGet
- /// CHECK: Return
- /// CHECK: InstanceFieldSet
-
- // Set and merge the same value in two branches.
- static int test4(TestClass obj, boolean b) {
- if (b) {
- obj.i = 1;
- } else {
- obj.i = 1;
- }
- return obj.i;
- }
-
- /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: Return
- /// CHECK: InstanceFieldSet
-
- /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: Return
- /// CHECK: InstanceFieldSet
-
- // Set and merge different values in two branches.
- static int test5(TestClass obj, boolean b) {
- if (b) {
- obj.i = 1;
- } else {
- obj.i = 2;
- }
- return obj.i;
- }
-
/// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
@@ -557,66 +514,6 @@ public class Main {
return sum;
}
- /// CHECK-START: int Main.test23(boolean) load_store_elimination (before)
- /// CHECK: NewInstance
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: Return
- /// CHECK: InstanceFieldGet
- /// CHECK: InstanceFieldSet
-
- /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
- /// CHECK: NewInstance
- /// CHECK-NOT: InstanceFieldSet
- /// CHECK-NOT: InstanceFieldGet
- /// CHECK: InstanceFieldSet
- /// CHECK: InstanceFieldGet
- /// CHECK: Return
- /// CHECK-NOT: InstanceFieldGet
- /// CHECK: InstanceFieldSet
-
- // Test store elimination on merging.
- static int test23(boolean b) {
- TestClass obj = new TestClass();
- obj.i = 3; // This store can be eliminated since the value flows into each branch.
- if (b) {
- obj.i += 1; // This store cannot be eliminated due to the merge later.
- } else {
- obj.i += 2; // This store cannot be eliminated due to the merge later.
- }
- return obj.i;
- }
-
- /// CHECK-START: float Main.test24() load_store_elimination (before)
- /// CHECK-DAG: <<True:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8
- /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42
- /// CHECK-DAG: <<Obj:l\d+>> NewInstance
- /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>]
- /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>]
- /// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>]
- /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
- /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- /// CHECK-START: float Main.test24() load_store_elimination (after)
- /// CHECK-DAG: <<True:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8
- /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42
- /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- static float test24() {
- float a = 42.0f;
- TestClass3 obj = new TestClass3();
- if (obj.test1) {
- a = obj.floatField;
- }
- return a;
- }
-
/// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
/// CHECK: NewInstance
/// CHECK: InstanceFieldSet
@@ -1275,7 +1172,14 @@ public class Main {
}
}
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
+
+ Class main2 = Class.forName("Main2");
+ Method test4 = main2.getMethod("test4", TestClass.class, boolean.class);
+ Method test5 = main2.getMethod("test5", TestClass.class, boolean.class);
+ Method test23 = main2.getMethod("test23", boolean.class);
+ Method test24 = main2.getMethod("test24");
+
assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
assertIntEquals(test1(new TestClass(), new TestClass()), 3);
assertIntEquals(test2(new TestClass()), 1);
@@ -1283,10 +1187,10 @@ public class Main {
TestClass obj2 = new TestClass();
obj1.next = obj2;
assertIntEquals(test3(obj1), 10);
- assertIntEquals(test4(new TestClass(), true), 1);
- assertIntEquals(test4(new TestClass(), false), 1);
- assertIntEquals(test5(new TestClass(), true), 1);
- assertIntEquals(test5(new TestClass(), false), 2);
+ assertIntEquals((int)test4.invoke(null, new TestClass(), true), 1);
+ assertIntEquals((int)test4.invoke(null, new TestClass(), false), 1);
+ assertIntEquals((int)test5.invoke(null, new TestClass(), true), 1);
+ assertIntEquals((int)test5.invoke(null, new TestClass(), false), 2);
assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
assertIntEquals(test7(new TestClass()), 1);
@@ -1312,9 +1216,9 @@ public class Main {
assertFloatEquals(test20().i, 0);
test21(new TestClass());
assertIntEquals(test22(), 13);
- assertIntEquals(test23(true), 4);
- assertIntEquals(test23(false), 5);
- assertFloatEquals(test24(), 8.0f);
+ assertIntEquals((int)test23.invoke(null, true), 4);
+ assertIntEquals((int)test23.invoke(null, false), 5);
+ assertFloatEquals((float)test24.invoke(null), 8.0f);
testFinalizableByForcingGc();
assertIntEquals($noinline$testHSelect(true), 0xdead);
int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
diff --git a/test/530-checker-peel-unroll/src/Main.java b/test/530-checker-peel-unroll/src/Main.java
index 2051b47afe..804c9fe916 100644
--- a/test/530-checker-peel-unroll/src/Main.java
+++ b/test/530-checker-peel-unroll/src/Main.java
@@ -455,6 +455,235 @@ public class Main {
}
}
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (before)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<PhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Get0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddT:i\d+>> Mul [<<PhiT>>,<<Get0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<PhiI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddArr:i\d+>> Add [<<AddS>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: <<STAdd:i\d+>> Add [<<PhiS>>,<<PhiT>>] loop:none
+ /// CHECK-DAG: <<ZCheck:i\d+>> DivZeroCheck [<<STAdd>>] env:[[<<PhiS>>,<<PhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
+ /// CHECK-DAG: <<Div:i\d+>> Div [<<Const1>>,<<ZCheck>>] loop:none
+ /// CHECK-DAG: Return [<<Div>>] loop:none
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<PhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Get0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddT:i\d+>> Mul [<<PhiT>>,<<Get0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<PhiI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddArr:i\d+>> Add [<<AddS>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: GreaterThanOrEqual [<<AddI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddIA:i\d+>> Add [<<AddI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0A:i\d+>> ArrayGet [<<Array>>,<<AddIA>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddSA:i\d+>> Add [<<AddS>>,<<Get0A>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddTA:i\d+>> Mul [<<AddT>>,<<Get0A>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1A:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddArrA:i\d+>> Add [<<AddSA>>,<<Get1A>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<AddI>>,<<AddArrA>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: <<RetPhiS:i\d+>> Phi [<<PhiS>>,<<AddS>>] loop:none
+ /// CHECK-DAG: <<RetPhiT:i\d+>> Phi [<<PhiT>>,<<AddT>>] loop:none
+ /// CHECK-DAG: <<STAdd:i\d+>> Add [<<RetPhiS>>,<<RetPhiT>>] loop:none
+ /// CHECK-DAG: <<ZCheck:i\d+>> DivZeroCheck [<<STAdd>>] env:[[<<RetPhiS>>,<<RetPhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
+ /// CHECK-DAG: <<Div:i\d+>> Div [<<Const1>>,<<ZCheck>>] loop:none
+ /// CHECK-DAG: Return [<<Div>>] loop:none
+ //
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+ private static final int unrollingSimpleLiveOuts(int[] a) {
+ int s = 1;
+ int t = 2;
+ for (int i = 0; i < LENGTH - 2; i++) {
+ int temp = a[i + 1];
+ s += temp;
+ t *= temp;
+ a[i] += s;
+ }
+
+ return 1 / (s + t);
+ }
+
+ /// CHECK-START: int Main.unrollingWhileLiveOuts(int[]) loop_optimization (before)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<Const128>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Rem:i\d+>> Rem [<<AddI>>,<<Const2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Rem>>,<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Phi [<<PhiS>>,<<AddS>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: int Main.unrollingWhileLiveOuts(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<Const128>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Rem:i\d+>> Rem [<<AddI>>,<<Const2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Rem>>,<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<PhiS>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<PhiSM:i\d+>> Phi [<<PhiS>>,<<AddS>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: <<AddIA:i\d+>> Add [<<AddI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<CheckA:z\d+>> GreaterThanOrEqual [<<AddI>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IfA:v\d+>> If [<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<RemA:i\d+>> Rem [<<AddIA>>,<<Const2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<NEA:z\d+>> NotEqual [<<RemA>>,<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: If [<<NEA>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddSA:i\d+>> Add [<<PhiSM>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<PhiSM>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Phi [<<AddSA>>,<<PhiSM>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: <<RetPhi:i\d+>> Phi [<<PhiS>>,<<PhiSM>>] loop:none
+ /// CHECK-DAG: Return [<<RetPhi>>] loop:none
+ //
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+ private static final int unrollingWhileLiveOuts(int[] a) {
+ int i = 0;
+ int s = 128;
+ while (i++ < LENGTH - 2) {
+ if (i % 2 == 0) {
+ a[i] = s++;
+ }
+ }
+ return s;
+ }
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ //
+ /// CHECK-DAG: <<OutPhiJ:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop0:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<OutPhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}] loop:<<Loop0>> outer_loop:none
+ /// CHECK-DAG: <<OutPhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}] loop:<<Loop0>> outer_loop:none
+ //
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<OutPhiS>>,{{i\d+}}] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<PhiT:i\d+>> Phi [<<OutPhiT>>,{{i\d+}}] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Get0>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddT:i\d+>> Mul [<<PhiT>>,<<Get0>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<PhiI>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddArr:i\d+>> Add [<<AddS>>,<<Get1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ //
+ /// CHECK-DAG: Add [<<OutPhiJ>>,<<Const1>>] loop:<<Loop0>> outer_loop:none
+ //
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ //
+ /// CHECK-DAG: <<OutPhiJ:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop0:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<OutPhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}] loop:<<Loop0>> outer_loop:none
+ /// CHECK-DAG: <<OutPhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}] loop:<<Loop0>> outer_loop:none
+ //
+ /// CHECK-DAG: <<PhiI:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<PhiS:i\d+>> Phi [<<OutPhiS>>,{{i\d+}}] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<PhiT:i\d+>> Phi [<<OutPhiT>>,{{i\d+}}] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<PhiI>>,<<Limit>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<PhiI>>,<<Const1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddS:i\d+>> Add [<<PhiS>>,<<Get0>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddT:i\d+>> Mul [<<PhiT>>,<<Get0>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<PhiI>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddArr:i\d+>> Add [<<AddS>>,<<Get1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ //
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddIA:i\d+>> Add [<<AddI>>,<<Const1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get0A:i\d+>> ArrayGet [<<Array>>,<<AddIA>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddSA:i\d+>> Add [<<AddS>>,<<Get0A>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddTA:i\d+>> Mul [<<AddT>>,<<Get0A>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<Get1A:i\d+>> ArrayGet [<<Array>>,<<AddI>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: <<AddArrA:i\d+>> Add [<<AddSA>>,<<Get1A>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ /// CHECK-DAG: ArraySet [<<Array>>,<<AddI>>,<<AddArrA>>] loop:<<Loop1>> outer_loop:<<Loop0>>
+ //
+ /// CHECK-DAG: <<RetPhiS:i\d+>> Phi [<<PhiS>>,<<AddS>>] loop:<<Loop0>> outer_loop:none
+ /// CHECK-DAG: <<RetPhiT:i\d+>> Phi [<<PhiT>>,<<AddT>>] loop:<<Loop0>> outer_loop:none
+ /// CHECK-DAG: Add [<<OutPhiJ>>,<<Const1>>] loop:<<Loop0>> outer_loop:none
+ //
+ /// CHECK-DAG: <<RetAdd:i\d+>> Add [<<OutPhiS>>,<<OutPhiT>>] loop:none
+ /// CHECK-DAG: Return [<<RetAdd>>] loop:none
+ //
+ /// CHECK-NOT: ArrayGet
+ /// CHECK-NOT: ArraySet
+ private static final int unrollingLiveOutsNested(int[] a) {
+ int s = 1;
+ int t = 2;
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < LENGTH - 2; i++) {
+ int temp = a[i + 1];
+ s += temp;
+ t *= temp;
+ a[i] += s;
+ }
+ }
+ return s + t;
+ }
+
/// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
/// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
@@ -802,7 +1031,11 @@ public class Main {
peelingBreakFromNest(a, false);
peelingBreakFromNest(a, true);
- int expected = 141312;
+ unrollingSimpleLiveOuts(a);
+ unrollingWhileLiveOuts(a);
+ unrollingLiveOutsNested(a);
+
+ int expected = 51565978;
int found = 0;
for (int i = 0; i < a.length; i++) {
found += a[i];
diff --git a/test/549-checker-types-merge/build b/test/549-checker-types-merge/build
deleted file mode 100644
index 10ffcc537d..0000000000
--- a/test/549-checker-types-merge/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/567-checker-compare/build b/test/567-checker-compare/build
deleted file mode 100644
index 10ffcc537d..0000000000
--- a/test/567-checker-compare/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/910-methods/build b/test/910-methods/build
deleted file mode 100644
index 10ffcc537d..0000000000
--- a/test/910-methods/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/911-get-stack-trace/check b/test/911-get-stack-trace/check
deleted file mode 100644
index ee00266b36..0000000000
--- a/test/911-get-stack-trace/check
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-if [[ "$DX" == 'd8' ]]; then
- patch -p0 expected.txt < expected_d8.diff
-fi
-
-./default-check "$@"
-if [[ "$?" == "0" ]]; then
- exit 0;
-fi
-
-# We cannot always correctly determine if D8 was used because of (b/68406220).
-# So we are just going to try to see it matches the expect output of D8 no
-# matter what.
-patch -p0 expected.txt < expected_d8.diff
-
-./default-check "$@"
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
index 8177f494ac..b0a400ab75 100644
--- a/test/911-get-stack-trace/expected.txt
+++ b/test/911-get-stack-trace/expected.txt
@@ -9,19 +9,19 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- doTest ()V 34 25
+ doTest ()V 33 25
run ()V 0 25
---------
print (Ljava/lang/Thread;II)V 0 38
@@ -29,19 +29,19 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- doTest ()V 38 26
+ doTest ()V 37 26
run ()V 0 25
---------
getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
@@ -54,12 +54,12 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
From bottom
---------
run ()V 0 25
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
doTest ()V 60 32
@@ -67,7 +67,7 @@ From bottom
---------
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
@@ -76,68 +76,76 @@ From bottom
################################
From top
---------
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
---------
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
From bottom
---------
run ()V 4 28
---------
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 28
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
###########################
@@ -145,20 +153,20 @@ From bottom
###########################
From top
---------
- printOrWait (IILart/ControlData;)V 44 54
+ printOrWait (IILart/ControlData;)V 45 54
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
@@ -166,29 +174,29 @@ From top
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
---------
- printOrWait (IILart/ControlData;)V 44 54
+ printOrWait (IILart/ControlData;)V 45 54
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
---------
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
From bottom
@@ -196,15 +204,15 @@ From bottom
run ()V 4 61
---------
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 61
---------
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
################################
@@ -263,7 +271,9 @@ main
<not printed>
---------
AllTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -271,7 +281,9 @@ AllTraces Thread 0
---------
AllTraces Thread 1
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -279,7 +291,9 @@ AllTraces Thread 1
---------
AllTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -287,7 +301,9 @@ AllTraces Thread 2
---------
AllTraces Thread 3
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -295,7 +311,9 @@ AllTraces Thread 3
---------
AllTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -303,7 +321,9 @@ AllTraces Thread 4
---------
AllTraces Thread 5
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -311,7 +331,9 @@ AllTraces Thread 5
---------
AllTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -319,7 +341,9 @@ AllTraces Thread 6
---------
AllTraces Thread 7
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -327,7 +351,9 @@ AllTraces Thread 7
---------
AllTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -335,7 +361,9 @@ AllTraces Thread 8
---------
AllTraces Thread 9
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -360,7 +388,7 @@ Signal Catcher
Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
- doTest ()V 122 59
+ doTest ()V 120 59
run ()V 24 37
---------
@@ -368,210 +396,230 @@ main
<not printed>
---------
AllTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 1
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 3
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 5
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 7
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
---------
AllTraces Thread 9
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 47
@@ -595,7 +643,7 @@ Signal Catcher
Test911
getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
printAll (I)V 0 75
- doTest ()V 127 61
+ doTest ()V 125 61
run ()V 24 37
---------
@@ -627,12 +675,14 @@ ThreadListTraces Thread 8
Test911
getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 112 54
+ doTest ()V 110 54
run ()V 32 41
---------
ThreadListTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -640,7 +690,9 @@ ThreadListTraces Thread 0
---------
ThreadListTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -648,7 +700,9 @@ ThreadListTraces Thread 2
---------
ThreadListTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -656,7 +710,9 @@ ThreadListTraces Thread 4
---------
ThreadListTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -664,7 +720,9 @@ ThreadListTraces Thread 6
---------
ThreadListTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
@@ -674,110 +732,120 @@ ThreadListTraces Thread 8
Test911
getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 117 56
+ doTest ()V 115 56
run ()V 32 41
---------
ThreadListTraces Thread 0
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 2
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 4
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 6
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
---------
ThreadListTraces Thread 8
- wait ()V -1 -2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
printOrWait (IILart/ControlData;)V 24 47
baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
bar (IIILart/ControlData;)J 0 26
foo (IIILart/ControlData;)I 0 21
run ()V 4 37
@@ -789,7 +857,7 @@ ThreadListTraces Thread 8
4
JVMTI_ERROR_ILLEGAL_ARGUMENT
[public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff]
-[public static void art.Frames.doTestSameThread(), 35]
+[public static void art.Frames.doTestSameThread(), 40]
[public static void art.Frames.doTest() throws java.lang.Exception, 0]
[public void art.Test911$1.run(), 28]
JVMTI_ERROR_NO_MORE_FRAMES
@@ -797,23 +865,25 @@ JVMTI_ERROR_NO_MORE_FRAMES
################################
### Other thread (suspended) ###
################################
-18
+20
JVMTI_ERROR_ILLEGAL_ARGUMENT
-[public final native void java.lang.Object.wait() throws java.lang.InterruptedException, ffffffff]
+[public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, ffffffff]
+[public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, 1]
+[public final void java.lang.Object.wait() throws java.lang.InterruptedException, 2]
[private static void art.Recurse.printOrWait(int,int,art.ControlData), 18]
[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
[public void art.Frames$1.run(), 4]
@@ -824,20 +894,20 @@ JVMTI_ERROR_NO_MORE_FRAMES
###########################
17
JVMTI_ERROR_ILLEGAL_ARGUMENT
-[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c]
+[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
[public void art.Frames$2.run(), 4]
diff --git a/test/911-get-stack-trace/expected_d8.diff b/test/911-get-stack-trace/expected_d8.diff
deleted file mode 100644
index c12015a832..0000000000
--- a/test/911-get-stack-trace/expected_d8.diff
+++ /dev/null
@@ -1,456 +0,0 @@
-12c12
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-15c15
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-18c18
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-21c21
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-24c24
-< doTest ()V 34 25
----
-> doTest ()V 33 25
-32c32
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-35c35
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-38c38
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-41c41
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-44c44
-< doTest ()V 38 26
----
-> doTest ()V 37 26
-57c57
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-62c62
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-70c70
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-84c84
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-87c87
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-90c90
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-93c93
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-102c102
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-105c105
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-108c108
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-111c111
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-125c125
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-132c132
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-137c137
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-140c140
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-148c148
-< printOrWait (IILart/ControlData;)V 44 54
----
-> printOrWait (IILart/ControlData;)V 45 54
-152c152
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-155c155
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-158c158
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-161c161
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-169c169
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-172c172
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-175c175
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-178c178
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-183c183
-< printOrWait (IILart/ControlData;)V 44 54
----
-> printOrWait (IILart/ControlData;)V 45 54
-187c187
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-191c191
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-199c199
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-204c204
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-207c207
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-363c363
-< doTest ()V 122 59
----
-> doTest ()V 120 59
-376c376
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-379c379
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-382c382
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-385c385
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-397c397
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-400c400
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-403c403
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-406c406
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-418c418
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-421c421
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-424c424
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-427c427
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-439c439
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-442c442
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-445c445
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-448c448
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-460c460
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-463c463
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-466c466
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-469c469
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-481c481
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-484c484
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-487c487
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-490c490
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-502c502
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-505c505
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-508c508
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-511c511
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-523c523
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-526c526
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-529c529
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-532c532
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-544c544
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-547c547
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-550c550
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-553c553
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-565c565
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-568c568
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-571c571
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-574c574
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-598c598
-< doTest ()V 127 61
----
-> doTest ()V 125 61
-630c630
-< doTest ()V 112 54
----
-> doTest ()V 110 54
-677c677
-< doTest ()V 117 56
----
-> doTest ()V 115 56
-687c687
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-690c690
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-693c693
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-696c696
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-708c708
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-711c711
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-714c714
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-717c717
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-729c729
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-732c732
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-735c735
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-738c738
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-750c750
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-753c753
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-756c756
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-759c759
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-771c771
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-774c774
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-777c777
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-780c780
-< baz (IIILart/ControlData;)Ljava/lang/Object; 9 34
----
-> baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
-792c792
-< [public static void art.Frames.doTestSameThread(), 35]
----
-> [public static void art.Frames.doTestSameThread(), 40]
-807c807
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-810c810
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-813c813
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-816c816
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-827c827
-< [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2c]
----
-> [private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
-831c831
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-834c834
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-837c837
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-840c840
-< [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 9]
----
-> [private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
diff --git a/test/911-get-stack-trace/src/art/AllTraces.java b/test/911-get-stack-trace/src/art/AllTraces.java
index d73f78bba1..507925c29e 100644
--- a/test/911-get-stack-trace/src/art/AllTraces.java
+++ b/test/911-get-stack-trace/src/art/AllTraces.java
@@ -56,7 +56,7 @@ public class AllTraces {
printAll(0);
- printAll(5);
+ printAll(7);
printAll(25);
diff --git a/test/911-get-stack-trace/src/art/OtherThread.java b/test/911-get-stack-trace/src/art/OtherThread.java
index 675bff55a6..3f5ae59e18 100644
--- a/test/911-get-stack-trace/src/art/OtherThread.java
+++ b/test/911-get-stack-trace/src/art/OtherThread.java
@@ -36,8 +36,8 @@ public class OtherThread {
System.out.println("From top");
PrintThread.print(t, 0, 25);
PrintThread.print(t, 1, 25);
- PrintThread.print(t, 0, 5);
- PrintThread.print(t, 2, 5);
+ PrintThread.print(t, 0, 7);
+ PrintThread.print(t, 2, 7);
System.out.println("From bottom");
PrintThread.print(t, -1, 25);
diff --git a/test/911-get-stack-trace/src/art/ThreadListTraces.java b/test/911-get-stack-trace/src/art/ThreadListTraces.java
index 0de93de706..9b27e72f22 100644
--- a/test/911-get-stack-trace/src/art/ThreadListTraces.java
+++ b/test/911-get-stack-trace/src/art/ThreadListTraces.java
@@ -51,7 +51,7 @@ public class ThreadListTraces {
printList(list, 0);
- printList(list, 5);
+ printList(list, 7);
printList(list, 25);
diff --git a/test/913-heaps/check b/test/913-heaps/check
index c3b47f56ac..f7f8dab8cd 100644
--- a/test/913-heaps/check
+++ b/test/913-heaps/check
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Jack/D8 has a different set of bytecode offsets/method IDs in the expected.txt
+# D8 has a different set of bytecode offsets/method IDs in the expected.txt
if [[ "$USE_D8" == true ]]; then
patch -p0 expected.txt < expected_d8.diff
fi
diff --git a/test/dexdump/invoke-custom.dex b/test/dexdump/invoke-custom.dex
index dab6f0f0d6..c7de9dedf0 100644
--- a/test/dexdump/invoke-custom.dex
+++ b/test/dexdump/invoke-custom.dex
Binary files differ
diff --git a/test/dexdump/invoke-custom.lst b/test/dexdump/invoke-custom.lst
index 9037c28990..e481d2abcd 100644
--- a/test/dexdump/invoke-custom.lst
+++ b/test/dexdump/invoke-custom.lst
@@ -1,35 +1,145 @@
#invoke-custom.dex
-0x000009a0 8 invokecustom.Super <init> ()V InvokeCustom.java 29
-0x000009b8 16 invokecustom.Super targetMethodTest4 ()V InvokeCustom.java 31
-0x000009d8 8 invokecustom.InvokeCustom <clinit> ()V InvokeCustom.java 102
-0x000009f0 14 invokecustom.InvokeCustom <init> ()V InvokeCustom.java 39
-0x00000a10 74 invokecustom.InvokeCustom <init> (I)V InvokeCustom.java 40
-0x00000a6c 72 invokecustom.InvokeCustom bsmCreateCallSite (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite; InvokeCustom.java 160
-0x00000ac4 58 invokecustom.InvokeCustom bsmLookupStatic (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; InvokeCustom.java 142
-0x00000b10 164 invokecustom.InvokeCustom bsmLookupStaticWithExtraArgs (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IJFD)Ljava/lang/invoke/CallSite; InvokeCustom.java 151
-0x00000bc4 270 invokecustom.InvokeCustom bsmLookupTest9 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite; InvokeCustom.java 170
-0x00000ce4 164 invokecustom.InvokeCustom checkFieldTest9 (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V InvokeCustom.java 120
-0x00000d98 160 invokecustom.InvokeCustom checkStaticFieldTest9 (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V InvokeCustom.java 107
-0x00000e48 22 invokecustom.InvokeCustom lambda$lambdaTest$0 (Ljava/lang/String;)Z InvokeCustom.java 192
-0x00000e70 142 invokecustom.InvokeCustom lambdaTest ()V InvokeCustom.java 191
-0x00000f10 56 invokecustom.InvokeCustom main ([Ljava/lang/String;)V InvokeCustom.java -1
-0x00000f58 16 invokecustom.InvokeCustom targetMethodTest1 ()V InvokeCustom.java 45
-0x00000f78 92 invokecustom.InvokeCustom targetMethodTest2 (ZBCSIFJDLjava/lang/String;)V InvokeCustom.java 50
-0x00000fe4 16 invokecustom.InvokeCustom targetMethodTest3 ()V InvokeCustom.java 62
-0x00001004 166 invokecustom.InvokeCustom targetMethodTest5 (III)I InvokeCustom.java 72
-0x000010bc 170 invokecustom.InvokeCustom targetMethodTest6 (JJJ)J InvokeCustom.java 81
-0x00001178 172 invokecustom.InvokeCustom targetMethodTest7 (FFD)D InvokeCustom.java 90
-0x00001234 50 invokecustom.InvokeCustom targetMethodTest8 (Ljava/lang/String;)V InvokeCustom.java 99
-0x00001278 16 invokecustom.InvokeCustom targetMethodTest9 ()V InvokeCustom.java 133
-0x00001298 8 invokecustom.InvokeCustom test1 ()V InvokeCustom.java -1
-0x000012b0 54 invokecustom.InvokeCustom test2 ()V InvokeCustom.java -1
-0x000012f8 8 invokecustom.InvokeCustom test3 ()V InvokeCustom.java -1
-0x00001310 18 invokecustom.InvokeCustom test4 ()V InvokeCustom.java -1
-0x00001334 70 invokecustom.InvokeCustom test5 ()V InvokeCustom.java -1
-0x0000138c 88 invokecustom.InvokeCustom test6 ()V InvokeCustom.java -1
-0x000013f4 80 invokecustom.InvokeCustom test7 ()V InvokeCustom.java -1
-0x00001454 32 invokecustom.InvokeCustom test8 ()V InvokeCustom.java -1
-0x00001484 8 invokecustom.InvokeCustom test9 ()V InvokeCustom.java -1
-0x0000149c 54 invokecustom.InvokeCustom helperMethodTest9 ()V InvokeCustom.java 129
-0x000014e4 16 invokecustom.InvokeCustom run ()V InvokeCustom.java 137
-0x00001504 16 invokecustom.InvokeCustom targetMethodTest4 ()V InvokeCustom.java 68
+0x00001b28 8 TestBadBootstrapArguments$TestersConstantCallSite <init> (Ljava/lang/invoke/MethodHandle;)V TestBadBootstrapArguments.java 449
+0x00002554 8 TestBase <init> ()V TestBase.java 19
+0x0000256c 68 TestBase assertEquals (BB)V TestBase.java 27
+0x000025c0 68 TestBase assertEquals (CC)V TestBase.java 34
+0x00002614 72 TestBase assertEquals (DD)V TestBase.java 69
+0x0000266c 72 TestBase assertEquals (FF)V TestBase.java 62
+0x000026c4 68 TestBase assertEquals (II)V TestBase.java 48
+0x00002774 72 TestBase assertEquals (JJ)V TestBase.java 55
+0x00002718 76 TestBase assertEquals (Ljava/lang/Object;Ljava/lang/Object;)V TestBase.java 76
+0x000027cc 68 TestBase assertEquals (SS)V TestBase.java 41
+0x00002820 76 TestBase assertNotEquals (Ljava/lang/Object;Ljava/lang/Object;)V TestBase.java 82
+0x0000287c 16 TestBase assertNotReached ()V TestBase.java 88
+0x0000289c 52 TestBase assertTrue (Z)V TestBase.java 21
+0x000028e0 22 TestBase fail ()V TestBase.java 92
+0x00002acc 8 TestInvocationKinds$Widget <init> (I)V TestInvocationKinds.java 177
+0x00002ef8 8 TestInvokeCustomWithConcurrentThreads$1 <init> ()V TestInvokeCustomWithConcurrentThreads.java 33
+0x00002eb0 26 TestInvokeCustomWithConcurrentThreads$1 initialValue ()Ljava/lang/Integer; TestInvokeCustomWithConcurrentThreads.java 36
+0x00002edc 10 TestInvokeCustomWithConcurrentThreads$1 initialValue ()Ljava/lang/Object; TestInvokeCustomWithConcurrentThreads.java 33
+0x00003fd8 8 UnrelatedBSM <init> ()V UnrelatedBSM.java 23
+0x00003fb4 20 UnrelatedBSM bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite; UnrelatedBSM.java 27
+0x00001910 8 Main <init> ()V Main.java 21
+0x00001928 132 Main TestLinkerMethodMinimalArguments ()V Main.java 49
+0x000019e0 44 Main TestLinkerMethodMultipleArgumentTypes ()V Main.java 42
+0x00001a1c 156 Main TestUninitializedCallSite ()V Main.java 24
+0x00001ae0 56 Main main ([Ljava/lang/String;)V Main.java 78
+0x00001d74 8 TestBadBootstrapArguments <init> ()V TestBadBootstrapArguments.java 27
+0x00001d8c 16 TestBadBootstrapArguments boxingArguments ()V TestBadBootstrapArguments.java 348
+0x00001bc4 170 TestBadBootstrapArguments bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 35
+0x00001c80 90 TestBadBootstrapArguments bsmDJ (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 270
+0x00001cec 90 TestBadBootstrapArguments bsmDoubleLong (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 314
+0x00001b6c 26 TestBadBootstrapArguments bsmReturningInteger (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer; TestBadBootstrapArguments.java 425
+0x00001b98 26 TestBadBootstrapArguments bsmReturningObject (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object; TestBadBootstrapArguments.java 402
+0x00001b40 28 TestBadBootstrapArguments bsmReturningTestersConstantCallsite (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite; TestBadBootstrapArguments.java 455
+0x00001dac 16 TestBadBootstrapArguments bsmReturningVoid (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V TestBadBootstrapArguments.java 380
+0x00001d58 10 TestBadBootstrapArguments bsmZBCS (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 227
+0x00001dcc 16 TestBadBootstrapArguments extraArguments ()V TestBadBootstrapArguments.java 158
+0x00001dec 16 TestBadBootstrapArguments happy ()V TestBadBootstrapArguments.java 74
+0x00001e0c 8 TestBadBootstrapArguments integerReturnType ()V TestBadBootstrapArguments.java 444
+0x00001e24 8 TestBadBootstrapArguments invokeBoxingArguments ()V TestBadBootstrapArguments.java 344
+0x00001e3c 8 TestBadBootstrapArguments invokeExtraArguments ()V TestBadBootstrapArguments.java 154
+0x00001e54 8 TestBadBootstrapArguments invokeHappy ()V TestBadBootstrapArguments.java 70
+0x00001e6c 8 TestBadBootstrapArguments invokeIntegerReturnType ()V TestBadBootstrapArguments.java 440
+0x00001e84 8 TestBadBootstrapArguments invokeMissingParameterTypes ()V TestBadBootstrapArguments.java 124
+0x00001e9c 8 TestBadBootstrapArguments invokeNarrowArguments ()V TestBadBootstrapArguments.java 256
+0x00001eb4 8 TestBadBootstrapArguments invokeObjectReturnType ()V TestBadBootstrapArguments.java 417
+0x00001ecc 8 TestBadBootstrapArguments invokeViaCustomCallSiteClass ()V TestBadBootstrapArguments.java 469
+0x00001ee4 8 TestBadBootstrapArguments invokeVoidReturnType ()V TestBadBootstrapArguments.java 394
+0x00001efc 8 TestBadBootstrapArguments invokeWideningArguments ()V TestBadBootstrapArguments.java 300
+0x00001f14 8 TestBadBootstrapArguments invokeWideningBoxingArguments ()V TestBadBootstrapArguments.java 372
+0x00001f2c 8 TestBadBootstrapArguments invokeWrongArguments ()V TestBadBootstrapArguments.java 182
+0x00001f44 8 TestBadBootstrapArguments invokeWrongArgumentsAgain ()V TestBadBootstrapArguments.java 210
+0x00001f5c 8 TestBadBootstrapArguments invokeWrongParameterTypes ()V TestBadBootstrapArguments.java 98
+0x00001f74 16 TestBadBootstrapArguments missingParameterTypes ()V TestBadBootstrapArguments.java 128
+0x00001f94 8 TestBadBootstrapArguments narrowArguments ()V TestBadBootstrapArguments.java 260
+0x00001fac 8 TestBadBootstrapArguments objectReturnType ()V TestBadBootstrapArguments.java 421
+0x00001fc4 16 TestBadBootstrapArguments sayHello ()V TestBadBootstrapArguments.java 473
+0x00001fe4 1058 TestBadBootstrapArguments test ()V TestBadBootstrapArguments.java 477
+0x0000249c 8 TestBadBootstrapArguments voidReturnType ()V TestBadBootstrapArguments.java 398
+0x000024b4 16 TestBadBootstrapArguments wideningArguments ()V TestBadBootstrapArguments.java 304
+0x000024d4 16 TestBadBootstrapArguments wideningBoxingArguments ()V TestBadBootstrapArguments.java 376
+0x000024f4 16 TestBadBootstrapArguments wrongArguments ()V TestBadBootstrapArguments.java 186
+0x00002514 16 TestBadBootstrapArguments wrongArgumentsAgain ()V TestBadBootstrapArguments.java 214
+0x00002534 16 TestBadBootstrapArguments wrongParameterTypes ()V TestBadBootstrapArguments.java 102
+0x000029d8 8 TestDynamicBootstrapArguments <clinit> ()V TestDynamicBootstrapArguments.java 27
+0x000029f0 8 TestDynamicBootstrapArguments <init> ()V TestDynamicBootstrapArguments.java 26
+0x00002970 86 TestDynamicBootstrapArguments bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite; TestDynamicBootstrapArguments.java 36
+0x00002908 60 TestDynamicBootstrapArguments targetA100000000 (ILjava/lang/String;Ljava/lang/Double;)I TestDynamicBootstrapArguments.java 71
+0x00002a08 50 TestDynamicBootstrapArguments test ()V TestDynamicBootstrapArguments.java 86
+0x00002a4c 110 TestDynamicBootstrapArguments testCallSites ()V TestDynamicBootstrapArguments.java 80
+0x00002954 10 TestDynamicBootstrapArguments testDynamic (ILjava/lang/String;Ljava/lang/Double;)I TestDynamicBootstrapArguments.java 66
+0x00002cb4 8 TestInvocationKinds <init> ()V TestInvocationKinds.java 25
+0x00002b00 12 TestInvocationKinds getInstanceField (LTestInvocationKinds;)D TestInvocationKinds.java 117
+0x00002b38 10 TestInvocationKinds getStaticField ()I TestInvocationKinds.java 71
+0x00002b70 40 TestInvocationKinds lookupConstructor (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 183
+0x00002ba8 40 TestInvocationKinds lookupInstanceFieldGetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 101
+0x00002be0 42 TestInvocationKinds lookupInstanceFieldSetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 78
+0x00002c1c 32 TestInvocationKinds lookupStaticFieldGetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 32
+0x00002c4c 34 TestInvocationKinds lookupStaticFieldSetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 54
+0x00002c80 36 TestInvocationKinds lookupVirtual (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 146
+0x00002ae4 10 TestInvocationKinds makeWidget (I)LTestInvocationKinds$Widget; TestInvocationKinds.java 200
+0x00002b54 10 TestInvocationKinds maxIntegerValue (LTestInvocationKinds;II)I TestInvocationKinds.java 159
+0x00002ccc 16 TestInvocationKinds setInstanceField (LTestInvocationKinds;D)V TestInvocationKinds.java 94
+0x00002cec 8 TestInvocationKinds setStaticField (I)V TestInvocationKinds.java 48
+0x00002d04 48 TestInvocationKinds test ()V TestInvocationKinds.java 212
+0x00002d44 62 TestInvocationKinds testConstructor ()V TestInvocationKinds.java 205
+0x00002d94 88 TestInvocationKinds testInstanceFieldAccessors ()V TestInvocationKinds.java 133
+0x00002dfc 50 TestInvocationKinds testInvokeVirtual ()V TestInvocationKinds.java 168
+0x00002e40 94 TestInvocationKinds testStaticFieldAccessors ()V TestInvocationKinds.java 122
+0x00002b1c 12 TestInvocationKinds getMaxIntegerValue (II)I TestInvocationKinds.java 164
+0x00003074 74 TestInvokeCustomWithConcurrentThreads <clinit> ()V TestInvokeCustomWithConcurrentThreads.java 30
+0x000030d0 8 TestInvokeCustomWithConcurrentThreads <init> ()V TestInvokeCustomWithConcurrentThreads.java 52
+0x0000305c 6 TestInvokeCustomWithConcurrentThreads access$000 ()Ljava/util/concurrent/atomic/AtomicInteger; TestInvokeCustomWithConcurrentThreads.java 27
+0x00002f10 26 TestInvokeCustomWithConcurrentThreads getThreadIndex ()I TestInvokeCustomWithConcurrentThreads.java 55
+0x00002f88 194 TestInvokeCustomWithConcurrentThreads linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvokeCustomWithConcurrentThreads.java 87
+0x00002f3c 2 TestInvokeCustomWithConcurrentThreads notUsed (I)I TestInvokeCustomWithConcurrentThreads.java 59
+0x00002f50 40 TestInvokeCustomWithConcurrentThreads setCalled (I)I TestInvokeCustomWithConcurrentThreads.java 79
+0x0000310c 458 TestInvokeCustomWithConcurrentThreads test ()V TestInvokeCustomWithConcurrentThreads.java 107
+0x000030e8 18 TestInvokeCustomWithConcurrentThreads run ()V TestInvokeCustomWithConcurrentThreads.java 63
+0x00003414 8 TestLinkerMethodMinimalArguments <clinit> ()V TestLinkerMethodMinimalArguments.java 26
+0x0000342c 8 TestLinkerMethodMinimalArguments <init> ()V TestLinkerMethodMinimalArguments.java 25
+0x000032e8 46 TestLinkerMethodMinimalArguments _add (II)I TestLinkerMethodMinimalArguments.java 51
+0x00003328 10 TestLinkerMethodMinimalArguments add (II)I TestLinkerMethodMinimalArguments.java 45
+0x00003344 192 TestLinkerMethodMinimalArguments linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestLinkerMethodMinimalArguments.java 61
+0x00003444 136 TestLinkerMethodMinimalArguments test (III)V TestLinkerMethodMinimalArguments.java 78
+0x00003628 8 TestLinkerMethodMultipleArgumentTypes <clinit> ()V TestLinkerMethodMultipleArgumentTypes.java 28
+0x00003640 8 TestLinkerMethodMultipleArgumentTypes <init> ()V TestLinkerMethodMultipleArgumentTypes.java 26
+0x000034f4 6 TestLinkerMethodMultipleArgumentTypes _add (II)I TestLinkerMethodMultipleArgumentTypes.java 74
+0x0000350c 10 TestLinkerMethodMultipleArgumentTypes add (II)I TestLinkerMethodMultipleArgumentTypes.java 68
+0x00003528 238 TestLinkerMethodMultipleArgumentTypes linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite; TestLinkerMethodMultipleArgumentTypes.java 93
+0x00003658 34 TestLinkerMethodMultipleArgumentTypes test (II)V TestLinkerMethodMultipleArgumentTypes.java 114
+0x000034dc 6 TestLinkerMethodMultipleArgumentTypes GetBootstrapRunCount ()I TestLinkerMethodMultipleArgumentTypes.java 110
+0x000036f4 8 TestLinkerUnrelatedBSM <init> ()V TestLinkerUnrelatedBSM.java 23
+0x0000368c 6 TestLinkerUnrelatedBSM _addf (FF)F TestLinkerUnrelatedBSM.java 47
+0x000036a4 6 TestLinkerUnrelatedBSM _subf (FF)F TestLinkerUnrelatedBSM.java 73
+0x000036bc 10 TestLinkerUnrelatedBSM addf (FF)F TestLinkerUnrelatedBSM.java 42
+0x000036d8 10 TestLinkerUnrelatedBSM subf (FF)F TestLinkerUnrelatedBSM.java 68
+0x0000370c 68 TestLinkerUnrelatedBSM test ()V TestLinkerUnrelatedBSM.java 77
+0x00003a8c 8 TestVariableArityLinkerMethod <init> ()V TestVariableArityLinkerMethod.java 27
+0x00003760 68 TestVariableArityLinkerMethod bsmWithBoxedArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 477
+0x000037b4 74 TestVariableArityLinkerMethod bsmWithClassAndFloatArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 294
+0x00003810 68 TestVariableArityLinkerMethod bsmWithClassArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 367
+0x00003864 68 TestVariableArityLinkerMethod bsmWithDoubleArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 332
+0x000038b8 82 TestVariableArityLinkerMethod bsmWithFloatAndLongArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 257
+0x0000391c 82 TestVariableArityLinkerMethod bsmWithIntAndStringArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 133
+0x00003980 82 TestVariableArityLinkerMethod bsmWithLongAndIntArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 219
+0x000039e4 68 TestVariableArityLinkerMethod bsmWithStringArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 61
+0x00003a38 68 TestVariableArityLinkerMethod bsmWithWiderArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 447
+0x00003aa4 16 TestVariableArityLinkerMethod methodA ()V TestVariableArityLinkerMethod.java 86
+0x00003ac4 16 TestVariableArityLinkerMethod methodB ()V TestVariableArityLinkerMethod.java 105
+0x00003ae4 16 TestVariableArityLinkerMethod methodC ()V TestVariableArityLinkerMethod.java 123
+0x00003b04 16 TestVariableArityLinkerMethod methodD ()V TestVariableArityLinkerMethod.java 166
+0x00003b24 16 TestVariableArityLinkerMethod methodE ()V TestVariableArityLinkerMethod.java 189
+0x00003b44 16 TestVariableArityLinkerMethod methodF ()V TestVariableArityLinkerMethod.java 209
+0x00003b64 16 TestVariableArityLinkerMethod methodG ()V TestVariableArityLinkerMethod.java 247
+0x00003b84 16 TestVariableArityLinkerMethod methodH ()V TestVariableArityLinkerMethod.java 284
+0x00003ba4 16 TestVariableArityLinkerMethod methodI ()V TestVariableArityLinkerMethod.java 323
+0x00003bc4 16 TestVariableArityLinkerMethod methodJ ()V TestVariableArityLinkerMethod.java 358
+0x00003be4 16 TestVariableArityLinkerMethod methodK ()V TestVariableArityLinkerMethod.java 392
+0x00003c04 8 TestVariableArityLinkerMethod methodO ()V TestVariableArityLinkerMethod.java 413
+0x00003c1c 8 TestVariableArityLinkerMethod methodP ()V TestVariableArityLinkerMethod.java 441
+0x00003c34 8 TestVariableArityLinkerMethod methodQ ()V TestVariableArityLinkerMethod.java 468
+0x00003c4c 8 TestVariableArityLinkerMethod methodR ()V TestVariableArityLinkerMethod.java 501
+0x00003c64 318 TestVariableArityLinkerMethod printBsmArgs (Ljava/lang/String;[Ljava/lang/Object;)V TestVariableArityLinkerMethod.java 29
+0x00003db4 448 TestVariableArityLinkerMethod test ()V TestVariableArityLinkerMethod.java 506
diff --git a/test/dexdump/invoke-custom.txt b/test/dexdump/invoke-custom.txt
index bd3250865b..cfab248168 100644
--- a/test/dexdump/invoke-custom.txt
+++ b/test/dexdump/invoke-custom.txt
@@ -2,49 +2,98 @@ Processing 'invoke-custom.dex'...
Opened 'invoke-custom.dex', DEX version '038'
DEX file header:
magic : 'dex\n038\0'
-checksum : d11a9e29
-signature : 5b54...15c3
-file_size : 8984
+checksum : dc722174
+signature : b59a...f803
+file_size : 31732
header_size : 112
link_size : 0
link_off : 0 (0x000000)
-string_ids_size : 165
+string_ids_size : 478
string_ids_off : 112 (0x000070)
-type_ids_size : 38
-type_ids_off : 772 (0x000304)
-proto_ids_size : 51
-proto_ids_off : 924 (0x00039c)
-field_ids_size : 3
-field_ids_off : 1536 (0x000600)
-method_ids_size : 78
-method_ids_off : 1560 (0x000618)
-class_defs_size : 2
-class_defs_off : 2184 (0x000888)
-data_size : 6552
-data_off : 2432 (0x000980)
+type_ids_size : 77
+type_ids_off : 2024 (0x0007e8)
+proto_ids_size : 91
+proto_ids_off : 2332 (0x00091c)
+field_ids_size : 21
+field_ids_off : 3424 (0x000d60)
+method_ids_size : 243
+method_ids_off : 3592 (0x000e08)
+class_defs_size : 14
+class_defs_off : 5536 (0x0015a0)
+data_size : 25332
+data_off : 6400 (0x001900)
Class #0 header:
-class_idx : 8
-access_flags : 1024 (0x0400)
-superclass_idx : 13
+class_idx : 7
+access_flags : 0 (0x0000)
+superclass_idx : 52
interfaces_off : 0 (0x000000)
-source_file_idx : 27
-annotations_off : 0 (0x000000)
-class_data_off : 8589 (0x00218d)
+source_file_idx : 144
+annotations_off : 30700 (0x0077ec)
+class_data_off : 28922 (0x0070fa)
static_fields_size : 0
instance_fields_size: 0
direct_methods_size : 1
-virtual_methods_size: 2
+virtual_methods_size: 0
+
+Class #0 annotations:
+Annotations on class
+ VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestBadBootstrapArguments;
+ VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=8 name="TestersConstantCallSite"
Class #0 -
- Class descriptor : 'Linvokecustom/Super;'
+ Class descriptor : 'LTestBadBootstrapArguments$TestersConstantCallSite;'
+ Access flags : 0x0000 ()
+ Superclass : 'Ljava/lang/invoke/ConstantCallSite;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestBadBootstrapArguments$TestersConstantCallSite;)
+ name : '<init>'
+ type : '(Ljava/lang/invoke/MethodHandle;)V'
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
+ code -
+ registers : 2
+ ins : 2
+ outs : 2
+ insns size : 4 16-bit code units
+001b18: |[001b18] TestBadBootstrapArguments.TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V
+001b28: 7020 d200 1000 |0000: invoke-direct {v0, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001b2e: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=449
+ 0x0003 line=450
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestBadBootstrapArguments$TestersConstantCallSite;
+ 0x0000 - 0x0004 reg=1 mh Ljava/lang/invoke/MethodHandle;
+
+ Virtual methods -
+ source_file_idx : 144 (TestBadBootstrapArguments.java)
+
+Class #1 header:
+class_idx : 9
+access_flags : 1024 (0x0400)
+superclass_idx : 42
+interfaces_off : 0 (0x000000)
+source_file_idx : 145
+annotations_off : 0 (0x000000)
+class_data_off : 28932 (0x007104)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 13
+virtual_methods_size: 0
+
+Class #1 -
+ Class descriptor : 'LTestBase;'
Access flags : 0x0400 (ABSTRACT)
Superclass : 'Ljava/lang/Object;'
Interfaces -
Static fields -
Instance fields -
Direct methods -
- #0 : (in Linvokecustom/Super;)
+ #0 : (in LTestBase;)
name : '<init>'
type : '()V'
access : 0x10000 (CONSTRUCTOR)
@@ -53,627 +102,1581 @@ Class #0 -
ins : 1
outs : 1
insns size : 4 16-bit code units
-000990: |[000990] invokecustom.Super.<init>:()V
-0009a0: 7010 2b00 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@002b
-0009a6: 0e00 |0003: return-void
+002544: |[002544] TestBase.<init>:()V
+002554: 7010 bf00 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+00255a: 0e00 |0003: return-void
catches : (none)
positions :
- 0x0000 line=29
+ 0x0000 line=19
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestBase;
+
+ #1 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(BB)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 34 16-bit code units
+00255c: |[00255c] TestBase.assertEquals:(BB)V
+00256c: 3343 0300 |0000: if-ne v3, v4, 0003 // +0003
+002570: 0e00 |0002: return-void
+002572: 2200 1e00 |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002576: 2201 2d00 |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00257a: 7010 c100 0100 |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002580: 1a02 d300 |000a: const-string v2, "assertEquals b1: " // string@00d3
+002584: 6e20 c800 2100 |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00258a: 6e20 c500 3100 |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+002590: 1a02 0d00 |0012: const-string v2, ", b2: " // string@000d
+002594: 6e20 c800 2100 |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00259a: 6e20 c500 4100 |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0025a0: 6e10 ca00 0100 |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0025a6: 0c01 |001d: move-result-object v1
+0025a8: 7020 b500 1000 |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0025ae: 2700 |0021: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=27
+ 0x0002 line=28
+ 0x0003 line=30
+ locals :
+ 0x0000 - 0x0022 reg=3 b1 B
+ 0x0000 - 0x0022 reg=4 b2 B
+
+ #2 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(CC)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 34 16-bit code units
+0025b0: |[0025b0] TestBase.assertEquals:(CC)V
+0025c0: 3343 0300 |0000: if-ne v3, v4, 0003 // +0003
+0025c4: 0e00 |0002: return-void
+0025c6: 2200 1e00 |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0025ca: 2201 2d00 |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0025ce: 7010 c100 0100 |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0025d4: 1a02 d400 |000a: const-string v2, "assertEquals c1: " // string@00d4
+0025d8: 6e20 c800 2100 |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0025de: 6e20 c200 3100 |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(C)Ljava/lang/StringBuilder; // method@00c2
+0025e4: 1a02 0e00 |0012: const-string v2, ", c2: " // string@000e
+0025e8: 6e20 c800 2100 |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0025ee: 6e20 c200 4100 |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(C)Ljava/lang/StringBuilder; // method@00c2
+0025f4: 6e10 ca00 0100 |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0025fa: 0c01 |001d: move-result-object v1
+0025fc: 7020 b500 1000 |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002602: 2700 |0021: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=34
+ 0x0002 line=35
+ 0x0003 line=37
+ locals :
+ 0x0000 - 0x0022 reg=3 c1 C
+ 0x0000 - 0x0022 reg=4 c2 C
+
+ #3 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(DD)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 7
+ ins : 4
+ outs : 3
+ insns size : 36 16-bit code units
+002604: |[002604] TestBase.assertEquals:(DD)V
+002614: 2f00 0305 |0000: cmpl-double v0, v3, v5
+002618: 3900 0300 |0002: if-nez v0, 0005 // +0003
+00261c: 0e00 |0004: return-void
+00261e: 2200 1e00 |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002622: 2201 2d00 |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002626: 7010 c100 0100 |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00262c: 1a02 d500 |000c: const-string v2, "assertEquals d1: " // string@00d5
+002630: 6e20 c800 2100 |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002636: 6e30 c300 3104 |0011: invoke-virtual {v1, v3, v4}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@00c3
+00263c: 1a02 0f00 |0014: const-string v2, ", d2: " // string@000f
+002640: 6e20 c800 2100 |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002646: 6e30 c300 5106 |0019: invoke-virtual {v1, v5, v6}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@00c3
+00264c: 6e10 ca00 0100 |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002652: 0c01 |001f: move-result-object v1
+002654: 7020 b500 1000 |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00265a: 2700 |0023: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=69
+ 0x0004 line=70
+ 0x0005 line=72
+ locals :
+ 0x0000 - 0x0024 reg=3 d1 D
+ 0x0000 - 0x0024 reg=5 d2 D
+
+ #4 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(FF)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 36 16-bit code units
+00265c: |[00265c] TestBase.assertEquals:(FF)V
+00266c: 2d00 0304 |0000: cmpl-float v0, v3, v4
+002670: 3900 0300 |0002: if-nez v0, 0005 // +0003
+002674: 0e00 |0004: return-void
+002676: 2200 1e00 |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+00267a: 2201 2d00 |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00267e: 7010 c100 0100 |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002684: 1a02 d600 |000c: const-string v2, "assertEquals f1: " // string@00d6
+002688: 6e20 c800 2100 |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00268e: 6e20 c400 3100 |0011: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@00c4
+002694: 1a02 1000 |0014: const-string v2, ", f2: " // string@0010
+002698: 6e20 c800 2100 |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00269e: 6e20 c400 4100 |0019: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@00c4
+0026a4: 6e10 ca00 0100 |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0026aa: 0c01 |001f: move-result-object v1
+0026ac: 7020 b500 1000 |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0026b2: 2700 |0023: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=62
+ 0x0004 line=63
+ 0x0005 line=65
+ locals :
+ 0x0000 - 0x0024 reg=3 f1 F
+ 0x0000 - 0x0024 reg=4 f2 F
+
+ #5 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(II)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 34 16-bit code units
+0026b4: |[0026b4] TestBase.assertEquals:(II)V
+0026c4: 3343 0300 |0000: if-ne v3, v4, 0003 // +0003
+0026c8: 0e00 |0002: return-void
+0026ca: 2200 1e00 |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0026ce: 2201 2d00 |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0026d2: 7010 c100 0100 |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0026d8: 1a02 d700 |000a: const-string v2, "assertEquals i1: " // string@00d7
+0026dc: 6e20 c800 2100 |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0026e2: 6e20 c500 3100 |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0026e8: 1a02 1100 |0012: const-string v2, ", i2: " // string@0011
+0026ec: 6e20 c800 2100 |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0026f2: 6e20 c500 4100 |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0026f8: 6e10 ca00 0100 |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0026fe: 0c01 |001d: move-result-object v1
+002700: 7020 b500 1000 |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002706: 2700 |0021: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=48
+ 0x0002 line=49
+ 0x0003 line=51
+ locals :
+ 0x0000 - 0x0022 reg=3 i1 I
+ 0x0000 - 0x0022 reg=4 i2 I
+
+ #6 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(JJ)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 7
+ ins : 4
+ outs : 3
+ insns size : 36 16-bit code units
+002764: |[002764] TestBase.assertEquals:(JJ)V
+002774: 3100 0305 |0000: cmp-long v0, v3, v5
+002778: 3900 0300 |0002: if-nez v0, 0005 // +0003
+00277c: 0e00 |0004: return-void
+00277e: 2200 1e00 |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002782: 2201 2d00 |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002786: 7010 c100 0100 |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00278c: 1a02 d800 |000c: const-string v2, "assertEquals l1: " // string@00d8
+002790: 6e20 c800 2100 |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002796: 6e30 c600 3104 |0011: invoke-virtual {v1, v3, v4}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+00279c: 1a02 1200 |0014: const-string v2, ", l2: " // string@0012
+0027a0: 6e20 c800 2100 |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027a6: 6e30 c600 5106 |0019: invoke-virtual {v1, v5, v6}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+0027ac: 6e10 ca00 0100 |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0027b2: 0c01 |001f: move-result-object v1
+0027b4: 7020 b500 1000 |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0027ba: 2700 |0023: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=55
+ 0x0004 line=56
+ 0x0005 line=58
+ locals :
+ 0x0000 - 0x0024 reg=3 l1 J
+ 0x0000 - 0x0024 reg=5 l2 J
+
+ #7 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(Ljava/lang/Object;Ljava/lang/Object;)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 38 16-bit code units
+002708: |[002708] TestBase.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V
+002718: 7120 ec00 4300 |0000: invoke-static {v3, v4}, Ljava/util/Objects;.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z // method@00ec
+00271e: 0a00 |0003: move-result v0
+002720: 3800 0300 |0004: if-eqz v0, 0007 // +0003
+002724: 0e00 |0006: return-void
+002726: 2200 1e00 |0007: new-instance v0, Ljava/lang/AssertionError; // type@001e
+00272a: 2201 2d00 |0009: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00272e: 7010 c100 0100 |000b: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002734: 1a02 da00 |000e: const-string v2, "assertEquals: o1: " // string@00da
+002738: 6e20 c800 2100 |0010: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00273e: 6e20 c700 3100 |0013: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+002744: 1a02 1300 |0016: const-string v2, ", o2: " // string@0013
+002748: 6e20 c800 2100 |0018: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00274e: 6e20 c700 4100 |001b: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+002754: 6e10 ca00 0100 |001e: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00275a: 0c01 |0021: move-result-object v1
+00275c: 7020 b500 1000 |0022: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002762: 2700 |0025: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=76
+ 0x0006 line=79
+ 0x0007 line=77
+ locals :
+ 0x0000 - 0x0026 reg=3 o Ljava/lang/Object;
+ 0x0000 - 0x0026 reg=4 p Ljava/lang/Object;
+
+ #8 : (in LTestBase;)
+ name : 'assertEquals'
+ type : '(SS)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 34 16-bit code units
+0027bc: |[0027bc] TestBase.assertEquals:(SS)V
+0027cc: 3343 0300 |0000: if-ne v3, v4, 0003 // +0003
+0027d0: 0e00 |0002: return-void
+0027d2: 2200 1e00 |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0027d6: 2201 2d00 |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0027da: 7010 c100 0100 |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0027e0: 1a02 d900 |000a: const-string v2, "assertEquals s1: " // string@00d9
+0027e4: 6e20 c800 2100 |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027ea: 6e20 c500 3100 |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0027f0: 1a02 1400 |0012: const-string v2, ", s2: " // string@0014
+0027f4: 6e20 c800 2100 |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027fa: 6e20 c500 4100 |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+002800: 6e10 ca00 0100 |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002806: 0c01 |001d: move-result-object v1
+002808: 7020 b500 1000 |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00280e: 2700 |0021: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=41
+ 0x0002 line=42
+ 0x0003 line=44
+ locals :
+ 0x0000 - 0x0022 reg=3 s1 S
+ 0x0000 - 0x0022 reg=4 s2 S
+
+ #9 : (in LTestBase;)
+ name : 'assertNotEquals'
+ type : '(Ljava/lang/Object;Ljava/lang/Object;)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 2
+ outs : 2
+ insns size : 38 16-bit code units
+002810: |[002810] TestBase.assertNotEquals:(Ljava/lang/Object;Ljava/lang/Object;)V
+002820: 7120 ec00 4300 |0000: invoke-static {v3, v4}, Ljava/util/Objects;.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z // method@00ec
+002826: 0a00 |0003: move-result v0
+002828: 3900 0300 |0004: if-nez v0, 0007 // +0003
+00282c: 0e00 |0006: return-void
+00282e: 2200 1e00 |0007: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002832: 2201 2d00 |0009: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002836: 7010 c100 0100 |000b: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00283c: 1a02 dc00 |000e: const-string v2, "assertNotEquals: o1: " // string@00dc
+002840: 6e20 c800 2100 |0010: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002846: 6e20 c700 3100 |0013: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00284c: 1a02 1300 |0016: const-string v2, ", o2: " // string@0013
+002850: 6e20 c800 2100 |0018: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002856: 6e20 c700 4100 |001b: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00285c: 6e10 ca00 0100 |001e: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002862: 0c01 |0021: move-result-object v1
+002864: 7020 b500 1000 |0022: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00286a: 2700 |0025: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=82
+ 0x0006 line=85
+ 0x0007 line=83
+ locals :
+ 0x0000 - 0x0026 reg=3 o Ljava/lang/Object;
+ 0x0000 - 0x0026 reg=4 p Ljava/lang/Object;
+
+ #10 : (in LTestBase;)
+ name : 'assertNotReached'
+ type : '()V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+00286c: |[00286c] TestBase.assertNotReached:()V
+00287c: 2200 1e00 |0000: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002880: 1a01 a300 |0002: const-string v1, "Unreachable" // string@00a3
+002884: 7020 b500 1000 |0004: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00288a: 2700 |0007: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=88
+ locals :
+
+ #11 : (in LTestBase;)
+ name : 'assertTrue'
+ type : '(Z)V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 4
+ ins : 1
+ outs : 2
+ insns size : 26 16-bit code units
+00288c: |[00288c] TestBase.assertTrue:(Z)V
+00289c: 3803 0300 |0000: if-eqz v3, 0003 // +0003
+0028a0: 0e00 |0002: return-void
+0028a2: 2200 1e00 |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0028a6: 2201 2d00 |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0028aa: 7010 c100 0100 |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0028b0: 1a02 df00 |000a: const-string v2, "assertTrue value: " // string@00df
+0028b4: 6e20 c800 2100 |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0028ba: 6e20 c900 3100 |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Z)Ljava/lang/StringBuilder; // method@00c9
+0028c0: 6e10 ca00 0100 |0012: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0028c6: 0c01 |0015: move-result-object v1
+0028c8: 7020 b500 1000 |0016: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0028ce: 2700 |0019: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=21
+ 0x0002 line=24
+ 0x0003 line=22
+ locals :
+ 0x0000 - 0x001a reg=3 value Z
+
+ #12 : (in LTestBase;)
+ name : 'fail'
+ type : '()V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 11 16-bit code units
+0028d0: |[0028d0] TestBase.fail:()V
+0028e0: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0028e4: 1a01 2601 |0002: const-string v1, "fail" // string@0126
+0028e8: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0028ee: 7100 cc00 0000 |0007: invoke-static {}, Ljava/lang/Thread;.dumpStack:()V // method@00cc
+0028f4: 0e00 |000a: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=92
+ 0x0007 line=93
+ 0x000a line=94
locals :
- 0x0000 - 0x0004 reg=0 this Linvokecustom/Super;
Virtual methods -
- #0 : (in Linvokecustom/Super;)
- name : 'helperMethodTest9'
+ source_file_idx : 145 (TestBase.java)
+
+Class #2 header:
+class_idx : 11
+access_flags : 0 (0x0000)
+superclass_idx : 42
+interfaces_off : 0 (0x000000)
+source_file_idx : 148
+annotations_off : 30716 (0x0077fc)
+class_data_off : 28990 (0x00713e)
+static_fields_size : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 0
+
+Class #2 annotations:
+Annotations on class
+ VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestInvocationKinds;
+ VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=8 name="Widget"
+
+Class #2 -
+ Class descriptor : 'LTestInvocationKinds$Widget;'
+ Access flags : 0x0000 ()
+ Superclass : 'Ljava/lang/Object;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ #0 : (in LTestInvocationKinds$Widget;)
+ name : 'value'
+ type : 'I'
+ access : 0x0000 ()
+ Direct methods -
+ #0 : (in LTestInvocationKinds$Widget;)
+ name : '<init>'
+ type : '(I)V'
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
+ code -
+ registers : 2
+ ins : 2
+ outs : 1
+ insns size : 4 16-bit code units
+002abc: |[002abc] TestInvocationKinds.Widget.<init>:(I)V
+002acc: 7010 bf00 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+002ad2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=177
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestInvocationKinds$Widget;
+ 0x0000 - 0x0004 reg=1 value I
+
+ Virtual methods -
+ source_file_idx : 148 (TestInvocationKinds.java)
+
+Class #3 header:
+class_idx : 13
+access_flags : 0 (0x0000)
+superclass_idx : 48
+interfaces_off : 0 (0x000000)
+source_file_idx : 149
+annotations_off : 30732 (0x00780c)
+class_data_off : 29002 (0x00714a)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 1
+virtual_methods_size: 2
+
+Class #3 annotations:
+Annotations on class
+ VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestInvokeCustomWithConcurrentThreads;
+ VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=0 name=null
+ VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "Ljava/lang/ThreadLocal<" "Ljava/lang/Integer;" ">;" }
+
+Class #3 -
+ Class descriptor : 'LTestInvokeCustomWithConcurrentThreads$1;'
+ Access flags : 0x0000 ()
+ Superclass : 'Ljava/lang/ThreadLocal;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestInvokeCustomWithConcurrentThreads$1;)
+ name : '<init>'
type : '()V'
- access : 0x0401 (PUBLIC ABSTRACT)
- code : (none)
+ access : 0x10000 (CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+002ee8: |[002ee8] TestInvokeCustomWithConcurrentThreads.1.<init>:()V
+002ef8: 7010 cf00 0000 |0000: invoke-direct {v0}, Ljava/lang/ThreadLocal;.<init>:()V // method@00cf
+002efe: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=33
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestInvokeCustomWithConcurrentThreads$1;
+
+ Virtual methods -
+ #0 : (in LTestInvokeCustomWithConcurrentThreads$1;)
+ name : 'initialValue'
+ type : '()Ljava/lang/Integer;'
+ access : 0x0004 (PROTECTED)
+ code -
+ registers : 2
+ ins : 1
+ outs : 1
+ insns size : 13 16-bit code units
+002ea0: |[002ea0] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Integer;
+002eb0: 7100 6500 0000 |0000: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.access$000:()Ljava/util/concurrent/atomic/AtomicInteger; // method@0065
+002eb6: 0c00 |0003: move-result-object v0
+002eb8: 6e10 f100 0000 |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1
+002ebe: 0a00 |0007: move-result v0
+002ec0: 7110 bd00 0000 |0008: invoke-static {v0}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+002ec6: 0c00 |000b: move-result-object v0
+002ec8: 1100 |000c: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=36
+ locals :
+ 0x0000 - 0x000d reg=1 this LTestInvokeCustomWithConcurrentThreads$1;
+
+ #1 : (in LTestInvokeCustomWithConcurrentThreads$1;)
+ name : 'initialValue'
+ type : '()Ljava/lang/Object;'
+ access : 0x1044 (PROTECTED BRIDGE SYNTHETIC)
+ code -
+ registers : 2
+ ins : 1
+ outs : 1
+ insns size : 5 16-bit code units
+002ecc: |[002ecc] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Object;
+002edc: 6e10 6100 0100 |0000: invoke-virtual {v1}, LTestInvokeCustomWithConcurrentThreads$1;.initialValue:()Ljava/lang/Integer; // method@0061
+002ee2: 0c00 |0003: move-result-object v0
+002ee4: 1100 |0004: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=33
+ locals :
+ 0x0000 - 0x0005 reg=1 this LTestInvokeCustomWithConcurrentThreads$1;
+
+ source_file_idx : 149 (TestInvokeCustomWithConcurrentThreads.java)
- #1 : (in Linvokecustom/Super;)
- name : 'targetMethodTest4'
+Class #4 header:
+class_idx : 19
+access_flags : 0 (0x0000)
+superclass_idx : 42
+interfaces_off : 0 (0x000000)
+source_file_idx : 164
+annotations_off : 30748 (0x00781c)
+class_data_off : 29021 (0x00715d)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 2
+virtual_methods_size: 0
+
+Class #4 annotations:
+Annotations on method #170 'bsm'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "Ljava/lang/Class<" "*>;)" "Ljava/lang/invoke/CallSite;" }
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #4 -
+ Class descriptor : 'LUnrelatedBSM;'
+ Access flags : 0x0000 ()
+ Superclass : 'Ljava/lang/Object;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LUnrelatedBSM;)
+ name : '<init>'
type : '()V'
- access : 0x0001 (PUBLIC)
+ access : 0x10000 (CONSTRUCTOR)
code -
- registers : 3
+ registers : 1
ins : 1
- outs : 2
- insns size : 8 16-bit code units
-0009a8: |[0009a8] invokecustom.Super.targetMethodTest4:()V
-0009b8: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0009bc: 1a01 8b00 |0002: const-string v1, "targetMethodTest4 from Super" // string@008b
-0009c0: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0009c6: 0e00 |0007: return-void
+ outs : 1
+ insns size : 4 16-bit code units
+003fc8: |[003fc8] UnrelatedBSM.<init>:()V
+003fd8: 7010 bf00 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+003fde: 0e00 |0003: return-void
catches : (none)
positions :
- 0x0000 line=31
- 0x0007 line=32
+ 0x0000 line=23
locals :
- 0x0000 - 0x0008 reg=2 this Linvokecustom/Super;
+ 0x0000 - 0x0004 reg=0 this LUnrelatedBSM;
- source_file_idx : 27 (InvokeCustom.java)
+ #1 : (in LUnrelatedBSM;)
+ name : 'bsm'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 6
+ ins : 4
+ outs : 4
+ insns size : 10 16-bit code units
+003fa4: |[003fa4] UnrelatedBSM.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+003fb4: 6e40 d800 5243 |0000: invoke-virtual {v2, v5, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003fba: 0c00 |0003: move-result-object v0
+003fbc: 2201 3400 |0004: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003fc0: 7020 d200 0100 |0006: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003fc6: 1101 |0009: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=27
+ 0x0004 line=28
+ locals :
+ 0x0000 - 0x0000 reg=5 (null) Ljava/lang/Class;
+ 0x0004 - 0x000a reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x000a reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x000a reg=3 name Ljava/lang/String;
+ 0x0000 - 0x000a reg=4 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x000a reg=5 target Ljava/lang/Class; Ljava/lang/Class<*>;
-Class #1 header:
-class_idx : 7
+ Virtual methods -
+ source_file_idx : 164 (UnrelatedBSM.java)
+
+Class #5 header:
+class_idx : 6
access_flags : 1 (0x0001)
-superclass_idx : 8
-interfaces_off : 5460 (0x001554)
-source_file_idx : 27
-annotations_off : 5396 (0x001514)
-class_data_off : 8607 (0x00219f)
-static_fields_size : 1
-instance_fields_size: 1
-direct_methods_size : 29
-virtual_methods_size: 3
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 136
+annotations_off : 30772 (0x007834)
+class_data_off : 29036 (0x00716c)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 5
+virtual_methods_size: 0
-Class #1 annotations:
-Annotations on method #3 'bsmCreateCallSite'
+Class #5 annotations:
+Annotations on method #1 'TestLinkerMethodMinimalArguments'
VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
-Annotations on method #4 'bsmLookupStatic'
- VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodException; Ljava/lang/IllegalAccessException; }
-Annotations on method #5 'bsmLookupStaticWithExtraArgs'
- VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodException; Ljava/lang/IllegalAccessException; }
-Annotations on method #6 'bsmLookupTest9'
+Annotations on method #2 'TestLinkerMethodMultipleArgumentTypes'
VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
-Annotations on method #7 'checkFieldTest9'
+Annotations on method #3 'TestUninitializedCallSite'
VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
-Annotations on method #8 'checkStaticFieldTest9'
+Annotations on method #7 'main'
VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
-Class #1 -
- Class descriptor : 'Linvokecustom/InvokeCustom;'
+Class #5 -
+ Class descriptor : 'LMain;'
Access flags : 0x0001 (PUBLIC)
- Superclass : 'Linvokecustom/Super;'
+ Superclass : 'LTestBase;'
Interfaces -
- #0 : 'Ljava/lang/Runnable;'
Static fields -
- #0 : (in Linvokecustom/InvokeCustom;)
- name : 'staticFieldTest9'
- type : 'I'
- access : 0x000a (PRIVATE STATIC)
Instance fields -
- #0 : (in Linvokecustom/InvokeCustom;)
- name : 'fieldTest9'
- type : 'F'
- access : 0x0002 (PRIVATE)
Direct methods -
- #0 : (in Linvokecustom/InvokeCustom;)
- name : '<clinit>'
+ #0 : (in LMain;)
+ name : '<init>'
type : '()V'
- access : 0x10008 (STATIC CONSTRUCTOR)
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
code -
registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+001900: |[001900] Main.<init>:()V
+001910: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+001916: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=21
+ locals :
+ 0x0000 - 0x0004 reg=0 this LMain;
+
+ #1 : (in LMain;)
+ name : 'TestLinkerMethodMinimalArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 4
ins : 0
+ outs : 3
+ insns size : 66 16-bit code units
+001918: |[001918] Main.TestLinkerMethodMinimalArguments:()V
+001928: 1210 |0000: const/4 v0, #int 1 // #1
+00192a: 1301 0a00 |0001: const/16 v1, #int 10 // #a
+00192e: 7130 7700 1001 |0003: invoke-static {v0, v1, v1}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001934: 7100 0500 0000 |0006: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00193a: 280f |0009: goto 0018 // +000f
+00193c: 0d00 |000a: move-exception v0
+00193e: 6e10 b600 0000 |000b: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+001944: 0c02 |000e: move-result-object v2
+001946: 6e10 c000 0200 |000f: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00194c: 0c02 |0012: move-result-object v2
+00194e: 1c03 2200 |0013: const-class v3, Ljava/lang/ClassCastException; // type@0022
+001952: 7120 0400 3200 |0015: invoke-static {v2, v3}, LMain;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0004
+001958: 1220 |0018: const/4 v0, #int 2 // #2
+00195a: 1302 0b00 |0019: const/16 v2, #int 11 // #b
+00195e: 7130 7700 1002 |001b: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001964: 7100 0500 0000 |001e: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00196a: 280f |0021: goto 0030 // +000f
+00196c: 0d00 |0022: move-exception v0
+00196e: 6e10 b600 0000 |0023: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+001974: 0c02 |0026: move-result-object v2
+001976: 6e10 c000 0200 |0027: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00197c: 0c02 |002a: move-result-object v2
+00197e: 1c03 2600 |002b: const-class v3, Ljava/lang/InstantiationException; // type@0026
+001982: 7120 0400 3200 |002d: invoke-static {v2, v3}, LMain;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0004
+001988: 1230 |0030: const/4 v0, #int 3 // #3
+00198a: 1302 0c00 |0031: const/16 v2, #int 12 // #c
+00198e: 7130 7700 1002 |0033: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001994: 7100 0500 0000 |0036: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00199a: 2802 |0039: goto 003b // +0002
+00199c: 0d00 |003a: move-exception v0
+00199e: 1200 |003b: const/4 v0, #int 0 // #0
+0019a0: 1302 0d00 |003c: const/16 v2, #int 13 // #d
+0019a4: 7130 7700 1002 |003e: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+0019aa: 0e00 |0041: return-void
+ catches : 3
+ 0x0003 - 0x0009
+ Ljava/lang/BootstrapMethodError; -> 0x000a
+ 0x001b - 0x0021
+ Ljava/lang/BootstrapMethodError; -> 0x0022
+ 0x0033 - 0x0039
+ Ljava/lang/ArithmeticException; -> 0x003a
+ positions :
+ 0x0000 line=49
+ 0x0006 line=53
+ 0x0009 line=56
+ 0x000a line=54
+ 0x000b line=55
+ 0x0018 line=59
+ 0x001e line=61
+ 0x0021 line=64
+ 0x0022 line=62
+ 0x0023 line=63
+ 0x0030 line=67
+ 0x0036 line=69
+ 0x0039 line=71
+ 0x003a line=70
+ 0x003b line=73
+ 0x0041 line=75
+ locals :
+ 0x000b - 0x0018 reg=0 e Ljava/lang/BootstrapMethodError;
+ 0x0023 - 0x0030 reg=0 e Ljava/lang/BootstrapMethodError;
+
+ #2 : (in LMain;)
+ name : 'TestLinkerMethodMultipleArgumentTypes'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 22 16-bit code units
+0019d0: |[0019d0] Main.TestLinkerMethodMultipleArgumentTypes:()V
+0019e0: 1300 2100 |0000: const/16 v0, #int 33 // #21
+0019e4: 1301 4300 |0002: const/16 v1, #int 67 // #43
+0019e8: 7120 8400 1000 |0004: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+0019ee: 1300 f0d8 |0007: const/16 v0, #int -10000 // #d8f0
+0019f2: 1301 e803 |0009: const/16 v1, #int 1000 // #3e8
+0019f6: 7120 8400 1000 |000b: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+0019fc: 1300 18fc |000e: const/16 v0, #int -1000 // #fc18
+001a00: 1301 1027 |0010: const/16 v1, #int 10000 // #2710
+001a04: 7120 8400 1000 |0012: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+001a0a: 0e00 |0015: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=42
+ 0x0007 line=43
+ 0x000e line=44
+ 0x0015 line=45
+ locals :
+
+ #3 : (in LMain;)
+ name : 'TestUninitializedCallSite'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 7
+ ins : 0
+ outs : 3
+ insns size : 78 16-bit code units
+001a0c: |[001a0c] Main.TestUninitializedCallSite:()V
+001a1c: 2200 3900 |0000: new-instance v0, Ljava/lang/invoke/MutableCallSite; // type@0039
+001a20: 6201 1200 |0002: sget-object v1, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+001a24: 7110 e100 0100 |0004: invoke-static {v1}, Ljava/lang/invoke/MethodType;.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00e1
+001a2a: 0c01 |0007: move-result-object v1
+001a2c: 7020 e600 1000 |0008: invoke-direct {v0, v1}, Ljava/lang/invoke/MutableCallSite;.<init>:(Ljava/lang/invoke/MethodType;)V // method@00e6
+001a32: 6e10 d100 0000 |000b: invoke-virtual {v0}, Ljava/lang/invoke/CallSite;.getTarget:()Ljava/lang/invoke/MethodHandle; // method@00d1
+001a38: 0c01 |000e: move-result-object v1
+001a3a: fa10 d300 0100 4100 |000f: invoke-polymorphic {v1}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, ()V // method@00d3, proto@0041
+001a42: 7100 0600 0000 |0013: invoke-static {}, LMain;.fail:()V // method@0006
+001a48: 2809 |0016: goto 001f // +0009
+001a4a: 0d01 |0017: move-exception v1
+001a4c: 6202 1300 |0018: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001a50: 1a03 2100 |001a: const-string v3, "Caught exception from uninitialized call site" // string@0021
+001a54: 6e20 b300 3200 |001c: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001a5a: 2201 3900 |001f: new-instance v1, Ljava/lang/invoke/MutableCallSite; // type@0039
+001a5e: 1c02 2c00 |0021: const-class v2, Ljava/lang/String; // type@002c
+001a62: 6203 1200 |0023: sget-object v3, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+001a66: 1214 |0025: const/4 v4, #int 1 // #1
+001a68: 2344 4600 |0026: new-array v4, v4, [Ljava/lang/Class; // type@0046
+001a6c: 1205 |0028: const/4 v5, #int 0 // #0
+001a6e: 6206 1100 |0029: sget-object v6, Ljava/lang/Character;.TYPE:Ljava/lang/Class; // field@0011
+001a72: 4d06 0405 |002b: aput-object v6, v4, v5
+001a76: 7130 e200 3204 |002d: invoke-static {v2, v3, v4}, Ljava/lang/invoke/MethodType;.methodType:(Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00e2
+001a7c: 0c02 |0030: move-result-object v2
+001a7e: 7020 e600 2100 |0031: invoke-direct {v1, v2}, Ljava/lang/invoke/MutableCallSite;.<init>:(Ljava/lang/invoke/MethodType;)V // method@00e6
+001a84: 0710 |0034: move-object v0, v1
+001a86: 6e10 d100 0000 |0035: invoke-virtual {v0}, Ljava/lang/invoke/CallSite;.getTarget:()Ljava/lang/invoke/MethodHandle; // method@00d1
+001a8c: 0c01 |0038: move-result-object v1
+001a8e: 1302 ff05 |0039: const/16 v2, #int 1535 // #5ff
+001a92: 1303 6400 |003b: const/16 v3, #int 100 // #64
+001a96: fa30 d300 2103 4800 |003d: invoke-polymorphic {v1, v2, v3}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (IC)V // method@00d3, proto@0048
+001a9e: 7100 0600 0000 |0041: invoke-static {}, LMain;.fail:()V // method@0006
+001aa4: 2809 |0044: goto 004d // +0009
+001aa6: 0d01 |0045: move-exception v1
+001aa8: 6202 1300 |0046: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001aac: 1a03 2100 |0048: const-string v3, "Caught exception from uninitialized call site" // string@0021
+001ab0: 6e20 b300 3200 |004a: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ab6: 0e00 |004d: return-void
+ catches : 2
+ 0x000b - 0x0016
+ Ljava/lang/IllegalStateException; -> 0x0017
+ 0x0035 - 0x0044
+ Ljava/lang/IllegalStateException; -> 0x0045
+ positions :
+ 0x0000 line=24
+ 0x000b line=26
+ 0x0013 line=27
+ 0x0016 line=30
+ 0x0017 line=28
+ 0x0018 line=29
+ 0x001f line=32
+ 0x0035 line=34
+ 0x0041 line=35
+ 0x0044 line=38
+ 0x0045 line=36
+ 0x0046 line=37
+ 0x004d line=39
+ locals :
+ 0x0018 - 0x001f reg=1 e Ljava/lang/IllegalStateException;
+ 0x0046 - 0x004d reg=1 e Ljava/lang/IllegalStateException;
+ 0x000b - 0x004e reg=0 callSite Ljava/lang/invoke/CallSite;
+
+ #4 : (in LMain;)
+ name : 'main'
+ type : '([Ljava/lang/String;)V'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 1
+ ins : 1
outs : 0
- insns size : 4 16-bit code units
-0009c8: |[0009c8] invokecustom.InvokeCustom.<clinit>:()V
-0009d8: 1200 |0000: const/4 v0, #int 0 // #0
-0009da: 6700 0100 |0001: sput v0, Linvokecustom/InvokeCustom;.staticFieldTest9:I // field@0001
-0009de: 0e00 |0003: return-void
+ insns size : 28 16-bit code units
+001ad0: |[001ad0] Main.main:([Ljava/lang/String;)V
+001ae0: 7100 0300 0000 |0000: invoke-static {}, LMain;.TestUninitializedCallSite:()V // method@0003
+001ae6: 7100 0100 0000 |0003: invoke-static {}, LMain;.TestLinkerMethodMinimalArguments:()V // method@0001
+001aec: 7100 0200 0000 |0006: invoke-static {}, LMain;.TestLinkerMethodMultipleArgumentTypes:()V // method@0002
+001af2: 7100 8c00 0000 |0009: invoke-static {}, LTestLinkerUnrelatedBSM;.test:()V // method@008c
+001af8: 7100 6e00 0000 |000c: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.test:()V // method@006e
+001afe: 7100 5b00 0000 |000f: invoke-static {}, LTestInvocationKinds;.test:()V // method@005b
+001b04: 7100 4500 0000 |0012: invoke-static {}, LTestDynamicBootstrapArguments;.test:()V // method@0045
+001b0a: 7100 2b00 0000 |0015: invoke-static {}, LTestBadBootstrapArguments;.test:()V // method@002b
+001b10: 7100 a800 0000 |0018: invoke-static {}, LTestVariableArityLinkerMethod;.test:()V // method@00a8
+001b16: 0e00 |001b: return-void
catches : (none)
positions :
- 0x0000 line=102
+ 0x0000 line=78
+ 0x0003 line=79
+ 0x0006 line=80
+ 0x0009 line=81
+ 0x000c line=82
+ 0x000f line=83
+ 0x0012 line=84
+ 0x0015 line=85
+ 0x0018 line=86
+ 0x001b line=87
locals :
+ 0x0000 - 0x001c reg=0 args [Ljava/lang/String;
- #1 : (in Linvokecustom/InvokeCustom;)
+ Virtual methods -
+ source_file_idx : 136 (Main.java)
+
+Class #6 header:
+class_idx : 8
+access_flags : 1 (0x0001)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 144
+annotations_off : 30820 (0x007864)
+class_data_off : 29062 (0x007186)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 38
+virtual_methods_size: 0
+
+Class #6 annotations:
+Annotations on class
+ VISIBILITY_SYSTEM Ldalvik/annotation/MemberClasses; value={ LTestBadBootstrapArguments$TestersConstantCallSite; }
+Annotations on method #14 'bsm'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #15 'bsmDJ'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #16 'bsmDoubleLong'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #19 'bsmReturningTestersConstantCallsite'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #21 'bsmZBCS'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #25 'invokeBoxingArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDoubleLong" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Double; Ljava/lang/Long; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; longValue={ 9223372036854775807 } } fieldOrMethodName="boxingArguments"
+Annotations on method #26 'invokeExtraArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 1 } Lannotations/Constant; stringValue={ "2" } Lannotations/Constant; intValue={ 3 } } fieldOrMethodName="extraArguments"
+Annotations on method #27 'invokeHappy'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; stringValue={ "very" } } fieldOrMethodName="happy"
+Annotations on method #28 'invokeIntegerReturnType'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningInteger" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=Ljava/lang/Integer; } fieldOrMethodName="integerReturnType"
+Annotations on method #29 'invokeMissingParameterTypes'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I D } } constantArgumentsForBootstrapMethod={ } fieldOrMethodName="missingParameterTypes"
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodError; }
+Annotations on method #30 'invokeNarrowArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmZBCS" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Z B C S } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; booleanValue={ true } Lannotations/Constant; byteValue={ 127 } Lannotations/Constant; charValue={ 65 } Lannotations/Constant; shortValue={ -32768 } } fieldOrMethodName="narrowArguments"
+Annotations on method #31 'invokeObjectReturnType'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningObject" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=Ljava/lang/Object; } fieldOrMethodName="ObjectReturnType"
+Annotations on method #32 'invokeViaCustomCallSiteClass'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningTestersConstantCallsite" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=LTestBadBootstrapArguments$TestersConstantCallSite; } fieldOrMethodName="sayHello"
+Annotations on method #33 'invokeVoidReturnType'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningVoid" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=V } fieldOrMethodName="voidReturnType"
+Annotations on method #34 'invokeWideningArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDJ" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; D J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; intValue={ 2147483647 } } fieldOrMethodName="wideningArguments"
+Annotations on method #35 'invokeWideningBoxingArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDoubleLong" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Double; Ljava/lang/Long; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; floatValue={ 3.40282e+38 } Lannotations/Constant; longValue={ 2147483647 } } fieldOrMethodName="wideningBoxingArguments"
+Annotations on method #36 'invokeWrongArguments'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "1" } Lannotations/Constant; doubleValue={ 3.14159 } } fieldOrMethodName="wrongArguments"
+Annotations on method #37 'invokeWrongArgumentsAgain'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 3.14159 } Lannotations/Constant; stringValue={ "pie" } } fieldOrMethodName="wrongArgumentsAgain"
+Annotations on method #38 'invokeWrongParameterTypes'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I D } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; stringValue={ "very" } } fieldOrMethodName="wrongParameterTypes"
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodError; }
+
+Class #6 -
+ Class descriptor : 'LTestBadBootstrapArguments;'
+ Access flags : 0x0001 (PUBLIC)
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestBadBootstrapArguments;)
name : '<init>'
type : '()V'
access : 0x10001 (PUBLIC CONSTRUCTOR)
code -
- registers : 2
+ registers : 1
ins : 1
outs : 1
- insns size : 7 16-bit code units
-0009e0: |[0009e0] invokecustom.InvokeCustom.<init>:()V
-0009f0: 7010 2000 0100 |0000: invoke-direct {v1}, Linvokecustom/Super;.<init>:()V // method@0020
-0009f6: 1200 |0003: const/4 v0, #int 0 // #0
-0009f8: 5910 0000 |0004: iput v0, v1, Linvokecustom/InvokeCustom;.fieldTest9:F // field@0000
-0009fc: 0e00 |0006: return-void
+ insns size : 4 16-bit code units
+001d64: |[001d64] TestBadBootstrapArguments.<init>:()V
+001d74: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+001d7a: 0e00 |0003: return-void
catches : (none)
positions :
- 0x0000 line=39
- 0x0003 line=115
- 0x0006 line=39
+ 0x0000 line=27
locals :
- 0x0000 - 0x0007 reg=1 this Linvokecustom/InvokeCustom;
+ 0x0000 - 0x0004 reg=0 this LTestBadBootstrapArguments;
- #2 : (in Linvokecustom/InvokeCustom;)
- name : '<init>'
- type : '(I)V'
- access : 0x10001 (PUBLIC CONSTRUCTOR)
+ #1 : (in LTestBadBootstrapArguments;)
+ name : 'boxingArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 5
- ins : 2
+ registers : 2
+ ins : 0
outs : 2
- insns size : 37 16-bit code units
-000a00: |[000a00] invokecustom.InvokeCustom.<init>:(I)V
-000a10: 7010 2000 0300 |0000: invoke-direct {v3}, Linvokecustom/Super;.<init>:()V // method@0020
-000a16: 1200 |0003: const/4 v0, #int 0 // #0
-000a18: 5930 0000 |0004: iput v0, v3, Linvokecustom/InvokeCustom;.fieldTest9:F // field@0000
-000a1c: 6200 0200 |0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000a20: 2201 1000 |0008: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-000a24: 7010 3000 0100 |000a: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000a2a: 1a02 1a00 |000d: const-string v2, "InvokeCustom.<init>(" // string@001a
-000a2e: 6e20 3600 2100 |000f: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000a34: 0c01 |0012: move-result-object v1
-000a36: 6e20 3300 4100 |0013: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-000a3c: 0c01 |0016: move-result-object v1
-000a3e: 1a02 0800 |0017: const-string v2, ")" // string@0008
-000a42: 6e20 3600 2100 |0019: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000a48: 0c01 |001c: move-result-object v1
-000a4a: 6e10 3700 0100 |001d: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000a50: 0c01 |0020: move-result-object v1
-000a52: 6e20 2900 1000 |0021: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000a58: 0e00 |0024: return-void
- catches : (none)
- positions :
- 0x0000 line=40
- 0x0003 line=115
- 0x0006 line=41
- 0x0024 line=42
- locals :
- 0x0000 - 0x0025 reg=3 this Linvokecustom/InvokeCustom;
- 0x0000 - 0x0025 reg=4 (null) I
-
- #3 : (in Linvokecustom/InvokeCustom;)
- name : 'bsmCreateCallSite'
- type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;'
- access : 0x0009 (PUBLIC STATIC)
+ insns size : 8 16-bit code units
+001d7c: |[001d7c] TestBadBootstrapArguments.boxingArguments:()V
+001d8c: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d90: 1a01 e900 |0002: const-string v1, "boxingArguments" // string@00e9
+001d94: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001d9a: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=348
+ 0x0007 line=349
+ locals :
+
+ #2 : (in LTestBadBootstrapArguments;)
+ name : 'bsm'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
code -
registers : 7
- ins : 4
- outs : 2
- insns size : 36 16-bit code units
-000a5c: |[000a5c] invokecustom.InvokeCustom.bsmCreateCallSite:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
-000a6c: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000a70: 2201 1000 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-000a74: 7010 3000 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000a7a: 1a02 6000 |0007: const-string v2, "bsmCreateCallSite [" // string@0060
-000a7e: 6e20 3600 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000a84: 0c01 |000c: move-result-object v1
-000a86: 6e20 3500 6100 |000d: invoke-virtual {v1, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000a8c: 0c01 |0010: move-result-object v1
-000a8e: 1a02 5900 |0011: const-string v2, "]" // string@0059
-000a92: 6e20 3600 2100 |0013: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000a98: 0c01 |0016: move-result-object v1
-000a9a: 6e10 3700 0100 |0017: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000aa0: 0c01 |001a: move-result-object v1
-000aa2: 6e20 2900 1000 |001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000aa8: 2200 1400 |001e: new-instance v0, Ljava/lang/invoke/ConstantCallSite; // type@0014
-000aac: 7020 3800 6000 |0020: invoke-direct {v0, v6}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0038
-000ab2: 1100 |0023: return-object v0
- catches : (none)
- positions :
- 0x0000 line=160
- 0x001e line=161
- locals :
- 0x0000 - 0x0024 reg=3 (null) Ljava/lang/invoke/MethodHandles$Lookup;
- 0x0000 - 0x0024 reg=4 (null) Ljava/lang/String;
- 0x0000 - 0x0024 reg=5 (null) Ljava/lang/invoke/MethodType;
- 0x0000 - 0x0024 reg=6 (null) Ljava/lang/invoke/MethodHandle;
-
- #4 : (in Linvokecustom/InvokeCustom;)
- name : 'bsmLookupStatic'
- type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
- access : 0x0009 (PUBLIC STATIC)
+ ins : 5
+ outs : 4
+ insns size : 85 16-bit code units
+001bb4: |[001bb4] TestBadBootstrapArguments.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;
+001bc4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bc8: 1a01 ee00 |0002: const-string v1, "bsm(" // string@00ee
+001bcc: 6e20 b000 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bd2: 6200 1300 |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bd6: 6e10 dc00 0200 |0009: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001bdc: 0c01 |000c: move-result-object v1
+001bde: 6e20 af00 1000 |000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001be4: 6200 1300 |0010: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001be8: 1a01 0c00 |0012: const-string v1, ", " // string@000c
+001bec: 6e20 b000 1000 |0014: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bf2: 6200 1300 |0017: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bf6: 6e20 b000 3000 |0019: invoke-virtual {v0, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bfc: 6200 1300 |001c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c00: 1a01 0c00 |001e: const-string v1, ", " // string@000c
+001c04: 6e20 b000 1000 |0020: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c0a: 6200 1300 |0023: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c0e: 6e20 af00 4000 |0025: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001c14: 6200 1300 |0028: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c18: 1a01 0c00 |002a: const-string v1, ", " // string@000c
+001c1c: 6e20 b000 1000 |002c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c22: 6200 1300 |002f: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c26: 6e20 ad00 5000 |0031: invoke-virtual {v0, v5}, Ljava/io/PrintStream;.print:(I)V // method@00ad
+001c2c: 6200 1300 |0034: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c30: 1a01 0c00 |0036: const-string v1, ", " // string@000c
+001c34: 6e20 b000 1000 |0038: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c3a: 6200 1300 |003b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c3e: 6e20 b000 6000 |003d: invoke-virtual {v0, v6}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c44: 6200 1300 |0040: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c48: 1a01 0700 |0042: const-string v1, ")" // string@0007
+001c4c: 6e20 b300 1000 |0044: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001c52: 6e10 dc00 0200 |0047: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001c58: 0c00 |004a: move-result-object v0
+001c5a: 6e40 d800 0243 |004b: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001c60: 0c00 |004e: move-result-object v0
+001c62: 2201 3400 |004f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001c66: 7020 d200 0100 |0051: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001c6c: 1101 |0054: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=35
+ 0x0007 line=36
+ 0x0010 line=37
+ 0x0017 line=38
+ 0x001c line=39
+ 0x0023 line=40
+ 0x0028 line=41
+ 0x002f line=42
+ 0x0034 line=43
+ 0x003b line=44
+ 0x0040 line=45
+ 0x0047 line=46
+ 0x004f line=47
+ locals :
+ 0x004f - 0x0055 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0055 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0055 reg=3 methodName Ljava/lang/String;
+ 0x0000 - 0x0055 reg=4 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0055 reg=5 extraInt I
+ 0x0000 - 0x0055 reg=6 extraString Ljava/lang/String;
+
+ #3 : (in LTestBadBootstrapArguments;)
+ name : 'bsmDJ'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 5
- ins : 3
+ registers : 9
+ ins : 7
outs : 4
- insns size : 29 16-bit code units
-000ab4: |[000ab4] invokecustom.InvokeCustom.bsmLookupStatic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
-000ac4: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000ac8: 1a01 6200 |0002: const-string v1, "bsmLookupStatic []" // string@0062
-000acc: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000ad2: 7100 4600 0000 |0007: invoke-static {}, Ljava/lang/invoke/MethodHandles;.lookup:()Ljava/lang/invoke/MethodHandles$Lookup; // method@0046
-000ad8: 0c00 |000a: move-result-object v0
-000ada: 6e10 4500 0000 |000b: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@0045
-000ae0: 0c01 |000e: move-result-object v1
-000ae2: 6e40 4400 1043 |000f: invoke-virtual {v0, v1, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@0044
-000ae8: 0c00 |0012: move-result-object v0
-000aea: 2201 1400 |0013: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0014
-000aee: 6e20 3a00 4000 |0015: invoke-virtual {v0, v4}, Ljava/lang/invoke/MethodHandle;.asType:(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@003a
-000af4: 0c00 |0018: move-result-object v0
-000af6: 7020 3800 0100 |0019: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0038
-000afc: 1101 |001c: return-object v1
- catches : (none)
- positions :
- 0x0000 line=142
- 0x0007 line=143
- 0x000b line=144
- 0x0013 line=145
- locals :
- 0x0000 - 0x001d reg=2 (null) Ljava/lang/invoke/MethodHandles$Lookup;
- 0x0000 - 0x001d reg=3 (null) Ljava/lang/String;
- 0x0000 - 0x001d reg=4 (null) Ljava/lang/invoke/MethodType;
-
- #5 : (in Linvokecustom/InvokeCustom;)
- name : 'bsmLookupStaticWithExtraArgs'
- type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IJFD)Ljava/lang/invoke/CallSite;'
- access : 0x0009 (PUBLIC STATIC)
+ insns size : 45 16-bit code units
+001c70: |[001c70] TestBadBootstrapArguments.bsmDJ:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;
+001c80: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c84: 1a01 f100 |0002: const-string v1, "bsmDJ(..., " // string@00f1
+001c88: 6e20 b000 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c8e: 6200 1300 |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c92: 6e30 ac00 5006 |0009: invoke-virtual {v0, v5, v6}, Ljava/io/PrintStream;.print:(D)V // method@00ac
+001c98: 6200 1300 |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c9c: 1a01 0c00 |000e: const-string v1, ", " // string@000c
+001ca0: 6e20 b000 1000 |0010: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001ca6: 6200 1300 |0013: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001caa: 6e30 ae00 7008 |0015: invoke-virtual {v0, v7, v8}, Ljava/io/PrintStream;.print:(J)V // method@00ae
+001cb0: 6200 1300 |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cb4: 1a01 0700 |001a: const-string v1, ")" // string@0007
+001cb8: 6e20 b300 1000 |001c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001cbe: 6e10 dc00 0200 |001f: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001cc4: 0c00 |0022: move-result-object v0
+001cc6: 6e40 d800 0243 |0023: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001ccc: 0c00 |0026: move-result-object v0
+001cce: 2201 3400 |0027: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001cd2: 7020 d200 0100 |0029: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001cd8: 1101 |002c: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=270
+ 0x0007 line=271
+ 0x000c line=272
+ 0x0013 line=273
+ 0x0018 line=274
+ 0x001f line=275
+ 0x0027 line=276
+ locals :
+ 0x0027 - 0x002d reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x002d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x002d reg=3 methodName Ljava/lang/String;
+ 0x0000 - 0x002d reg=4 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x002d reg=5 extraArg0 D
+ 0x0000 - 0x002d reg=7 extraArg1 J
+
+ #4 : (in LTestBadBootstrapArguments;)
+ name : 'bsmDoubleLong'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 12
- ins : 9
+ registers : 7
+ ins : 5
outs : 4
- insns size : 82 16-bit code units
-000b00: |[000b00] invokecustom.InvokeCustom.bsmLookupStaticWithExtraArgs:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IJFD)Ljava/lang/invoke/CallSite;
-000b10: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000b14: 2201 1000 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-000b18: 7010 3000 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000b1e: 1a02 6400 |0007: const-string v2, "bsmLookupStaticWithExtraArgs [" // string@0064
-000b22: 6e20 3600 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000b28: 0c01 |000c: move-result-object v1
-000b2a: 6e20 3300 6100 |000d: invoke-virtual {v1, v6}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-000b30: 0c01 |0010: move-result-object v1
-000b32: 1a02 0900 |0011: const-string v2, ", " // string@0009
-000b36: 6e20 3600 2100 |0013: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000b3c: 0c01 |0016: move-result-object v1
-000b3e: 6e30 3400 7108 |0017: invoke-virtual {v1, v7, v8}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-000b44: 0c01 |001a: move-result-object v1
-000b46: 1a02 0900 |001b: const-string v2, ", " // string@0009
-000b4a: 6e20 3600 2100 |001d: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000b50: 0c01 |0020: move-result-object v1
-000b52: 6e20 3200 9100 |0021: invoke-virtual {v1, v9}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-000b58: 0c01 |0024: move-result-object v1
-000b5a: 1a02 0900 |0025: const-string v2, ", " // string@0009
-000b5e: 6e20 3600 2100 |0027: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000b64: 0c01 |002a: move-result-object v1
-000b66: 6e30 3100 a10b |002b: invoke-virtual {v1, v10, v11}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@0031
-000b6c: 0c01 |002e: move-result-object v1
-000b6e: 1a02 5900 |002f: const-string v2, "]" // string@0059
-000b72: 6e20 3600 2100 |0031: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000b78: 0c01 |0034: move-result-object v1
-000b7a: 6e10 3700 0100 |0035: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000b80: 0c01 |0038: move-result-object v1
-000b82: 6e20 2900 1000 |0039: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000b88: 7100 4600 0000 |003c: invoke-static {}, Ljava/lang/invoke/MethodHandles;.lookup:()Ljava/lang/invoke/MethodHandles$Lookup; // method@0046
-000b8e: 0c00 |003f: move-result-object v0
-000b90: 6e10 4500 0000 |0040: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@0045
-000b96: 0c01 |0043: move-result-object v1
-000b98: 6e40 4400 1054 |0044: invoke-virtual {v0, v1, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@0044
-000b9e: 0c00 |0047: move-result-object v0
-000ba0: 2201 1400 |0048: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0014
-000ba4: 6e20 3a00 5000 |004a: invoke-virtual {v0, v5}, Ljava/lang/invoke/MethodHandle;.asType:(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@003a
-000baa: 0c00 |004d: move-result-object v0
-000bac: 7020 3800 0100 |004e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0038
-000bb2: 1101 |0051: return-object v1
- catches : (none)
- positions :
- 0x0000 line=151
- 0x003c line=152
- 0x0040 line=153
- 0x0048 line=154
- locals :
- 0x0000 - 0x0052 reg=3 (null) Ljava/lang/invoke/MethodHandles$Lookup;
- 0x0000 - 0x0052 reg=4 (null) Ljava/lang/String;
- 0x0000 - 0x0052 reg=5 (null) Ljava/lang/invoke/MethodType;
- 0x0000 - 0x0052 reg=6 (null) I
- 0x0000 - 0x0052 reg=7 (null) J
- 0x0000 - 0x0052 reg=9 (null) F
- 0x0000 - 0x0052 reg=10 (null) D
-
- #6 : (in Linvokecustom/InvokeCustom;)
- name : 'bsmLookupTest9'
- type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;'
- access : 0x0009 (PUBLIC STATIC)
+ insns size : 45 16-bit code units
+001cdc: |[001cdc] TestBadBootstrapArguments.bsmDoubleLong:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;
+001cec: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cf0: 1a01 f300 |0002: const-string v1, "bsmDoubleLong(..., " // string@00f3
+001cf4: 6e20 b000 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001cfa: 6200 1300 |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cfe: 6e20 af00 5000 |0009: invoke-virtual {v0, v5}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001d04: 6200 1300 |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d08: 1a01 0c00 |000e: const-string v1, ", " // string@000c
+001d0c: 6e20 b000 1000 |0010: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001d12: 6200 1300 |0013: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d16: 6e20 af00 6000 |0015: invoke-virtual {v0, v6}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001d1c: 6200 1300 |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d20: 1a01 0700 |001a: const-string v1, ")" // string@0007
+001d24: 6e20 b300 1000 |001c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001d2a: 6e10 dc00 0200 |001f: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001d30: 0c00 |0022: move-result-object v0
+001d32: 6e40 d800 0243 |0023: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001d38: 0c00 |0026: move-result-object v0
+001d3a: 2201 3400 |0027: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001d3e: 7020 d200 0100 |0029: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001d44: 1101 |002c: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=314
+ 0x0007 line=315
+ 0x000c line=316
+ 0x0013 line=317
+ 0x0018 line=318
+ 0x001f line=319
+ 0x0027 line=320
+ locals :
+ 0x0027 - 0x002d reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x002d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x002d reg=3 methodName Ljava/lang/String;
+ 0x0000 - 0x002d reg=4 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x002d reg=5 extraArg0 Ljava/lang/Double;
+ 0x0000 - 0x002d reg=6 extraArg1 Ljava/lang/Long;
+
+ #5 : (in LTestBadBootstrapArguments;)
+ name : 'bsmReturningInteger'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;'
+ access : 0x0008 (STATIC)
code -
- registers : 13
- ins : 10
+ registers : 5
+ ins : 3
+ outs : 2
+ insns size : 13 16-bit code units
+001b5c: |[001b5c] TestBadBootstrapArguments.bsmReturningInteger:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;
+001b6c: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001b70: 1a01 eb00 |0002: const-string v1, "bsm returning Integer value." // string@00eb
+001b74: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001b7a: 1230 |0007: const/4 v0, #int 3 // #3
+001b7c: 7110 bd00 0000 |0008: invoke-static {v0}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+001b82: 0c00 |000b: move-result-object v0
+001b84: 1100 |000c: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=425
+ 0x0007 line=426
+ locals :
+ 0x0000 - 0x000d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x000d reg=3 name Ljava/lang/String;
+ 0x0000 - 0x000d reg=4 type Ljava/lang/invoke/MethodType;
+
+ #6 : (in LTestBadBootstrapArguments;)
+ name : 'bsmReturningObject'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 2
+ insns size : 13 16-bit code units
+001b88: |[001b88] TestBadBootstrapArguments.bsmReturningObject:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;
+001b98: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001b9c: 1a01 ec00 |0002: const-string v1, "bsm returning Object value." // string@00ec
+001ba0: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ba6: 2200 2a00 |0007: new-instance v0, Ljava/lang/Object; // type@002a
+001baa: 7010 bf00 0000 |0009: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+001bb0: 1100 |000c: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=402
+ 0x0007 line=403
+ locals :
+ 0x0000 - 0x000d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x000d reg=3 name Ljava/lang/String;
+ 0x0000 - 0x000d reg=4 type Ljava/lang/invoke/MethodType;
+
+ #7 : (in LTestBadBootstrapArguments;)
+ name : 'bsmReturningTestersConstantCallsite'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
outs : 4
- insns size : 135 16-bit code units
-000bb4: |[000bb4] invokecustom.InvokeCustom.bsmLookupTest9:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
-000bc4: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000bc8: 2201 1000 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-000bcc: 7010 3000 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000bd2: 1a02 6600 |0007: const-string v2, "bsmLookupTest9 [" // string@0066
-000bd6: 6e20 3600 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000bdc: 0c01 |000c: move-result-object v1
-000bde: 6e20 3500 6100 |000d: invoke-virtual {v1, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000be4: 0c01 |0010: move-result-object v1
-000be6: 1a02 0900 |0011: const-string v2, ", " // string@0009
-000bea: 6e20 3600 2100 |0013: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000bf0: 0c01 |0016: move-result-object v1
-000bf2: 6e20 3500 7100 |0017: invoke-virtual {v1, v7}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000bf8: 0c01 |001a: move-result-object v1
-000bfa: 1a02 0900 |001b: const-string v2, ", " // string@0009
-000bfe: 6e20 3600 2100 |001d: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000c04: 0c01 |0020: move-result-object v1
-000c06: 6e20 3500 8100 |0021: invoke-virtual {v1, v8}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000c0c: 0c01 |0024: move-result-object v1
-000c0e: 1a02 0900 |0025: const-string v2, ", " // string@0009
-000c12: 6e20 3600 2100 |0027: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000c18: 0c01 |002a: move-result-object v1
-000c1a: 6e20 3500 9100 |002b: invoke-virtual {v1, v9}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000c20: 0c01 |002e: move-result-object v1
-000c22: 1a02 5900 |002f: const-string v2, "]" // string@0059
-000c26: 6e20 3600 2100 |0031: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000c2c: 0c01 |0034: move-result-object v1
-000c2e: 6e10 3700 0100 |0035: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000c34: 0c01 |0038: move-result-object v1
-000c36: 6e20 2900 1000 |0039: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000c3c: 6200 0200 |003c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000c40: 2201 1000 |003e: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-000c44: 7010 3000 0100 |0040: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000c4a: 6e20 3600 4100 |0043: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000c50: 0c01 |0046: move-result-object v1
-000c52: 1a02 0100 |0047: const-string v2, " " // string@0001
-000c56: 6e20 3600 2100 |0049: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000c5c: 0c01 |004c: move-result-object v1
-000c5e: 6e20 3500 5100 |004d: invoke-virtual {v1, v5}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-000c64: 0c01 |0050: move-result-object v1
-000c66: 6e10 3700 0100 |0051: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000c6c: 0c01 |0054: move-result-object v1
-000c6e: 6e20 2900 1000 |0055: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000c74: 7120 0800 7600 |0058: invoke-static {v6, v7}, Linvokecustom/InvokeCustom;.checkStaticFieldTest9:(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V // method@0008
-000c7a: 2200 0700 |005b: new-instance v0, Linvokecustom/InvokeCustom; // type@0007
-000c7e: 7010 0100 0000 |005d: invoke-direct {v0}, Linvokecustom/InvokeCustom;.<init>:()V // method@0001
-000c84: 7030 0700 8009 |0060: invoke-direct {v0, v8, v9}, Linvokecustom/InvokeCustom;.checkFieldTest9:(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V // method@0007
-000c8a: fa20 4000 0a00 2700 |0063: invoke-polymorphic {v10, v0}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Linvokecustom/InvokeCustom;)V // method@0040, proto@0027
-000c92: 1230 |0067: const/4 v0, #int 3 // #3
-000c94: fa20 4000 0b00 0500 |0068: invoke-polymorphic {v11, v0}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (I)Linvokecustom/InvokeCustom; // method@0040, proto@0005
-000c9c: 0c00 |006c: move-result-object v0
-000c9e: fa20 3b00 0c00 2700 |006d: invoke-polymorphic {v12, v0}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (Linvokecustom/InvokeCustom;)V // method@003b, proto@0027
-000ca6: 7100 4600 0000 |0071: invoke-static {}, Ljava/lang/invoke/MethodHandles;.lookup:()Ljava/lang/invoke/MethodHandles$Lookup; // method@0046
-000cac: 0c00 |0074: move-result-object v0
-000cae: 6e10 4500 0000 |0075: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@0045
-000cb4: 0c01 |0078: move-result-object v1
-000cb6: 6e40 4400 1054 |0079: invoke-virtual {v0, v1, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@0044
-000cbc: 0c00 |007c: move-result-object v0
-000cbe: 2201 1400 |007d: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0014
-000cc2: 6e20 3a00 5000 |007f: invoke-virtual {v0, v5}, Ljava/lang/invoke/MethodHandle;.asType:(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@003a
-000cc8: 0c00 |0082: move-result-object v0
-000cca: 7020 3800 0100 |0083: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0038
-000cd0: 1101 |0086: return-object v1
- catches : (none)
- positions :
- 0x0000 line=170
- 0x003c line=172
- 0x0058 line=175
- 0x005b line=176
- 0x0060 line=177
- 0x0063 line=180
- 0x0067 line=182
- 0x006d line=183
- 0x0071 line=185
- 0x0075 line=186
- 0x007d line=187
- locals :
- 0x0000 - 0x0087 reg=3 (null) Ljava/lang/invoke/MethodHandles$Lookup;
- 0x0000 - 0x0087 reg=4 (null) Ljava/lang/String;
- 0x0000 - 0x0087 reg=5 (null) Ljava/lang/invoke/MethodType;
- 0x0000 - 0x0087 reg=6 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=7 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=8 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=9 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=10 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=11 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0087 reg=12 (null) Ljava/lang/invoke/MethodHandle;
-
- #7 : (in Linvokecustom/InvokeCustom;)
- name : 'checkFieldTest9'
- type : '(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V'
- access : 0x0002 (PRIVATE)
+ insns size : 14 16-bit code units
+001b30: |[001b30] TestBadBootstrapArguments.bsmReturningTestersConstantCallsite:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;
+001b40: 2200 0700 |0000: new-instance v0, LTestBadBootstrapArguments$TestersConstantCallSite; // type@0007
+001b44: 6e10 dc00 0200 |0002: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001b4a: 0c01 |0005: move-result-object v1
+001b4c: 6e40 d800 1243 |0006: invoke-virtual {v2, v1, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001b52: 0c01 |0009: move-result-object v1
+001b54: 7020 0800 1000 |000a: invoke-direct {v0, v1}, LTestBadBootstrapArguments$TestersConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0008
+001b5a: 1100 |000d: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=455
+ locals :
+ 0x0000 - 0x000e reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x000e reg=3 name Ljava/lang/String;
+ 0x0000 - 0x000e reg=4 type Ljava/lang/invoke/MethodType;
+
+ #8 : (in LTestBadBootstrapArguments;)
+ name : 'bsmReturningVoid'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V'
+ access : 0x0008 (STATIC)
code -
- registers : 9
+ registers : 5
ins : 3
- outs : 3
- insns size : 82 16-bit code units
-000cd4: |[000cd4] invokecustom.InvokeCustom.checkFieldTest9:(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
-000ce4: 1405 0ff0 6a20 |0000: const v5, #float 1.99e-19 // #206af00f
-000cea: fa20 4000 6700 0100 |0003: invoke-polymorphic {v7, v6}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Linvokecustom/InvokeCustom;)F // method@0040, proto@0001
-000cf2: 0a00 |0007: move-result v0
-000cf4: fa30 4000 6805 2800 |0008: invoke-polymorphic {v8, v6, v5}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Linvokecustom/InvokeCustom;F)V // method@0040, proto@0028
-000cfc: fa20 4000 6700 0100 |000c: invoke-polymorphic {v7, v6}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Linvokecustom/InvokeCustom;)F // method@0040, proto@0001
-000d04: 0a01 |0010: move-result v1
-000d06: 6202 0200 |0011: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000d0a: 2203 1000 |0013: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-000d0e: 7010 3000 0300 |0015: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000d14: 1a04 6800 |0018: const-string v4, "checkFieldTest9: old " // string@0068
-000d18: 6e20 3600 4300 |001a: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000d1e: 0c03 |001d: move-result-object v3
-000d20: 6e20 3200 0300 |001e: invoke-virtual {v3, v0}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-000d26: 0c00 |0021: move-result-object v0
-000d28: 1a03 0700 |0022: const-string v3, " new " // string@0007
-000d2c: 6e20 3600 3000 |0024: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000d32: 0c00 |0027: move-result-object v0
-000d34: 6e20 3200 1000 |0028: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-000d3a: 0c00 |002b: move-result-object v0
-000d3c: 1a03 0600 |002c: const-string v3, " expected " // string@0006
-000d40: 6e20 3600 3000 |002e: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000d46: 0c00 |0031: move-result-object v0
-000d48: 6e20 3200 5000 |0032: invoke-virtual {v0, v5}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-000d4e: 0c00 |0035: move-result-object v0
-000d50: 1a03 0100 |0036: const-string v3, " " // string@0001
-000d54: 6e20 3600 3000 |0038: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000d5a: 0c00 |003b: move-result-object v0
-000d5c: 6e10 3700 0000 |003c: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000d62: 0c00 |003f: move-result-object v0
-000d64: 6e20 2300 0200 |0040: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@0023
-000d6a: 6202 0200 |0043: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000d6e: 2d00 0105 |0045: cmpl-float v0, v1, v5
-000d72: 3900 0800 |0047: if-nez v0, 004f // +0008
-000d76: 1a00 4400 |0049: const-string v0, "OK" // string@0044
-000d7a: 6e20 2900 0200 |004b: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000d80: 0e00 |004e: return-void
-000d82: 1a00 1100 |004f: const-string v0, "ERROR" // string@0011
-000d86: 28fa |0051: goto 004b // -0006
- catches : (none)
- positions :
- 0x0003 line=120
- 0x0008 line=121
- 0x000c line=122
- 0x0011 line=123
- 0x0043 line=125
- 0x004e line=126
- 0x004f line=125
- locals :
- 0x0000 - 0x0052 reg=6 this Linvokecustom/InvokeCustom;
- 0x0000 - 0x0052 reg=7 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0052 reg=8 (null) Ljava/lang/invoke/MethodHandle;
-
- #8 : (in Linvokecustom/InvokeCustom;)
- name : 'checkStaticFieldTest9'
- type : '(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V'
+ outs : 2
+ insns size : 8 16-bit code units
+001d9c: |[001d9c] TestBadBootstrapArguments.bsmReturningVoid:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V
+001dac: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001db0: 1a01 ed00 |0002: const-string v1, "bsm returning void value." // string@00ed
+001db4: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dba: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=380
+ 0x0007 line=381
+ locals :
+ 0x0000 - 0x0008 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0008 reg=3 name Ljava/lang/String;
+ 0x0000 - 0x0008 reg=4 type Ljava/lang/invoke/MethodType;
+
+ #9 : (in LTestBadBootstrapArguments;)
+ name : 'bsmZBCS'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;'
access : 0x000a (PRIVATE STATIC)
code -
registers : 8
- ins : 2
- outs : 2
- insns size : 80 16-bit code units
-000d88: |[000d88] invokecustom.InvokeCustom.checkStaticFieldTest9:(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
-000d98: 1405 1032 5476 |0000: const v5, #float 1.07596e+33 // #76543210
-000d9e: fa10 4000 0600 0200 |0003: invoke-polymorphic {v6}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, ()I // method@0040, proto@0002
-000da6: 0a00 |0007: move-result v0
-000da8: fa20 4000 5700 2500 |0008: invoke-polymorphic {v7, v5}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (I)V // method@0040, proto@0025
-000db0: fa10 4000 0600 0200 |000c: invoke-polymorphic {v6}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, ()I // method@0040, proto@0002
-000db8: 0a01 |0010: move-result v1
-000dba: 6202 0200 |0011: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000dbe: 2203 1000 |0013: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-000dc2: 7010 3000 0300 |0015: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-000dc8: 1a04 6a00 |0018: const-string v4, "checkStaticFieldTest9: old " // string@006a
-000dcc: 6e20 3600 4300 |001a: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000dd2: 0c03 |001d: move-result-object v3
-000dd4: 6e20 3300 0300 |001e: invoke-virtual {v3, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-000dda: 0c00 |0021: move-result-object v0
-000ddc: 1a03 0700 |0022: const-string v3, " new " // string@0007
-000de0: 6e20 3600 3000 |0024: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000de6: 0c00 |0027: move-result-object v0
-000de8: 6e20 3300 1000 |0028: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-000dee: 0c00 |002b: move-result-object v0
-000df0: 1a03 0600 |002c: const-string v3, " expected " // string@0006
-000df4: 6e20 3600 3000 |002e: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000dfa: 0c00 |0031: move-result-object v0
-000dfc: 6e20 3300 5000 |0032: invoke-virtual {v0, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-000e02: 0c00 |0035: move-result-object v0
-000e04: 1a03 0100 |0036: const-string v3, " " // string@0001
-000e08: 6e20 3600 3000 |0038: invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-000e0e: 0c00 |003b: move-result-object v0
-000e10: 6e10 3700 0000 |003c: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-000e16: 0c00 |003f: move-result-object v0
-000e18: 6e20 2300 0200 |0040: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@0023
-000e1e: 6202 0200 |0043: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000e22: 3351 0800 |0045: if-ne v1, v5, 004d // +0008
-000e26: 1a00 4400 |0047: const-string v0, "OK" // string@0044
-000e2a: 6e20 2900 0200 |0049: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000e30: 0e00 |004c: return-void
-000e32: 1a00 1100 |004d: const-string v0, "ERROR" // string@0011
-000e36: 28fa |004f: goto 0049 // -0006
- catches : (none)
- positions :
- 0x0003 line=107
- 0x0008 line=108
- 0x000c line=109
- 0x0011 line=110
- 0x0043 line=112
- 0x004c line=113
- 0x004d line=112
- locals :
- 0x0000 - 0x0050 reg=6 (null) Ljava/lang/invoke/MethodHandle;
- 0x0000 - 0x0050 reg=7 (null) Ljava/lang/invoke/MethodHandle;
-
- #9 : (in Linvokecustom/InvokeCustom;)
- name : 'lambda$lambdaTest$0'
- type : '(Ljava/lang/String;)Z'
- access : 0x100a (PRIVATE STATIC SYNTHETIC)
+ ins : 7
+ outs : 0
+ insns size : 5 16-bit code units
+001d48: |[001d48] TestBadBootstrapArguments.bsmZBCS:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;
+001d58: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001d5e: 1200 |0003: const/4 v0, #int 0 // #0
+001d60: 1100 |0004: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=227
+ 0x0003 line=228
+ locals :
+ 0x0000 - 0x0005 reg=1 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0005 reg=2 methodName Ljava/lang/String;
+ 0x0000 - 0x0005 reg=3 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0005 reg=4 extraArg0 Z
+ 0x0000 - 0x0005 reg=5 extraArg1 B
+ 0x0000 - 0x0005 reg=6 extraArg2 C
+ 0x0000 - 0x0005 reg=7 extraArg3 S
+
+ #10 : (in LTestBadBootstrapArguments;)
+ name : 'extraArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 3
- ins : 1
+ registers : 2
+ ins : 0
outs : 2
- insns size : 11 16-bit code units
-000e38: |[000e38] invokecustom.InvokeCustom.lambda$lambdaTest$0:(Ljava/lang/String;)Z
-000e48: 1a00 4500 |0000: const-string v0, "One" // string@0045
-000e4c: 6e10 2f00 0200 |0002: invoke-virtual {v2}, Ljava/lang/String;.trim:()Ljava/lang/String; // method@002f
-000e52: 0c01 |0005: move-result-object v1
-000e54: 6e20 2e00 1000 |0006: invoke-virtual {v0, v1}, Ljava/lang/String;.equals:(Ljava/lang/Object;)Z // method@002e
-000e5a: 0a00 |0009: move-result v0
-000e5c: 0f00 |000a: return v0
+ insns size : 8 16-bit code units
+001dbc: |[001dbc] TestBadBootstrapArguments.extraArguments:()V
+001dcc: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001dd0: 1a01 2001 |0002: const-string v1, "extraArguments" // string@0120
+001dd4: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dda: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=192
+ 0x0000 line=158
+ 0x0007 line=159
locals :
- 0x0000 - 0x000b reg=2 (null) Ljava/lang/String;
- #10 : (in Linvokecustom/InvokeCustom;)
- name : 'lambdaTest'
+ #11 : (in LTestBadBootstrapArguments;)
+ name : 'happy'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 3
+ registers : 2
ins : 0
outs : 2
- insns size : 71 16-bit code units
-000e60: |[000e60] invokecustom.InvokeCustom.lambdaTest:()V
-000e70: 1230 |0000: const/4 v0, #int 3 // #3
-000e72: 2300 2500 |0001: new-array v0, v0, [Ljava/lang/String; // type@0025
-000e76: 1201 |0003: const/4 v1, #int 0 // #0
-000e78: 1a02 4900 |0004: const-string v2, "Three" // string@0049
-000e7c: 4d02 0001 |0006: aput-object v2, v0, v1
-000e80: 1211 |0008: const/4 v1, #int 1 // #1
-000e82: 1a02 4500 |0009: const-string v2, "One" // string@0045
-000e86: 4d02 0001 |000b: aput-object v2, v0, v1
-000e8a: 1221 |000d: const/4 v1, #int 2 // #2
-000e8c: 1a02 1600 |000e: const-string v2, "FortyTwo" // string@0016
-000e90: 4d02 0001 |0010: aput-object v2, v0, v1
-000e94: 7110 4700 0000 |0012: invoke-static {v0}, Ljava/util/Arrays;.asList:([Ljava/lang/Object;)Ljava/util/List; // method@0047
-000e9a: 0c01 |0015: move-result-object v1
-000e9c: 7210 4800 0100 |0016: invoke-interface {v1}, Ljava/util/List;.stream:()Ljava/util/stream/Stream; // method@0048
-000ea2: 0c00 |0019: move-result-object v0
-000ea4: fc00 0000 0000 |001a: invoke-custom {}, call_site@0000
-000eaa: 0c02 |001d: move-result-object v2
-000eac: 7220 4a00 2000 |001e: invoke-interface {v0, v2}, Ljava/util/stream/Stream;.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream; // method@004a
-000eb2: 0c00 |0021: move-result-object v0
-000eb4: fc00 0100 0000 |0022: invoke-custom {}, call_site@0001
-000eba: 0c02 |0025: move-result-object v2
-000ebc: 7220 4d00 2000 |0026: invoke-interface {v0, v2}, Ljava/util/stream/Stream;.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream; // method@004d
-000ec2: 0c00 |0029: move-result-object v0
-000ec4: 7210 4b00 0000 |002a: invoke-interface {v0}, Ljava/util/stream/Stream;.findAny:()Ljava/util/Optional; // method@004b
-000eca: 0c00 |002d: move-result-object v0
-000ecc: 1a02 0000 |002e: const-string v2, "" // string@0000
-000ed0: 6e20 4900 2000 |0030: invoke-virtual {v0, v2}, Ljava/util/Optional;.orElse:(Ljava/lang/Object;)Ljava/lang/Object; // method@0049
-000ed6: 0c00 |0033: move-result-object v0
-000ed8: 1f00 0f00 |0034: check-cast v0, Ljava/lang/String; // type@000f
-000edc: 7210 4800 0100 |0036: invoke-interface {v1}, Ljava/util/List;.stream:()Ljava/util/stream/Stream; // method@0048
-000ee2: 0c00 |0039: move-result-object v0
-000ee4: 6201 0200 |003a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000ee8: 6e10 2c00 0100 |003c: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@002c
-000eee: fc10 0200 0100 |003f: invoke-custom {v1}, call_site@0002
-000ef4: 0c01 |0042: move-result-object v1
-000ef6: 7220 4c00 1000 |0043: invoke-interface {v0, v1}, Ljava/util/stream/Stream;.forEach:(Ljava/util/function/Consumer;)V // method@004c
-000efc: 0e00 |0046: return-void
- catches : (none)
- positions :
- 0x0000 line=191
- 0x0016 line=192
- 0x0026 line=193
- 0x0036 line=194
- 0x0046 line=195
- locals :
-
- #11 : (in Linvokecustom/InvokeCustom;)
- name : 'main'
- type : '([Ljava/lang/String;)V'
- access : 0x0009 (PUBLIC STATIC)
+ insns size : 8 16-bit code units
+001ddc: |[001ddc] TestBadBootstrapArguments.happy:()V
+001dec: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001df0: 1a01 3d01 |0002: const-string v1, "happy" // string@013d
+001df4: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dfa: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=74
+ 0x0007 line=75
+ locals :
+
+ #12 : (in LTestBadBootstrapArguments;)
+ name : 'integerReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 1
- ins : 1
+ registers : 0
+ ins : 0
outs : 0
- insns size : 28 16-bit code units
-000f00: |[000f00] invokecustom.InvokeCustom.main:([Ljava/lang/String;)V
-000f10: 7100 1700 0000 |0000: invoke-static {}, Linvokecustom/InvokeCustom;.test1:()V // method@0017
-000f16: 7100 1800 0000 |0003: invoke-static {}, Linvokecustom/InvokeCustom;.test2:()V // method@0018
-000f1c: 7100 1900 0000 |0006: invoke-static {}, Linvokecustom/InvokeCustom;.test3:()V // method@0019
-000f22: 7100 1a00 0000 |0009: invoke-static {}, Linvokecustom/InvokeCustom;.test4:()V // method@001a
-000f28: 7100 1b00 0000 |000c: invoke-static {}, Linvokecustom/InvokeCustom;.test5:()V // method@001b
-000f2e: 7100 1c00 0000 |000f: invoke-static {}, Linvokecustom/InvokeCustom;.test6:()V // method@001c
-000f34: 7100 1d00 0000 |0012: invoke-static {}, Linvokecustom/InvokeCustom;.test7:()V // method@001d
-000f3a: 7100 1e00 0000 |0015: invoke-static {}, Linvokecustom/InvokeCustom;.test8:()V // method@001e
-000f40: 7100 1f00 0000 |0018: invoke-static {}, Linvokecustom/InvokeCustom;.test9:()V // method@001f
-000f46: 0e00 |001b: return-void
+ insns size : 4 16-bit code units
+001dfc: |[001dfc] TestBadBootstrapArguments.integerReturnType:()V
+001e0c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e12: 0e00 |0003: return-void
catches : (none)
positions :
+ 0x0000 line=444
+ 0x0003 line=445
locals :
- #12 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest1'
+ #13 : (in LTestBadBootstrapArguments;)
+ name : 'invokeBoxingArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e14: |[001e14] TestBadBootstrapArguments.invokeBoxingArguments:()V
+001e24: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e2a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=344
+ 0x0003 line=345
+ locals :
+
+ #14 : (in LTestBadBootstrapArguments;)
+ name : 'invokeExtraArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e2c: |[001e2c] TestBadBootstrapArguments.invokeExtraArguments:()V
+001e3c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e42: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=154
+ 0x0003 line=155
+ locals :
+
+ #15 : (in LTestBadBootstrapArguments;)
+ name : 'invokeHappy'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e44: |[001e44] TestBadBootstrapArguments.invokeHappy:()V
+001e54: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e5a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=70
+ 0x0003 line=71
+ locals :
+
+ #16 : (in LTestBadBootstrapArguments;)
+ name : 'invokeIntegerReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e5c: |[001e5c] TestBadBootstrapArguments.invokeIntegerReturnType:()V
+001e6c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e72: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=440
+ 0x0003 line=441
+ locals :
+
+ #17 : (in LTestBadBootstrapArguments;)
+ name : 'invokeMissingParameterTypes'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e74: |[001e74] TestBadBootstrapArguments.invokeMissingParameterTypes:()V
+001e84: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e8a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=124
+ 0x0003 line=125
+ locals :
+
+ #18 : (in LTestBadBootstrapArguments;)
+ name : 'invokeNarrowArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001e8c: |[001e8c] TestBadBootstrapArguments.invokeNarrowArguments:()V
+001e9c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001ea2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=256
+ 0x0003 line=257
+ locals :
+
+ #19 : (in LTestBadBootstrapArguments;)
+ name : 'invokeObjectReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001ea4: |[001ea4] TestBadBootstrapArguments.invokeObjectReturnType:()V
+001eb4: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001eba: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=417
+ 0x0003 line=418
+ locals :
+
+ #20 : (in LTestBadBootstrapArguments;)
+ name : 'invokeViaCustomCallSiteClass'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001ebc: |[001ebc] TestBadBootstrapArguments.invokeViaCustomCallSiteClass:()V
+001ecc: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001ed2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=469
+ 0x0003 line=470
+ locals :
+
+ #21 : (in LTestBadBootstrapArguments;)
+ name : 'invokeVoidReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001ed4: |[001ed4] TestBadBootstrapArguments.invokeVoidReturnType:()V
+001ee4: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001eea: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=394
+ 0x0003 line=395
+ locals :
+
+ #22 : (in LTestBadBootstrapArguments;)
+ name : 'invokeWideningArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001eec: |[001eec] TestBadBootstrapArguments.invokeWideningArguments:()V
+001efc: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f02: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=300
+ 0x0003 line=301
+ locals :
+
+ #23 : (in LTestBadBootstrapArguments;)
+ name : 'invokeWideningBoxingArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f04: |[001f04] TestBadBootstrapArguments.invokeWideningBoxingArguments:()V
+001f14: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f1a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=372
+ 0x0003 line=373
+ locals :
+
+ #24 : (in LTestBadBootstrapArguments;)
+ name : 'invokeWrongArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f1c: |[001f1c] TestBadBootstrapArguments.invokeWrongArguments:()V
+001f2c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f32: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=182
+ 0x0003 line=183
+ locals :
+
+ #25 : (in LTestBadBootstrapArguments;)
+ name : 'invokeWrongArgumentsAgain'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f34: |[001f34] TestBadBootstrapArguments.invokeWrongArgumentsAgain:()V
+001f44: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f4a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=210
+ 0x0003 line=211
+ locals :
+
+ #26 : (in LTestBadBootstrapArguments;)
+ name : 'invokeWrongParameterTypes'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f4c: |[001f4c] TestBadBootstrapArguments.invokeWrongParameterTypes:()V
+001f5c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f62: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=98
+ 0x0003 line=99
+ locals :
+
+ #27 : (in LTestBadBootstrapArguments;)
+ name : 'missingParameterTypes'
type : '()V'
access : 0x000a (PRIVATE STATIC)
code -
@@ -681,71 +1684,55 @@ Class #1 -
ins : 0
outs : 2
insns size : 8 16-bit code units
-000f48: |[000f48] invokecustom.InvokeCustom.targetMethodTest1:()V
-000f58: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000f5c: 1a01 1700 |0002: const-string v1, "Hello World!" // string@0017
-000f60: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000f66: 0e00 |0007: return-void
+001f64: |[001f64] TestBadBootstrapArguments.missingParameterTypes:()V
+001f74: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001f78: 1a01 8c01 |0002: const-string v1, "missingParameterTypes" // string@018c
+001f7c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001f82: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=45
- 0x0007 line=46
+ 0x0000 line=128
+ 0x0007 line=129
locals :
- #13 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest2'
- type : '(ZBCSIFJDLjava/lang/String;)V'
+ #28 : (in LTestBadBootstrapArguments;)
+ name : 'narrowArguments'
+ type : '()V'
access : 0x000a (PRIVATE STATIC)
code -
- registers : 13
- ins : 11
- outs : 3
- insns size : 46 16-bit code units
-000f68: |[000f68] invokecustom.InvokeCustom.targetMethodTest2:(ZBCSIFJDLjava/lang/String;)V
-000f78: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000f7c: 6e20 2a00 2000 |0002: invoke-virtual {v0, v2}, Ljava/io/PrintStream;.println:(Z)V // method@002a
-000f82: 6200 0200 |0005: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000f86: 6e20 2700 3000 |0007: invoke-virtual {v0, v3}, Ljava/io/PrintStream;.println:(I)V // method@0027
-000f8c: 6200 0200 |000a: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000f90: 6e20 2400 4000 |000c: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.println:(C)V // method@0024
-000f96: 6200 0200 |000f: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000f9a: 6e20 2700 5000 |0011: invoke-virtual {v0, v5}, Ljava/io/PrintStream;.println:(I)V // method@0027
-000fa0: 6200 0200 |0014: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fa4: 6e20 2700 6000 |0016: invoke-virtual {v0, v6}, Ljava/io/PrintStream;.println:(I)V // method@0027
-000faa: 6200 0200 |0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fae: 6e20 2600 7000 |001b: invoke-virtual {v0, v7}, Ljava/io/PrintStream;.println:(F)V // method@0026
-000fb4: 6200 0200 |001e: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fb8: 6e30 2800 8009 |0020: invoke-virtual {v0, v8, v9}, Ljava/io/PrintStream;.println:(J)V // method@0028
-000fbe: 6200 0200 |0023: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fc2: 6e30 2500 a00b |0025: invoke-virtual {v0, v10, v11}, Ljava/io/PrintStream;.println:(D)V // method@0025
-000fc8: 6200 0200 |0028: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fcc: 6e20 2900 c000 |002a: invoke-virtual {v0, v12}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000fd2: 0e00 |002d: return-void
- catches : (none)
- positions :
- 0x0000 line=50
- 0x0005 line=51
- 0x000a line=52
- 0x000f line=53
- 0x0014 line=54
- 0x0019 line=55
- 0x001e line=56
- 0x0023 line=57
- 0x0028 line=58
- 0x002d line=59
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f84: |[001f84] TestBadBootstrapArguments.narrowArguments:()V
+001f94: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f9a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=260
+ 0x0003 line=261
locals :
- 0x0000 - 0x002e reg=2 (null) Z
- 0x0000 - 0x002e reg=3 (null) B
- 0x0000 - 0x002e reg=4 (null) C
- 0x0000 - 0x002e reg=5 (null) S
- 0x0000 - 0x002e reg=6 (null) I
- 0x0000 - 0x002e reg=7 (null) F
- 0x0000 - 0x002e reg=8 (null) J
- 0x0000 - 0x002e reg=10 (null) D
- 0x0000 - 0x002e reg=12 (null) Ljava/lang/String;
- #14 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest3'
+ #29 : (in LTestBadBootstrapArguments;)
+ name : 'objectReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+001f9c: |[001f9c] TestBadBootstrapArguments.objectReturnType:()V
+001fac: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001fb2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=421
+ 0x0003 line=422
+ locals :
+
+ #30 : (in LTestBadBootstrapArguments;)
+ name : 'sayHello'
type : '()V'
access : 0x000a (PRIVATE STATIC)
code -
@@ -753,237 +1740,459 @@ Class #1 -
ins : 0
outs : 2
insns size : 8 16-bit code units
-000fd4: |[000fd4] invokecustom.InvokeCustom.targetMethodTest3:()V
-000fe4: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-000fe8: 1a01 8800 |0002: const-string v1, "targetMethodTest3 from InvokeCustom" // string@0088
-000fec: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-000ff2: 0e00 |0007: return-void
+001fb4: |[001fb4] TestBadBootstrapArguments.sayHello:()V
+001fc4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001fc8: 1a01 2d00 |0002: const-string v1, "Hello!" // string@002d
+001fcc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001fd2: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=62
- 0x0007 line=63
+ 0x0000 line=473
+ 0x0007 line=474
locals :
- #15 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest5'
- type : '(III)I'
- access : 0x0009 (PUBLIC STATIC)
+ #31 : (in LTestBadBootstrapArguments;)
+ name : 'test'
+ type : '()V'
+ access : 0x0008 (STATIC)
code -
- registers : 7
- ins : 3
+ registers : 3
+ ins : 0
outs : 2
- insns size : 83 16-bit code units
-000ff4: |[000ff4] invokecustom.InvokeCustom.targetMethodTest5:(III)I
-001004: 9000 0405 |0000: add-int v0, v4, v5
-001008: 6201 0200 |0002: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-00100c: 2202 1000 |0004: new-instance v2, Ljava/lang/StringBuilder; // type@0010
-001010: 7010 3000 0200 |0006: invoke-direct {v2}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-001016: 1a03 8d00 |0009: const-string v3, "targetMethodTest5 " // string@008d
-00101a: 6e20 3600 3200 |000b: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001020: 0c02 |000e: move-result-object v2
-001022: 6e20 3300 4200 |000f: invoke-virtual {v2, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-001028: 0c02 |0012: move-result-object v2
-00102a: 1a03 0400 |0013: const-string v3, " + " // string@0004
-00102e: 6e20 3600 3200 |0015: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001034: 0c02 |0018: move-result-object v2
-001036: 6e20 3300 5200 |0019: invoke-virtual {v2, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-00103c: 0c02 |001c: move-result-object v2
-00103e: 1a03 0500 |001d: const-string v3, " = " // string@0005
-001042: 6e20 3600 3200 |001f: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001048: 0c02 |0022: move-result-object v2
-00104a: 6e20 3300 0200 |0023: invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-001050: 0c02 |0026: move-result-object v2
-001052: 6e10 3700 0200 |0027: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-001058: 0c02 |002a: move-result-object v2
-00105a: 6e20 2900 2100 |002b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001060: 3260 2400 |002e: if-eq v0, v6, 0052 // +0024
-001064: 6201 0200 |0030: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001068: 2202 1000 |0032: new-instance v2, Ljava/lang/StringBuilder; // type@0010
-00106c: 7010 3000 0200 |0034: invoke-direct {v2}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-001072: 1a03 1400 |0037: const-string v3, "Failed " // string@0014
-001076: 6e20 3600 3200 |0039: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-00107c: 0c02 |003c: move-result-object v2
-00107e: 6e20 3300 0200 |003d: invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-001084: 0c02 |0040: move-result-object v2
-001086: 1a03 0200 |0041: const-string v3, " != " // string@0002
-00108a: 6e20 3600 3200 |0043: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001090: 0c02 |0046: move-result-object v2
-001092: 6e20 3300 6200 |0047: invoke-virtual {v2, v6}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-001098: 0c02 |004a: move-result-object v2
-00109a: 6e10 3700 0200 |004b: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-0010a0: 0c02 |004e: move-result-object v2
-0010a2: 6e20 2900 2100 |004f: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0010a8: 0f00 |0052: return v0
- catches : (none)
- positions :
- 0x0000 line=72
- 0x0002 line=73
- 0x002e line=74
- 0x0030 line=75
- 0x0052 line=77
- locals :
- 0x0000 - 0x0053 reg=4 (null) I
- 0x0000 - 0x0053 reg=5 (null) I
- 0x0000 - 0x0053 reg=6 (null) I
-
- #16 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest6'
- type : '(JJJ)J'
- access : 0x0009 (PUBLIC STATIC)
+ insns size : 529 16-bit code units
+001fd4: |[001fd4] TestBadBootstrapArguments.test:()V
+001fe4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001fe8: 1a01 8f00 |0002: const-string v1, "TestBadBootstrapArguments" // string@008f
+001fec: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ff2: fc00 0000 0000 |0007: invoke-custom {}, call_site@0000
+001ff8: fc00 0100 0000 |000a: invoke-custom {}, call_site@0001
+001ffe: 7100 0b00 0000 |000d: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002004: 2812 |0010: goto 0022 // +0012
+002006: 0d00 |0011: move-exception v0
+002008: 6201 1300 |0012: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00200c: 1a02 6101 |0014: const-string v2, "invokeWrongParameterTypes => " // string@0161
+002010: 6e20 b000 2100 |0016: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002016: 6201 1300 |0019: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00201a: 6e10 c000 0000 |001b: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002020: 0c02 |001e: move-result-object v2
+002022: 6e20 b200 2100 |001f: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002028: fc00 0200 0000 |0022: invoke-custom {}, call_site@0002
+00202e: 7100 0b00 0000 |0025: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002034: 2812 |0028: goto 003a // +0012
+002036: 0d00 |0029: move-exception v0
+002038: 6201 1300 |002a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00203c: 1a02 5101 |002c: const-string v2, "invokeMissingParameterTypes => " // string@0151
+002040: 6e20 b000 2100 |002e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002046: 6201 1300 |0031: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00204a: 6e10 c000 0000 |0033: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002050: 0c02 |0036: move-result-object v2
+002052: 6e20 b200 2100 |0037: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002058: fc00 0300 0000 |003a: invoke-custom {}, call_site@0003
+00205e: 7100 0b00 0000 |003d: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002064: 2833 |0040: goto 0073 // +0033
+002066: 0d00 |0041: move-exception v0
+002068: 1c01 3a00 |0042: const-class v1, Ljava/lang/invoke/WrongMethodTypeException; // type@003a
+00206c: 6e10 b600 0000 |0044: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002072: 0c02 |0047: move-result-object v2
+002074: 6e10 c000 0200 |0048: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00207a: 0c02 |004b: move-result-object v2
+00207c: 7120 0a00 2100 |004c: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+002082: 6201 1300 |004f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002086: 1a02 4c01 |0051: const-string v2, "invokeExtraArguments => " // string@014c
+00208a: 6e20 b000 2100 |0053: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002090: 6201 1300 |0056: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002094: 6e10 c000 0000 |0058: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00209a: 0c02 |005b: move-result-object v2
+00209c: 6e20 af00 2100 |005c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0020a2: 6201 1300 |005f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020a6: 1a02 0200 |0061: const-string v2, " => " // string@0002
+0020aa: 6e20 b000 2100 |0063: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0020b0: 6201 1300 |0066: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020b4: 6e10 b600 0000 |0068: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0020ba: 0c02 |006b: move-result-object v2
+0020bc: 6e10 c000 0200 |006c: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0020c2: 0c02 |006f: move-result-object v2
+0020c4: 6e20 b200 2100 |0070: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0020ca: fc00 0400 0000 |0073: invoke-custom {}, call_site@0004
+0020d0: 7100 0b00 0000 |0076: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0020d6: 2833 |0079: goto 00ac // +0033
+0020d8: 0d00 |007a: move-exception v0
+0020da: 1c01 2200 |007b: const-class v1, Ljava/lang/ClassCastException; // type@0022
+0020de: 6e10 b600 0000 |007d: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0020e4: 0c02 |0080: move-result-object v2
+0020e6: 6e10 c000 0200 |0081: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0020ec: 0c02 |0084: move-result-object v2
+0020ee: 7120 0a00 2100 |0085: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+0020f4: 6201 1300 |0088: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020f8: 1a02 5d01 |008a: const-string v2, "invokeWrongArguments => " // string@015d
+0020fc: 6e20 b000 2100 |008c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002102: 6201 1300 |008f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002106: 6e10 c000 0000 |0091: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00210c: 0c02 |0094: move-result-object v2
+00210e: 6e20 af00 2100 |0095: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002114: 6201 1300 |0098: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002118: 1a02 0200 |009a: const-string v2, " => " // string@0002
+00211c: 6e20 b000 2100 |009c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002122: 6201 1300 |009f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002126: 6e10 b600 0000 |00a1: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00212c: 0c02 |00a4: move-result-object v2
+00212e: 6e10 c000 0200 |00a5: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002134: 0c02 |00a8: move-result-object v2
+002136: 6e20 b200 2100 |00a9: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+00213c: fc00 0500 0000 |00ac: invoke-custom {}, call_site@0005
+002142: 7100 0b00 0000 |00af: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002148: 2833 |00b2: goto 00e5 // +0033
+00214a: 0d00 |00b3: move-exception v0
+00214c: 1c01 2200 |00b4: const-class v1, Ljava/lang/ClassCastException; // type@0022
+002150: 6e10 b600 0000 |00b6: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002156: 0c02 |00b9: move-result-object v2
+002158: 6e10 c000 0200 |00ba: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00215e: 0c02 |00bd: move-result-object v2
+002160: 7120 0a00 2100 |00be: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+002166: 6201 1300 |00c1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00216a: 1a02 5d01 |00c3: const-string v2, "invokeWrongArguments => " // string@015d
+00216e: 6e20 b000 2100 |00c5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002174: 6201 1300 |00c8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002178: 6e10 c000 0000 |00ca: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00217e: 0c02 |00cd: move-result-object v2
+002180: 6e20 af00 2100 |00ce: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002186: 6201 1300 |00d1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00218a: 1a02 0200 |00d3: const-string v2, " => " // string@0002
+00218e: 6e20 b000 2100 |00d5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002194: 6201 1300 |00d8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002198: 6e10 b600 0000 |00da: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00219e: 0c02 |00dd: move-result-object v2
+0021a0: 6e10 c000 0200 |00de: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021a6: 0c02 |00e1: move-result-object v2
+0021a8: 6e20 b200 2100 |00e2: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0021ae: fc00 0600 0000 |00e5: invoke-custom {}, call_site@0006
+0021b4: 7100 0b00 0000 |00e8: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0021ba: 2833 |00eb: goto 011e // +0033
+0021bc: 0d00 |00ec: move-exception v0
+0021be: 1c01 2200 |00ed: const-class v1, Ljava/lang/ClassCastException; // type@0022
+0021c2: 6e10 b600 0000 |00ef: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0021c8: 0c02 |00f2: move-result-object v2
+0021ca: 6e10 c000 0200 |00f3: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021d0: 0c02 |00f6: move-result-object v2
+0021d2: 7120 0a00 2100 |00f7: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+0021d8: 6201 1300 |00fa: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021dc: 1a02 5f01 |00fc: const-string v2, "invokeWrongArgumentsAgain => " // string@015f
+0021e0: 6e20 b000 2100 |00fe: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0021e6: 6201 1300 |0101: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021ea: 6e10 c000 0000 |0103: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021f0: 0c02 |0106: move-result-object v2
+0021f2: 6e20 af00 2100 |0107: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0021f8: 6201 1300 |010a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021fc: 1a02 0200 |010c: const-string v2, " => " // string@0002
+002200: 6e20 b000 2100 |010e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002206: 6201 1300 |0111: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00220a: 6e10 b600 0000 |0113: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002210: 0c02 |0116: move-result-object v2
+002212: 6e10 c000 0200 |0117: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002218: 0c02 |011a: move-result-object v2
+00221a: 6e20 b200 2100 |011b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002220: fc00 0700 0000 |011e: invoke-custom {}, call_site@0007
+002226: 7100 0b00 0000 |0121: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+00222c: 2833 |0124: goto 0157 // +0033
+00222e: 0d00 |0125: move-exception v0
+002230: 1c01 2200 |0126: const-class v1, Ljava/lang/ClassCastException; // type@0022
+002234: 6e10 b600 0000 |0128: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00223a: 0c02 |012b: move-result-object v2
+00223c: 6e10 c000 0200 |012c: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002242: 0c02 |012f: move-result-object v2
+002244: 7120 0a00 2100 |0130: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+00224a: 6201 1300 |0133: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00224e: 1a02 5301 |0135: const-string v2, "invokeNarrowArguments => " // string@0153
+002252: 6e20 b000 2100 |0137: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002258: 6201 1300 |013a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00225c: 6e10 c000 0000 |013c: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002262: 0c02 |013f: move-result-object v2
+002264: 6e20 af00 2100 |0140: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+00226a: 6201 1300 |0143: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00226e: 1a02 0200 |0145: const-string v2, " => " // string@0002
+002272: 6e20 b000 2100 |0147: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002278: 6201 1300 |014a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00227c: 6e10 b600 0000 |014c: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002282: 0c02 |014f: move-result-object v2
+002284: 6e10 c000 0200 |0150: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00228a: 0c02 |0153: move-result-object v2
+00228c: 6e20 b200 2100 |0154: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002292: fc00 0800 0000 |0157: invoke-custom {}, call_site@0008
+002298: fc00 0900 0000 |015a: invoke-custom {}, call_site@0009
+00229e: fc00 0a00 0000 |015d: invoke-custom {}, call_site@000a
+0022a4: 7100 0b00 0000 |0160: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0022aa: 2826 |0163: goto 0189 // +0026
+0022ac: 0d00 |0164: move-exception v0
+0022ae: 6201 1300 |0165: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022b2: 1a02 5b01 |0167: const-string v2, "invokeWideningBoxingArguments => " // string@015b
+0022b6: 6e20 b000 2100 |0169: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0022bc: 6201 1300 |016c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022c0: 6e10 c000 0000 |016e: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0022c6: 0c02 |0171: move-result-object v2
+0022c8: 6e20 af00 2100 |0172: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0022ce: 6201 1300 |0175: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022d2: 1a02 0200 |0177: const-string v2, " => " // string@0002
+0022d6: 6e20 b000 2100 |0179: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0022dc: 6201 1300 |017c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022e0: 6e10 b600 0000 |017e: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0022e6: 0c02 |0181: move-result-object v2
+0022e8: 6e10 c000 0200 |0182: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0022ee: 0c02 |0185: move-result-object v2
+0022f0: 6e20 b200 2100 |0186: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0022f6: fc00 0b00 0000 |0189: invoke-custom {}, call_site@000b
+0022fc: 7100 0b00 0000 |018c: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002302: 2826 |018f: goto 01b5 // +0026
+002304: 0d00 |0190: move-exception v0
+002306: 6201 1300 |0191: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00230a: 1a02 5801 |0193: const-string v2, "invokeVoidReturnType() => " // string@0158
+00230e: 6e20 b000 2100 |0195: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002314: 6201 1300 |0198: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002318: 6e10 c000 0000 |019a: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00231e: 0c02 |019d: move-result-object v2
+002320: 6e20 af00 2100 |019e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002326: 6201 1300 |01a1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00232a: 1a02 0200 |01a3: const-string v2, " => " // string@0002
+00232e: 6e20 b000 2100 |01a5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002334: 6201 1300 |01a8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002338: 6e10 b600 0000 |01aa: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00233e: 0c02 |01ad: move-result-object v2
+002340: 6e10 c000 0200 |01ae: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002346: 0c02 |01b1: move-result-object v2
+002348: 6e20 b200 2100 |01b2: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+00234e: fc00 0c00 0000 |01b5: invoke-custom {}, call_site@000c
+002354: 7100 0b00 0000 |01b8: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+00235a: 2826 |01bb: goto 01e1 // +0026
+00235c: 0d00 |01bc: move-exception v0
+00235e: 6201 1300 |01bd: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002362: 1a02 5501 |01bf: const-string v2, "invokeObjectReturnType() => " // string@0155
+002366: 6e20 b000 2100 |01c1: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00236c: 6201 1300 |01c4: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002370: 6e10 c000 0000 |01c6: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002376: 0c02 |01c9: move-result-object v2
+002378: 6e20 af00 2100 |01ca: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+00237e: 6201 1300 |01cd: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002382: 1a02 0200 |01cf: const-string v2, " => " // string@0002
+002386: 6e20 b000 2100 |01d1: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00238c: 6201 1300 |01d4: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002390: 6e10 b600 0000 |01d6: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002396: 0c02 |01d9: move-result-object v2
+002398: 6e10 c000 0200 |01da: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00239e: 0c02 |01dd: move-result-object v2
+0023a0: 6e20 b200 2100 |01de: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0023a6: fc00 0d00 0000 |01e1: invoke-custom {}, call_site@000d
+0023ac: 7100 0b00 0000 |01e4: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0023b2: 2826 |01e7: goto 020d // +0026
+0023b4: 0d00 |01e8: move-exception v0
+0023b6: 6201 1300 |01e9: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023ba: 1a02 4f01 |01eb: const-string v2, "invokeIntegerReturnType() => " // string@014f
+0023be: 6e20 b000 2100 |01ed: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0023c4: 6201 1300 |01f0: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023c8: 6e10 c000 0000 |01f2: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0023ce: 0c02 |01f5: move-result-object v2
+0023d0: 6e20 af00 2100 |01f6: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0023d6: 6201 1300 |01f9: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023da: 1a02 0200 |01fb: const-string v2, " => " // string@0002
+0023de: 6e20 b000 2100 |01fd: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0023e4: 6201 1300 |0200: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023e8: 6e10 b600 0000 |0202: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0023ee: 0c02 |0205: move-result-object v2
+0023f0: 6e10 c000 0200 |0206: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0023f6: 0c02 |0209: move-result-object v2
+0023f8: 6e20 b200 2100 |020a: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0023fe: fc00 0e00 0000 |020d: invoke-custom {}, call_site@000e
+002404: 0e00 |0210: return-void
+ catches : 11
+ 0x000a - 0x0010
+ Ljava/lang/NoSuchMethodError; -> 0x0011
+ 0x0022 - 0x0028
+ Ljava/lang/NoSuchMethodError; -> 0x0029
+ 0x003a - 0x0040
+ Ljava/lang/BootstrapMethodError; -> 0x0041
+ 0x0073 - 0x0079
+ Ljava/lang/BootstrapMethodError; -> 0x007a
+ 0x00ac - 0x00b2
+ Ljava/lang/BootstrapMethodError; -> 0x00b3
+ 0x00e5 - 0x00eb
+ Ljava/lang/BootstrapMethodError; -> 0x00ec
+ 0x011e - 0x0124
+ Ljava/lang/BootstrapMethodError; -> 0x0125
+ 0x015d - 0x0163
+ Ljava/lang/BootstrapMethodError; -> 0x0164
+ 0x0189 - 0x018f
+ Ljava/lang/BootstrapMethodError; -> 0x0190
+ 0x01b5 - 0x01bb
+ Ljava/lang/BootstrapMethodError; -> 0x01bc
+ 0x01e1 - 0x01e7
+ Ljava/lang/BootstrapMethodError; -> 0x01e8
+ positions :
+ 0x0000 line=477
+ 0x0007 line=478
+ 0x000a line=480
+ 0x000d line=481
+ 0x0010 line=485
+ 0x0011 line=482
+ 0x0012 line=483
+ 0x0019 line=484
+ 0x0022 line=487
+ 0x0025 line=488
+ 0x0028 line=492
+ 0x0029 line=489
+ 0x002a line=490
+ 0x0031 line=491
+ 0x003a line=494
+ 0x003d line=495
+ 0x0040 line=502
+ 0x0041 line=496
+ 0x0042 line=497
+ 0x004f line=498
+ 0x0056 line=499
+ 0x005f line=500
+ 0x0066 line=501
+ 0x0073 line=504
+ 0x0076 line=505
+ 0x0079 line=512
+ 0x007a line=506
+ 0x007b line=507
+ 0x0088 line=508
+ 0x008f line=509
+ 0x0098 line=510
+ 0x009f line=511
+ 0x00ac line=514
+ 0x00af line=515
+ 0x00b2 line=522
+ 0x00b3 line=516
+ 0x00b4 line=517
+ 0x00c1 line=518
+ 0x00c8 line=519
+ 0x00d1 line=520
+ 0x00d8 line=521
+ 0x00e5 line=524
+ 0x00e8 line=525
+ 0x00eb line=532
+ 0x00ec line=526
+ 0x00ed line=527
+ 0x00fa line=528
+ 0x0101 line=529
+ 0x010a line=530
+ 0x0111 line=531
+ 0x011e line=534
+ 0x0121 line=535
+ 0x0124 line=542
+ 0x0125 line=536
+ 0x0126 line=537
+ 0x0133 line=538
+ 0x013a line=539
+ 0x0143 line=540
+ 0x014a line=541
+ 0x0157 line=543
+ 0x015a line=544
+ 0x015d line=546
+ 0x0160 line=547
+ 0x0163 line=553
+ 0x0164 line=548
+ 0x0165 line=549
+ 0x016c line=550
+ 0x0175 line=551
+ 0x017c line=552
+ 0x0189 line=555
+ 0x018c line=556
+ 0x018f line=562
+ 0x0190 line=557
+ 0x0191 line=558
+ 0x0198 line=559
+ 0x01a1 line=560
+ 0x01a8 line=561
+ 0x01b5 line=564
+ 0x01b8 line=565
+ 0x01bb line=571
+ 0x01bc line=566
+ 0x01bd line=567
+ 0x01c4 line=568
+ 0x01cd line=569
+ 0x01d4 line=570
+ 0x01e1 line=573
+ 0x01e4 line=574
+ 0x01e7 line=580
+ 0x01e8 line=575
+ 0x01e9 line=576
+ 0x01f0 line=577
+ 0x01f9 line=578
+ 0x0200 line=579
+ 0x020d line=581
+ 0x0210 line=582
+ locals :
+ 0x0012 - 0x0022 reg=0 expected Ljava/lang/NoSuchMethodError;
+ 0x002a - 0x003a reg=0 expected Ljava/lang/NoSuchMethodError;
+ 0x0042 - 0x0073 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x007b - 0x00ac reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x00b4 - 0x00e5 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x00ed - 0x011e reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x0126 - 0x0157 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x0165 - 0x0189 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x0191 - 0x01b5 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x01bd - 0x01e1 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x01e9 - 0x020d reg=0 expected Ljava/lang/BootstrapMethodError;
+
+ #32 : (in LTestBadBootstrapArguments;)
+ name : 'voidReturnType'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 12
- ins : 6
- outs : 3
- insns size : 85 16-bit code units
-0010ac: |[0010ac] invokecustom.InvokeCustom.targetMethodTest6:(JJJ)J
-0010bc: 9b00 0608 |0000: add-long v0, v6, v8
-0010c0: 6202 0200 |0002: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0010c4: 2203 1000 |0004: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-0010c8: 7010 3000 0300 |0006: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-0010ce: 1a04 9000 |0009: const-string v4, "targetMethodTest6 " // string@0090
-0010d2: 6e20 3600 4300 |000b: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0010d8: 0c03 |000e: move-result-object v3
-0010da: 6e30 3400 6307 |000f: invoke-virtual {v3, v6, v7}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-0010e0: 0c03 |0012: move-result-object v3
-0010e2: 1a04 0400 |0013: const-string v4, " + " // string@0004
-0010e6: 6e20 3600 4300 |0015: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0010ec: 0c03 |0018: move-result-object v3
-0010ee: 6e30 3400 8309 |0019: invoke-virtual {v3, v8, v9}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-0010f4: 0c03 |001c: move-result-object v3
-0010f6: 1a04 0500 |001d: const-string v4, " = " // string@0005
-0010fa: 6e20 3600 4300 |001f: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001100: 0c03 |0022: move-result-object v3
-001102: 6e30 3400 0301 |0023: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-001108: 0c03 |0026: move-result-object v3
-00110a: 6e10 3700 0300 |0027: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-001110: 0c03 |002a: move-result-object v3
-001112: 6e20 2900 3200 |002b: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001118: 3102 000a |002e: cmp-long v2, v0, v10
-00111c: 3802 2400 |0030: if-eqz v2, 0054 // +0024
-001120: 6202 0200 |0032: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001124: 2203 1000 |0034: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-001128: 7010 3000 0300 |0036: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-00112e: 1a04 1400 |0039: const-string v4, "Failed " // string@0014
-001132: 6e20 3600 4300 |003b: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001138: 0c03 |003e: move-result-object v3
-00113a: 6e30 3400 0301 |003f: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-001140: 0c03 |0042: move-result-object v3
-001142: 1a04 0200 |0043: const-string v4, " != " // string@0002
-001146: 6e20 3600 4300 |0045: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-00114c: 0c03 |0048: move-result-object v3
-00114e: 6e30 3400 a30b |0049: invoke-virtual {v3, v10, v11}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-001154: 0c03 |004c: move-result-object v3
-001156: 6e10 3700 0300 |004d: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-00115c: 0c03 |0050: move-result-object v3
-00115e: 6e20 2900 3200 |0051: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001164: 1000 |0054: return-wide v0
- catches : (none)
- positions :
- 0x0000 line=81
- 0x0002 line=82
- 0x002e line=83
- 0x0032 line=84
- 0x0054 line=86
- locals :
- 0x0000 - 0x0055 reg=6 (null) J
- 0x0000 - 0x0055 reg=8 (null) J
- 0x0000 - 0x0055 reg=10 (null) J
-
- #17 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest7'
- type : '(FFD)D'
- access : 0x0009 (PUBLIC STATIC)
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+00248c: |[00248c] TestBadBootstrapArguments.voidReturnType:()V
+00249c: 7100 0b00 0000 |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0024a2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=398
+ 0x0003 line=399
+ locals :
+
+ #33 : (in LTestBadBootstrapArguments;)
+ name : 'wideningArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 10
- ins : 4
- outs : 3
- insns size : 86 16-bit code units
-001168: |[001168] invokecustom.InvokeCustom.targetMethodTest7:(FFD)D
-001178: a800 0607 |0000: mul-float v0, v6, v7
-00117c: 8900 |0002: float-to-double v0, v0
-00117e: 6202 0200 |0003: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001182: 2203 1000 |0005: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-001186: 7010 3000 0300 |0007: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-00118c: 1a04 9300 |000a: const-string v4, "targetMethodTest7 " // string@0093
-001190: 6e20 3600 4300 |000c: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001196: 0c03 |000f: move-result-object v3
-001198: 6e20 3200 6300 |0010: invoke-virtual {v3, v6}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-00119e: 0c03 |0013: move-result-object v3
-0011a0: 1a04 0300 |0014: const-string v4, " * " // string@0003
-0011a4: 6e20 3600 4300 |0016: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0011aa: 0c03 |0019: move-result-object v3
-0011ac: 6e20 3200 7300 |001a: invoke-virtual {v3, v7}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@0032
-0011b2: 0c03 |001d: move-result-object v3
-0011b4: 1a04 0500 |001e: const-string v4, " = " // string@0005
-0011b8: 6e20 3600 4300 |0020: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0011be: 0c03 |0023: move-result-object v3
-0011c0: 6e30 3100 0301 |0024: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@0031
-0011c6: 0c03 |0027: move-result-object v3
-0011c8: 6e10 3700 0300 |0028: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-0011ce: 0c03 |002b: move-result-object v3
-0011d0: 6e20 2900 3200 |002c: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0011d6: 2f02 0008 |002f: cmpl-double v2, v0, v8
-0011da: 3802 2400 |0031: if-eqz v2, 0055 // +0024
-0011de: 6202 0200 |0033: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0011e2: 2203 1000 |0035: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-0011e6: 7010 3000 0300 |0037: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-0011ec: 1a04 1400 |003a: const-string v4, "Failed " // string@0014
-0011f0: 6e20 3600 4300 |003c: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0011f6: 0c03 |003f: move-result-object v3
-0011f8: 6e30 3100 0301 |0040: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@0031
-0011fe: 0c03 |0043: move-result-object v3
-001200: 1a04 0200 |0044: const-string v4, " != " // string@0002
-001204: 6e20 3600 4300 |0046: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-00120a: 0c03 |0049: move-result-object v3
-00120c: 6e30 3100 8309 |004a: invoke-virtual {v3, v8, v9}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@0031
-001212: 0c03 |004d: move-result-object v3
-001214: 6e10 3700 0300 |004e: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-00121a: 0c03 |0051: move-result-object v3
-00121c: 6e20 2900 3200 |0052: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001222: 1000 |0055: return-wide v0
- catches : (none)
- positions :
- 0x0000 line=90
- 0x0003 line=91
- 0x002f line=92
- 0x0033 line=93
- 0x0055 line=95
- locals :
- 0x0000 - 0x0056 reg=6 (null) F
- 0x0000 - 0x0056 reg=7 (null) F
- 0x0000 - 0x0056 reg=8 (null) D
-
- #18 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest8'
- type : '(Ljava/lang/String;)V'
- access : 0x0009 (PUBLIC STATIC)
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+0024a4: |[0024a4] TestBadBootstrapArguments.wideningArguments:()V
+0024b4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024b8: 1a01 d101 |0002: const-string v1, "wideningArguments" // string@01d1
+0024bc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0024c2: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=304
+ 0x0007 line=305
+ locals :
+
+ #34 : (in LTestBadBootstrapArguments;)
+ name : 'wideningBoxingArguments'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 4
- ins : 1
+ registers : 2
+ ins : 0
outs : 2
- insns size : 25 16-bit code units
-001224: |[001224] invokecustom.InvokeCustom.targetMethodTest8:(Ljava/lang/String;)V
-001234: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001238: 2201 1000 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-00123c: 7010 3000 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-001242: 1a02 9500 |0007: const-string v2, "targetMethodTest8 " // string@0095
-001246: 6e20 3600 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-00124c: 0c01 |000c: move-result-object v1
-00124e: 6e20 3600 3100 |000d: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001254: 0c01 |0010: move-result-object v1
-001256: 6e10 3700 0100 |0011: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-00125c: 0c01 |0014: move-result-object v1
-00125e: 6e20 2900 1000 |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001264: 0e00 |0018: return-void
+ insns size : 8 16-bit code units
+0024c4: |[0024c4] TestBadBootstrapArguments.wideningBoxingArguments:()V
+0024d4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024d8: 1a01 d201 |0002: const-string v1, "wideningBoxingArguments" // string@01d2
+0024dc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0024e2: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=99
- 0x0018 line=100
+ 0x0000 line=376
+ 0x0007 line=377
locals :
- 0x0000 - 0x0019 reg=3 (null) Ljava/lang/String;
- #19 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest9'
+ #35 : (in LTestBadBootstrapArguments;)
+ name : 'wrongArguments'
type : '()V'
access : 0x000a (PRIVATE STATIC)
code -
@@ -991,435 +2200,3526 @@ Class #1 -
ins : 0
outs : 2
insns size : 8 16-bit code units
-001268: |[001268] invokecustom.InvokeCustom.targetMethodTest9:()V
-001278: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-00127c: 1a01 9700 |0002: const-string v1, "targetMethodTest9()" // string@0097
-001280: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001286: 0e00 |0007: return-void
+0024e4: |[0024e4] TestBadBootstrapArguments.wrongArguments:()V
+0024f4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024f8: 1a01 d401 |0002: const-string v1, "wrongArguments" // string@01d4
+0024fc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002502: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=133
- 0x0007 line=134
+ 0x0000 line=186
+ 0x0007 line=187
locals :
- #20 : (in Linvokecustom/InvokeCustom;)
- name : 'test1'
+ #36 : (in LTestBadBootstrapArguments;)
+ name : 'wrongArgumentsAgain'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 0
+ registers : 2
ins : 0
- outs : 0
- insns size : 4 16-bit code units
-001288: |[001288] invokecustom.InvokeCustom.test1:()V
-001298: fc00 0300 0000 |0000: invoke-custom {}, call_site@0003
-00129e: 0e00 |0003: return-void
+ outs : 2
+ insns size : 8 16-bit code units
+002504: |[002504] TestBadBootstrapArguments.wrongArgumentsAgain:()V
+002514: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002518: 1a01 d501 |0002: const-string v1, "wrongArgumentsAgain" // string@01d5
+00251c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002522: 0e00 |0007: return-void
catches : (none)
positions :
+ 0x0000 line=214
+ 0x0007 line=215
locals :
- #21 : (in Linvokecustom/InvokeCustom;)
- name : 'test2'
+ #37 : (in LTestBadBootstrapArguments;)
+ name : 'wrongParameterTypes'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 11
+ registers : 2
ins : 0
- outs : 11
- insns size : 27 16-bit code units
-0012a0: |[0012a0] invokecustom.InvokeCustom.test2:()V
-0012b0: 1210 |0000: const/4 v0, #int 1 // #1
-0012b2: 1301 7f00 |0001: const/16 v1, #int 127 // #7f
-0012b6: 1302 6300 |0003: const/16 v2, #int 99 // #63
-0012ba: 1303 0004 |0005: const/16 v3, #int 1024 // #400
-0012be: 1404 40e2 0100 |0007: const v4, #float 1.72999e-40 // #0001e240
-0012c4: 1405 9a99 993f |000a: const v5, #float 1.2 // #3f99999a
-0012ca: 1706 15cd 5b07 |000d: const-wide/32 v6, #float 1.6536e-34 // #075bcd15
-0012d0: 1808 b6fa f8b0 4819 0c40 |0010: const-wide v8, #double 3.51235 // #400c1948b0f8fab6
-0012da: 1a0a 4800 |0015: const-string v10, "String" // string@0048
-0012de: fd0b 0400 0000 |0017: invoke-custom/range {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10}, call_site@0004
-0012e4: 0e00 |001a: return-void
+ outs : 2
+ insns size : 8 16-bit code units
+002524: |[002524] TestBadBootstrapArguments.wrongParameterTypes:()V
+002534: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002538: 1a01 d601 |0002: const-string v1, "wrongParameterTypes" // string@01d6
+00253c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002542: 0e00 |0007: return-void
catches : (none)
positions :
+ 0x0000 line=102
+ 0x0007 line=103
locals :
- #22 : (in Linvokecustom/InvokeCustom;)
- name : 'test3'
+ Virtual methods -
+ source_file_idx : 144 (TestBadBootstrapArguments.java)
+
+Class #7 header:
+class_idx : 10
+access_flags : 0 (0x0000)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 147
+annotations_off : 30988 (0x00790c)
+class_data_off : 29220 (0x007224)
+static_fields_size : 1
+instance_fields_size: 0
+direct_methods_size : 7
+virtual_methods_size: 0
+
+Class #7 annotations:
+Annotations on method #67 'bsm'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #71 'testDynamic'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestDynamicBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/String; J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "A" } Lannotations/Constant; longValue={ 100000000 } } fieldOrMethodName="target" parameterTypes={ I Ljava/lang/String; D } returnType=I
+
+Class #7 -
+ Class descriptor : 'LTestDynamicBootstrapArguments;'
+ Access flags : 0x0000 ()
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ #0 : (in LTestDynamicBootstrapArguments;)
+ name : 'bsmCalls'
+ type : 'I'
+ access : 0x000a (PRIVATE STATIC)
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestDynamicBootstrapArguments;)
+ name : '<clinit>'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x10008 (STATIC CONSTRUCTOR)
code -
- registers : 0
+ registers : 1
ins : 0
outs : 0
insns size : 4 16-bit code units
-0012e8: |[0012e8] invokecustom.InvokeCustom.test3:()V
-0012f8: fc00 0b00 0000 |0000: invoke-custom {}, call_site@000b
-0012fe: 0e00 |0003: return-void
+0029c8: |[0029c8] TestDynamicBootstrapArguments.<clinit>:()V
+0029d8: 1200 |0000: const/4 v0, #int 0 // #0
+0029da: 6700 0000 |0001: sput v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+0029de: 0e00 |0003: return-void
catches : (none)
positions :
+ 0x0000 line=27
locals :
- #23 : (in Linvokecustom/InvokeCustom;)
- name : 'test4'
+ #1 : (in LTestDynamicBootstrapArguments;)
+ name : '<init>'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x10000 (CONSTRUCTOR)
code -
registers : 1
- ins : 0
+ ins : 1
outs : 1
- insns size : 9 16-bit code units
-001300: |[001300] invokecustom.InvokeCustom.test4:()V
-001310: 2200 0700 |0000: new-instance v0, Linvokecustom/InvokeCustom; // type@0007
-001314: 7010 0100 0000 |0002: invoke-direct {v0}, Linvokecustom/InvokeCustom;.<init>:()V // method@0001
-00131a: fc10 0c00 0000 |0005: invoke-custom {v0}, call_site@000c
-001320: 0e00 |0008: return-void
+ insns size : 4 16-bit code units
+0029e0: |[0029e0] TestDynamicBootstrapArguments.<init>:()V
+0029f0: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0029f6: 0e00 |0003: return-void
catches : (none)
positions :
+ 0x0000 line=26
locals :
+ 0x0000 - 0x0004 reg=0 this LTestDynamicBootstrapArguments;
- #24 : (in Linvokecustom/InvokeCustom;)
- name : 'test5'
+ #2 : (in LTestDynamicBootstrapArguments;)
+ name : 'bsm'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 11
+ ins : 6
+ outs : 4
+ insns size : 43 16-bit code units
+002960: |[002960] TestDynamicBootstrapArguments.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;
+002970: 6000 0000 |0000: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002974: d800 0001 |0002: add-int/lit8 v0, v0, #int 1 // #01
+002978: 6700 0000 |0004: sput v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+00297c: 1c00 0a00 |0006: const-class v0, LTestDynamicBootstrapArguments; // type@000a
+002980: 2201 2d00 |0008: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002984: 7010 c100 0100 |000a: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00298a: 6e20 c800 6100 |000d: invoke-virtual {v1, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002990: 6e20 c800 8100 |0010: invoke-virtual {v1, v8}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002996: 6e30 c600 910a |0013: invoke-virtual {v1, v9, v10}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+00299c: 6e10 ca00 0100 |0016: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0029a2: 0c01 |0019: move-result-object v1
+0029a4: 6e40 d800 0571 |001a: invoke-virtual {v5, v0, v1, v7}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0029aa: 0c02 |001d: move-result-object v2
+0029ac: 6203 1300 |001e: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0029b0: 1a04 ea00 |0020: const-string v4, "bsm" // string@00ea
+0029b4: 6e20 b300 4300 |0022: invoke-virtual {v3, v4}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0029ba: 2203 3400 |0025: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0029be: 7020 d200 2300 |0027: invoke-direct {v3, v2}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0029c4: 1103 |002a: return-object v3
+ catches : (none)
+ positions :
+ 0x0000 line=36
+ 0x0006 line=37
+ 0x0008 line=38
+ 0x001a line=39
+ 0x001e line=40
+ 0x0025 line=41
+ locals :
+ 0x0008 - 0x002b reg=0 definingClass Ljava/lang/Class; Ljava/lang/Class<*>;
+ 0x001a - 0x002b reg=1 methodName Ljava/lang/String;
+ 0x001e - 0x002b reg=2 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x002b reg=5 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x002b reg=6 name Ljava/lang/String;
+ 0x0000 - 0x002b reg=7 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x002b reg=8 otherNameComponent Ljava/lang/String;
+ 0x0000 - 0x002b reg=9 nameSuffix J
+
+ #3 : (in LTestDynamicBootstrapArguments;)
+ name : 'targetA100000000'
+ type : '(ILjava/lang/String;Ljava/lang/Double;)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 2
+ insns size : 30 16-bit code units
+0028f8: |[0028f8] TestDynamicBootstrapArguments.targetA100000000:(ILjava/lang/String;Ljava/lang/Double;)I
+002908: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00290c: 6e20 ad00 2000 |0002: invoke-virtual {v0, v2}, Ljava/io/PrintStream;.print:(I)V // method@00ad
+002912: 6200 1300 |0005: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002916: 1a01 0c00 |0007: const-string v1, ", " // string@000c
+00291a: 6e20 b000 1000 |0009: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002920: 6200 1300 |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002924: 6e20 b000 3000 |000e: invoke-virtual {v0, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00292a: 6200 1300 |0011: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00292e: 1a01 0c00 |0013: const-string v1, ", " // string@000c
+002932: 6e20 b000 1000 |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002938: 6200 1300 |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00293c: 6e20 b200 4000 |001a: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002942: 0f02 |001d: return v2
+ catches : (none)
+ positions :
+ 0x0000 line=71
+ 0x0005 line=72
+ 0x000c line=73
+ 0x0011 line=74
+ 0x0018 line=75
+ 0x001d line=76
+ locals :
+ 0x0000 - 0x001e reg=2 i I
+ 0x0000 - 0x001e reg=3 s Ljava/lang/String;
+ 0x0000 - 0x001e reg=4 d Ljava/lang/Double;
+
+ #4 : (in LTestDynamicBootstrapArguments;)
+ name : 'test'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x0008 (STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 25 16-bit code units
+0029f8: |[0029f8] TestDynamicBootstrapArguments.test:()V
+002a08: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002a0c: 1a01 9200 |0002: const-string v1, "TestDynamicArguments" // string@0092
+002a10: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002a16: 7100 4600 0000 |0007: invoke-static {}, LTestDynamicBootstrapArguments;.testCallSites:()V // method@0046
+002a1c: 6000 0000 |000a: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002a20: 1231 |000c: const/4 v1, #int 3 // #3
+002a22: 7120 4100 0100 |000d: invoke-static {v1, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a28: 7100 4600 0000 |0010: invoke-static {}, LTestDynamicBootstrapArguments;.testCallSites:()V // method@0046
+002a2e: 6000 0000 |0013: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002a32: 7120 4100 0100 |0015: invoke-static {v1, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a38: 0e00 |0018: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=86
+ 0x0007 line=87
+ 0x000a line=88
+ 0x0010 line=89
+ 0x0013 line=90
+ 0x0018 line=91
+ locals :
+
+ #5 : (in LTestDynamicBootstrapArguments;)
+ name : 'testCallSites'
+ type : '()V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 3
+ ins : 0
+ outs : 3
+ insns size : 55 16-bit code units
+002a3c: |[002a3c] TestDynamicBootstrapArguments.testCallSites:()V
+002a4c: 1a00 8b00 |0000: const-string v0, "One" // string@008b
+002a50: 1801 182d 4454 fb21 0940 |0002: const-wide v1, #double 3.14159 // #400921fb54442d18
+002a5a: 7120 b900 2100 |0007: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002a60: 0c01 |000a: move-result-object v1
+002a62: 1202 |000b: const/4 v2, #int 0 // #0
+002a64: fc30 0f00 0201 |000c: invoke-custom {v2, v0, v1}, call_site@000f
+002a6a: 0a00 |000f: move-result v0
+002a6c: 7120 4100 0200 |0010: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a72: 1a00 a200 |0013: const-string v0, "Two" // string@00a2
+002a76: 1801 6957 148b 0abf 0540 |0015: const-wide v1, #double 2.71828 // #4005bf0a8b145769
+002a80: 7120 b900 2100 |001a: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002a86: 0c01 |001d: move-result-object v1
+002a88: 1212 |001e: const/4 v2, #int 1 // #1
+002a8a: fc30 1000 0201 |001f: invoke-custom {v2, v0, v1}, call_site@0010
+002a90: 0a00 |0022: move-result v0
+002a92: 7120 4100 0200 |0023: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a98: 1a00 9f00 |0026: const-string v0, "Three" // string@009f
+002a9c: 1601 0000 |0028: const-wide/16 v1, #int 0 // #0
+002aa0: 7120 b900 2100 |002a: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002aa6: 0c01 |002d: move-result-object v1
+002aa8: 1222 |002e: const/4 v2, #int 2 // #2
+002aaa: fc30 1100 0201 |002f: invoke-custom {v2, v0, v1}, call_site@0011
+002ab0: 0a00 |0032: move-result v0
+002ab2: 7120 4100 0200 |0033: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002ab8: 0e00 |0036: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=80
+ 0x0013 line=81
+ 0x0026 line=82
+ 0x0036 line=83
+ locals :
+
+ #6 : (in LTestDynamicBootstrapArguments;)
+ name : 'testDynamic'
+ type : '(ILjava/lang/String;Ljava/lang/Double;)I'
+ access : 0x000a (PRIVATE STATIC)
code -
registers : 4
+ ins : 3
+ outs : 0
+ insns size : 5 16-bit code units
+002944: |[002944] TestDynamicBootstrapArguments.testDynamic:(ILjava/lang/String;Ljava/lang/Double;)I
+002954: 7100 4200 0000 |0000: invoke-static {}, LTestDynamicBootstrapArguments;.assertNotReached:()V // method@0042
+00295a: 1200 |0003: const/4 v0, #int 0 // #0
+00295c: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=66
+ 0x0003 line=67
+ locals :
+ 0x0000 - 0x0005 reg=1 i I
+ 0x0000 - 0x0005 reg=2 s Ljava/lang/String;
+ 0x0000 - 0x0005 reg=3 d Ljava/lang/Double;
+
+ Virtual methods -
+ source_file_idx : 147 (TestDynamicBootstrapArguments.java)
+
+Class #8 header:
+class_idx : 12
+access_flags : 0 (0x0000)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 148
+annotations_off : 31020 (0x00792c)
+class_data_off : 29258 (0x00724a)
+static_fields_size : 1
+instance_fields_size: 1
+direct_methods_size : 18
+virtual_methods_size: 1
+
+Class #8 annotations:
+Annotations on class
+ VISIBILITY_SYSTEM Ldalvik/annotation/MemberClasses; value={ LTestInvocationKinds$Widget; }
+Annotations on method #78 'getInstanceField'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupInstanceFieldGetter" } fieldOrMethodName="instance_field" parameterTypes={ LTestInvocationKinds; } returnType=D
+Annotations on method #80 'getStaticField'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupStaticFieldGetter" } fieldOrMethodName="static_field" parameterTypes={ } returnType=I
+Annotations on method #81 'lookupConstructor'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #82 'lookupInstanceFieldGetter'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #83 'lookupInstanceFieldSetter'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #84 'lookupStaticFieldGetter'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #85 'lookupStaticFieldSetter'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #86 'lookupVirtual'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #87 'makeWidget'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupConstructor" } fieldOrMethodName="unused" parameterTypes={ I } returnType=LTestInvocationKinds$Widget;
+Annotations on method #88 'maxIntegerValue'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupVirtual" } fieldOrMethodName="getMaxIntegerValue" parameterTypes={ LTestInvocationKinds; I I } returnType=I
+Annotations on method #89 'setInstanceField'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupInstanceFieldSetter" } fieldOrMethodName="instance_field" parameterTypes={ LTestInvocationKinds; D } returnType=V
+Annotations on method #90 'setStaticField'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupStaticFieldSetter" } fieldOrMethodName="static_field" parameterTypes={ I } returnType=V
+
+Class #8 -
+ Class descriptor : 'LTestInvocationKinds;'
+ Access flags : 0x0000 ()
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ #0 : (in LTestInvocationKinds;)
+ name : 'static_field'
+ type : 'I'
+ access : 0x000a (PRIVATE STATIC)
+ Instance fields -
+ #0 : (in LTestInvocationKinds;)
+ name : 'instance_field'
+ type : 'D'
+ access : 0x0002 (PRIVATE)
+ Direct methods -
+ #0 : (in LTestInvocationKinds;)
+ name : '<init>'
+ type : '()V'
+ access : 0x10000 (CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+002ca4: |[002ca4] TestInvocationKinds.<init>:()V
+002cb4: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+002cba: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=25
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestInvocationKinds;
+
+ #1 : (in LTestInvocationKinds;)
+ name : 'getInstanceField'
+ type : '(LTestInvocationKinds;)D'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 1
+ outs : 0
+ insns size : 6 16-bit code units
+002af0: |[002af0] TestInvocationKinds.getInstanceField:(LTestInvocationKinds;)D
+002b00: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b06: 1900 f87f |0003: const-wide/high16 v0, #long 9221120237041090560 // #7ff8
+002b0a: 1000 |0005: return-wide v0
+ catches : (none)
+ positions :
+ 0x0000 line=117
+ 0x0003 line=118
+ locals :
+ 0x0000 - 0x0006 reg=2 instance LTestInvocationKinds;
+
+ #2 : (in LTestInvocationKinds;)
+ name : 'getStaticField'
+ type : '()I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 1
ins : 0
+ outs : 0
+ insns size : 5 16-bit code units
+002b28: |[002b28] TestInvocationKinds.getStaticField:()I
+002b38: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b3e: 1200 |0003: const/4 v0, #int 0 // #0
+002b40: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=71
+ 0x0003 line=72
+ locals :
+
+ #3 : (in LTestInvocationKinds;)
+ name : 'lookupConstructor'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 7
+ ins : 3
outs : 3
- insns size : 35 16-bit code units
-001324: |[001324] invokecustom.InvokeCustom.test5:()V
-001334: 1300 e803 |0000: const/16 v0, #int 1000 // #3e8
-001338: 1301 65fc |0002: const/16 v1, #int -923 // #fc65
-00133c: 1302 4d00 |0004: const/16 v2, #int 77 // #4d
-001340: fc30 0500 1002 |0006: invoke-custom {v0, v1, v2}, call_site@0005
-001346: 0a00 |0009: move-result v0
-001348: 6201 0200 |000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-00134c: 2202 1000 |000c: new-instance v2, Ljava/lang/StringBuilder; // type@0010
-001350: 7010 3000 0200 |000e: invoke-direct {v2}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-001356: 1a03 8e00 |0011: const-string v3, "targetMethodTest5 returned: " // string@008e
-00135a: 6e20 3600 3200 |0013: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-001360: 0c02 |0016: move-result-object v2
-001362: 6e20 3300 0200 |0017: invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@0033
-001368: 0c00 |001a: move-result-object v0
-00136a: 6e10 3700 0000 |001b: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-001370: 0c00 |001e: move-result-object v0
-001372: 6e20 2900 0100 |001f: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001378: 0e00 |0022: return-void
- catches : (none)
- positions :
- locals :
-
- #25 : (in Linvokecustom/InvokeCustom;)
- name : 'test6'
+ insns size : 20 16-bit code units
+002b60: |[002b60] TestInvocationKinds.lookupConstructor:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002b70: 6e10 e500 0600 |0000: invoke-virtual {v6}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002b76: 0c00 |0003: move-result-object v0
+002b78: 6201 1400 |0004: sget-object v1, Ljava/lang/Void;.TYPE:Ljava/lang/Class; // field@0014
+002b7c: 6e20 df00 1600 |0006: invoke-virtual {v6, v1}, Ljava/lang/invoke/MethodType;.changeReturnType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00df
+002b82: 0c01 |0009: move-result-object v1
+002b84: 6e30 d500 0401 |000a: invoke-virtual {v4, v0, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findConstructor:(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d5
+002b8a: 0c02 |000d: move-result-object v2
+002b8c: 2203 3400 |000e: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002b90: 7020 d200 2300 |0010: invoke-direct {v3, v2}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002b96: 1103 |0013: return-object v3
+ catches : (none)
+ positions :
+ 0x0000 line=183
+ 0x0004 line=184
+ 0x000a line=185
+ 0x000e line=186
+ locals :
+ 0x0004 - 0x0014 reg=0 cls Ljava/lang/Class; Ljava/lang/Class<*>;
+ 0x000a - 0x0014 reg=1 constructorMethodType Ljava/lang/invoke/MethodType;
+ 0x000e - 0x0014 reg=2 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0014 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0014 reg=5 name Ljava/lang/String;
+ 0x0000 - 0x0014 reg=6 methodType Ljava/lang/invoke/MethodType;
+
+ #4 : (in LTestInvocationKinds;)
+ name : 'lookupInstanceFieldGetter'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 4
+ insns size : 20 16-bit code units
+002b98: |[002b98] TestInvocationKinds.lookupInstanceFieldGetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002ba8: 0000 |0000: nop // spacer
+002baa: 1200 |0001: const/4 v0, #int 0 // #0
+002bac: 6e20 e400 0400 |0002: invoke-virtual {v4, v0}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bb2: 0c00 |0005: move-result-object v0
+002bb4: 6e10 e500 0400 |0006: invoke-virtual {v4}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002bba: 0c01 |0009: move-result-object v1
+002bbc: 6e40 d600 0213 |000a: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findGetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d6
+002bc2: 0c00 |000d: move-result-object v0
+002bc4: 2201 3400 |000e: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002bc8: 7020 d200 0100 |0010: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002bce: 1101 |0013: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=101
+ 0x0001 line=102
+ 0x000e line=103
+ locals :
+ 0x000e - 0x0014 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0014 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0014 reg=3 name Ljava/lang/String;
+ 0x0000 - 0x0014 reg=4 methodType Ljava/lang/invoke/MethodType;
+
+ #5 : (in LTestInvocationKinds;)
+ name : 'lookupInstanceFieldSetter'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 4
+ insns size : 21 16-bit code units
+002bd0: |[002bd0] TestInvocationKinds.lookupInstanceFieldSetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002be0: 0000 |0000: nop // spacer
+002be2: 1200 |0001: const/4 v0, #int 0 // #0
+002be4: 6e20 e400 0400 |0002: invoke-virtual {v4, v0}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bea: 0c00 |0005: move-result-object v0
+002bec: 1211 |0006: const/4 v1, #int 1 // #1
+002bee: 6e20 e400 1400 |0007: invoke-virtual {v4, v1}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bf4: 0c01 |000a: move-result-object v1
+002bf6: 6e40 d700 0213 |000b: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findSetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d7
+002bfc: 0c00 |000e: move-result-object v0
+002bfe: 2201 3400 |000f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c02: 7020 d200 0100 |0011: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c08: 1101 |0014: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=78
+ 0x0001 line=79
+ 0x000f line=80
+ locals :
+ 0x000f - 0x0015 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0015 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0015 reg=3 name Ljava/lang/String;
+ 0x0000 - 0x0015 reg=4 methodType Ljava/lang/invoke/MethodType;
+
+ #6 : (in LTestInvocationKinds;)
+ name : 'lookupStaticFieldGetter'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 4
+ insns size : 16 16-bit code units
+002c0c: |[002c0c] TestInvocationKinds.lookupStaticFieldGetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c1c: 1c00 0c00 |0000: const-class v0, LTestInvocationKinds; // type@000c
+002c20: 6e10 e500 0400 |0002: invoke-virtual {v4}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002c26: 0c01 |0005: move-result-object v1
+002c28: 6e40 d900 0213 |0006: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStaticGetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d9
+002c2e: 0c00 |0009: move-result-object v0
+002c30: 2201 3400 |000a: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c34: 7020 d200 0100 |000c: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c3a: 1101 |000f: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=32
+ 0x0002 line=33
+ 0x000a line=34
+ locals :
+ 0x000a - 0x0010 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0010 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0010 reg=3 name Ljava/lang/String;
+ 0x0000 - 0x0010 reg=4 methodType Ljava/lang/invoke/MethodType;
+
+ #7 : (in LTestInvocationKinds;)
+ name : 'lookupStaticFieldSetter'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 4
+ insns size : 17 16-bit code units
+002c3c: |[002c3c] TestInvocationKinds.lookupStaticFieldSetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c4c: 1c00 0c00 |0000: const-class v0, LTestInvocationKinds; // type@000c
+002c50: 1201 |0002: const/4 v1, #int 0 // #0
+002c52: 6e20 e400 1400 |0003: invoke-virtual {v4, v1}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002c58: 0c01 |0006: move-result-object v1
+002c5a: 6e40 da00 0213 |0007: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStaticSetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00da
+002c60: 0c00 |000a: move-result-object v0
+002c62: 2201 3400 |000b: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c66: 7020 d200 0100 |000d: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c6c: 1101 |0010: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=54
+ 0x0002 line=56
+ 0x0007 line=55
+ 0x000b line=57
+ locals :
+ 0x000b - 0x0011 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0011 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0011 reg=3 name Ljava/lang/String;
+ 0x0000 - 0x0011 reg=4 methodType Ljava/lang/invoke/MethodType;
+
+ #8 : (in LTestInvocationKinds;)
+ name : 'lookupVirtual'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 6
+ ins : 3
+ outs : 4
+ insns size : 18 16-bit code units
+002c70: |[002c70] TestInvocationKinds.lookupVirtual:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c80: 1200 |0000: const/4 v0, #int 0 // #0
+002c82: 1211 |0001: const/4 v1, #int 1 // #1
+002c84: 6e30 e000 0501 |0002: invoke-virtual {v5, v0, v1}, Ljava/lang/invoke/MethodType;.dropParameterTypes:(II)Ljava/lang/invoke/MethodType; // method@00e0
+002c8a: 0c00 |0005: move-result-object v0
+002c8c: 1c01 0c00 |0006: const-class v1, LTestInvocationKinds; // type@000c
+002c90: 6e40 db00 1304 |0008: invoke-virtual {v3, v1, v4, v0}, Ljava/lang/invoke/MethodHandles$Lookup;.findVirtual:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00db
+002c96: 0c01 |000b: move-result-object v1
+002c98: 2202 3400 |000c: new-instance v2, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c9c: 7020 d200 1200 |000e: invoke-direct {v2, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002ca2: 1102 |0011: return-object v2
+ catches : (none)
+ positions :
+ 0x0000 line=146
+ 0x0006 line=147
+ 0x000c line=148
+ locals :
+ 0x0006 - 0x0012 reg=0 mt Ljava/lang/invoke/MethodType;
+ 0x000c - 0x0012 reg=1 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0012 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0012 reg=4 name Ljava/lang/String;
+ 0x0000 - 0x0012 reg=5 methodType Ljava/lang/invoke/MethodType;
+
+ #9 : (in LTestInvocationKinds;)
+ name : 'makeWidget'
+ type : '(I)LTestInvocationKinds$Widget;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 1
+ outs : 0
+ insns size : 5 16-bit code units
+002ad4: |[002ad4] TestInvocationKinds.makeWidget:(I)LTestInvocationKinds$Widget;
+002ae4: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002aea: 1200 |0003: const/4 v0, #int 0 // #0
+002aec: 1100 |0004: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=200
+ 0x0003 line=201
+ locals :
+ 0x0000 - 0x0005 reg=1 v I
+
+ #10 : (in LTestInvocationKinds;)
+ name : 'maxIntegerValue'
+ type : '(LTestInvocationKinds;II)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 4
+ ins : 3
+ outs : 0
+ insns size : 5 16-bit code units
+002b44: |[002b44] TestInvocationKinds.maxIntegerValue:(LTestInvocationKinds;II)I
+002b54: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b5a: 1200 |0003: const/4 v0, #int 0 // #0
+002b5c: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=159
+ 0x0003 line=160
+ locals :
+ 0x0000 - 0x0005 reg=1 receiver LTestInvocationKinds;
+ 0x0000 - 0x0005 reg=2 x I
+ 0x0000 - 0x0005 reg=3 y I
+
+ #11 : (in LTestInvocationKinds;)
+ name : 'setInstanceField'
+ type : '(LTestInvocationKinds;D)V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 5
+ ins : 3
+ outs : 0
+ insns size : 8 16-bit code units
+002cbc: |[002cbc] TestInvocationKinds.setInstanceField:(LTestInvocationKinds;D)V
+002ccc: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002cd2: 1900 f87f |0003: const-wide/high16 v0, #long 9221120237041090560 // #7ff8
+002cd6: 5a20 0200 |0005: iput-wide v0, v2, LTestInvocationKinds;.instance_field:D // field@0002
+002cda: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=94
+ 0x0003 line=95
+ 0x0007 line=96
+ locals :
+ 0x0000 - 0x0008 reg=2 instance LTestInvocationKinds;
+ 0x0000 - 0x0008 reg=3 value D
+
+ #12 : (in LTestInvocationKinds;)
+ name : 'setStaticField'
+ type : '(I)V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 1
+ ins : 1
+ outs : 0
+ insns size : 4 16-bit code units
+002cdc: |[002cdc] TestInvocationKinds.setStaticField:(I)V
+002cec: 7100 4d00 0000 |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002cf2: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=48
+ 0x0003 line=49
+ locals :
+ 0x0000 - 0x0004 reg=0 value I
+
+ #13 : (in LTestInvocationKinds;)
+ name : 'test'
type : '()V'
access : 0x0009 (PUBLIC STATIC)
code -
- registers : 6
+ registers : 2
ins : 0
- outs : 6
- insns size : 44 16-bit code units
-00137c: |[00137c] invokecustom.InvokeCustom.test6:()V
-00138c: 1800 7777 7777 7707 0000 |0000: const-wide v0, #double 4.05612e-311 // #0000077777777777
-001396: 1802 efee eeee eefe ffff |0005: const-wide v2, #double -nan // #fffffeeeeeeeeeef
-0013a0: 1804 6666 6666 6606 0000 |000a: const-wide v4, #double 3.47668e-311 // #0000066666666666
-0013aa: fd06 0600 0000 |000f: invoke-custom/range {v0, v1, v2, v3, v4, v5}, call_site@0006
-0013b0: 0b00 |0012: move-result-wide v0
-0013b2: 6202 0200 |0013: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0013b6: 2203 1000 |0015: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-0013ba: 7010 3000 0300 |0017: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-0013c0: 1a04 9100 |001a: const-string v4, "targetMethodTest6 returned: " // string@0091
-0013c4: 6e20 3600 4300 |001c: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0013ca: 0c03 |001f: move-result-object v3
-0013cc: 6e30 3400 0301 |0020: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0034
-0013d2: 0c00 |0023: move-result-object v0
-0013d4: 6e10 3700 0000 |0024: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-0013da: 0c00 |0027: move-result-object v0
-0013dc: 6e20 2900 0200 |0028: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0013e2: 0e00 |002b: return-void
- catches : (none)
- positions :
- locals :
-
- #26 : (in Linvokecustom/InvokeCustom;)
- name : 'test7'
+ outs : 2
+ insns size : 24 16-bit code units
+002cf4: |[002cf4] TestInvocationKinds.test:()V
+002d04: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d08: 1c01 0c00 |0002: const-class v1, LTestInvocationKinds; // type@000c
+002d0c: 6e10 b700 0100 |0004: invoke-virtual {v1}, Ljava/lang/Class;.getName:()Ljava/lang/String; // method@00b7
+002d12: 0c01 |0007: move-result-object v1
+002d14: 6e20 b300 1000 |0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002d1a: 7100 5f00 0000 |000b: invoke-static {}, LTestInvocationKinds;.testStaticFieldAccessors:()V // method@005f
+002d20: 7100 5d00 0000 |000e: invoke-static {}, LTestInvocationKinds;.testInstanceFieldAccessors:()V // method@005d
+002d26: 7100 5e00 0000 |0011: invoke-static {}, LTestInvocationKinds;.testInvokeVirtual:()V // method@005e
+002d2c: 7100 5c00 0000 |0014: invoke-static {}, LTestInvocationKinds;.testConstructor:()V // method@005c
+002d32: 0e00 |0017: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=212
+ 0x000b line=213
+ 0x000e line=214
+ 0x0011 line=215
+ 0x0014 line=216
+ 0x0017 line=217
+ locals :
+
+ #14 : (in LTestInvocationKinds;)
+ name : 'testConstructor'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x0008 (STATIC)
+ code -
+ registers : 3
+ ins : 0
+ outs : 2
+ insns size : 31 16-bit code units
+002d34: |[002d34] TestInvocationKinds.testConstructor:()V
+002d44: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d48: 1a01 b601 |0002: const-string v1, "testConstructor => " // string@01b6
+002d4c: 6e20 b000 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002d52: 1230 |0007: const/4 v0, #int 3 // #3
+002d54: fc10 1200 0000 |0008: invoke-custom {v0}, call_site@0012
+002d5a: 0c00 |000b: move-result-object v0
+002d5c: 1c01 0b00 |000c: const-class v1, LTestInvocationKinds$Widget; // type@000b
+002d60: 6e10 c000 0000 |000e: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002d66: 0c02 |0011: move-result-object v2
+002d68: 7120 4c00 2100 |0012: invoke-static {v1, v2}, LTestInvocationKinds;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@004c
+002d6e: 6201 1300 |0015: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d72: 6e10 c000 0000 |0017: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002d78: 0c02 |001a: move-result-object v2
+002d7a: 6e20 b200 2100 |001b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002d80: 0e00 |001e: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=205
+ 0x0007 line=206
+ 0x000c line=207
+ 0x0015 line=208
+ 0x001e line=209
+ locals :
+ 0x000c - 0x001f reg=0 receiver LTestInvocationKinds$Widget;
+
+ #15 : (in LTestInvocationKinds;)
+ name : 'testInstanceFieldAccessors'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
code -
registers : 5
ins : 0
outs : 4
- insns size : 40 16-bit code units
-0013e4: |[0013e4] invokecustom.InvokeCustom.test7:()V
-0013f4: 1400 0040 003f |0000: const v0, #float 0.500977 // #3f004000
-0013fa: 1401 0040 00bf |0003: const v1, #float -0.500977 // #bf004000
-001400: 1802 0000 0000 0410 d0bf |0006: const-wide v2, #double -0.250978 // #bfd0100400000000
-00140a: fc40 0700 1032 |000b: invoke-custom {v0, v1, v2, v3}, call_site@0007
-001410: 0b00 |000e: move-result-wide v0
-001412: 6202 0200 |000f: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001416: 2203 1000 |0011: new-instance v3, Ljava/lang/StringBuilder; // type@0010
-00141a: 7010 3000 0300 |0013: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-001420: 1a04 9100 |0016: const-string v4, "targetMethodTest6 returned: " // string@0091
-001424: 6e20 3600 4300 |0018: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-00142a: 0c03 |001b: move-result-object v3
-00142c: 6e30 3100 0301 |001c: invoke-virtual {v3, v0, v1}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@0031
-001432: 0c00 |001f: move-result-object v0
-001434: 6e10 3700 0000 |0020: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-00143a: 0c00 |0023: move-result-object v0
-00143c: 6e20 2900 0200 |0024: invoke-virtual {v2, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001442: 0e00 |0027: return-void
- catches : (none)
- positions :
- locals :
-
- #27 : (in Linvokecustom/InvokeCustom;)
- name : 'test8'
+ insns size : 44 16-bit code units
+002d84: |[002d84] TestInvocationKinds.testInstanceFieldAccessors:()V
+002d94: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d98: 1a01 b801 |0002: const-string v1, "testInstanceFieldAccessors" // string@01b8
+002d9c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002da2: 2200 0c00 |0007: new-instance v0, LTestInvocationKinds; // type@000c
+002da6: 7010 4900 0000 |0009: invoke-direct {v0}, LTestInvocationKinds;.<init>:()V // method@0049
+002dac: 1601 0100 |000c: const-wide/16 v1, #int 1 // #1
+002db0: 5a01 0200 |000e: iput-wide v1, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002db4: 1801 182d 4454 fb21 0940 |0010: const-wide v1, #double 3.14159 // #400921fb54442d18
+002dbe: fc30 1300 1002 |0015: invoke-custom {v0, v1, v2}, call_site@0013
+002dc4: 5303 0200 |0018: iget-wide v3, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002dc8: 7140 4a00 2143 |001a: invoke-static {v1, v2, v3, v4}, LTestInvocationKinds;.assertEquals:(DD)V // method@004a
+002dce: 1801 6957 148b 0abf 0540 |001d: const-wide v1, #double 2.71828 // #4005bf0a8b145769
+002dd8: 5a01 0200 |0022: iput-wide v1, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002ddc: fc10 1400 0000 |0024: invoke-custom {v0}, call_site@0014
+002de2: 0b03 |0027: move-result-wide v3
+002de4: 7140 4a00 2143 |0028: invoke-static {v1, v2, v3, v4}, LTestInvocationKinds;.assertEquals:(DD)V // method@004a
+002dea: 0e00 |002b: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=133
+ 0x0007 line=134
+ 0x000c line=135
+ 0x0010 line=136
+ 0x0018 line=137
+ 0x001d line=138
+ 0x0024 line=139
+ 0x002b line=140
+ locals :
+ 0x000c - 0x002c reg=0 instance LTestInvocationKinds;
+
+ #16 : (in LTestInvocationKinds;)
+ name : 'testInvokeVirtual'
type : '()V'
- access : 0x0009 (PUBLIC STATIC)
+ access : 0x0008 (STATIC)
+ code -
+ registers : 3
+ ins : 0
+ outs : 3
+ insns size : 25 16-bit code units
+002dec: |[002dec] TestInvocationKinds.testInvokeVirtual:()V
+002dfc: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e00: 1a01 ba01 |0002: const-string v1, "testInvokeVirtual => max(77, -3) = " // string@01ba
+002e04: 6e20 b000 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002e0a: 2200 0c00 |0007: new-instance v0, LTestInvocationKinds; // type@000c
+002e0e: 7010 4900 0000 |0009: invoke-direct {v0}, LTestInvocationKinds;.<init>:()V // method@0049
+002e14: 1301 4d00 |000c: const/16 v1, #int 77 // #4d
+002e18: 12d2 |000e: const/4 v2, #int -3 // #fd
+002e1a: fc30 1500 1002 |000f: invoke-custom {v0, v1, v2}, call_site@0015
+002e20: 0a01 |0012: move-result v1
+002e22: 6202 1300 |0013: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e26: 6e20 b100 1200 |0015: invoke-virtual {v2, v1}, Ljava/io/PrintStream;.println:(I)V // method@00b1
+002e2c: 0e00 |0018: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=168
+ 0x0007 line=169
+ 0x000c line=170
+ 0x0013 line=171
+ 0x0018 line=172
+ locals :
+ 0x000c - 0x0019 reg=0 receiver LTestInvocationKinds;
+ 0x0013 - 0x0019 reg=1 result I
+
+ #17 : (in LTestInvocationKinds;)
+ name : 'testStaticFieldAccessors'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 47 16-bit code units
+002e30: |[002e30] TestInvocationKinds.testStaticFieldAccessors:()V
+002e40: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e44: 1a01 bb01 |0002: const-string v1, "testStaticFieldAccessors" // string@01bb
+002e48: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002e4e: 1230 |0007: const/4 v0, #int 3 // #3
+002e50: fc10 1600 0000 |0008: invoke-custom {v0}, call_site@0016
+002e56: 6001 0300 |000b: sget v1, LTestInvocationKinds;.static_field:I // field@0003
+002e5a: 7120 4b00 0100 |000d: invoke-static {v1, v0}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e60: 1240 |0010: const/4 v0, #int 4 // #4
+002e62: fc10 1700 0000 |0011: invoke-custom {v0}, call_site@0017
+002e68: 6001 0300 |0014: sget v1, LTestInvocationKinds;.static_field:I // field@0003
+002e6c: 7120 4b00 0100 |0016: invoke-static {v1, v0}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e72: 6000 0300 |0019: sget v0, LTestInvocationKinds;.static_field:I // field@0003
+002e76: fc00 1800 0000 |001b: invoke-custom {}, call_site@0018
+002e7c: 0a01 |001e: move-result v1
+002e7e: 7120 4b00 1000 |001f: invoke-static {v0, v1}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e84: 1400 ffff ff7f |0022: const v0, #float nan // #7fffffff
+002e8a: 6700 0300 |0025: sput v0, LTestInvocationKinds;.static_field:I // field@0003
+002e8e: fc00 1900 0000 |0027: invoke-custom {}, call_site@0019
+002e94: 0a01 |002a: move-result v1
+002e96: 7120 4b00 1000 |002b: invoke-static {v0, v1}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e9c: 0e00 |002e: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=122
+ 0x0007 line=123
+ 0x000b line=124
+ 0x0010 line=125
+ 0x0014 line=126
+ 0x0019 line=127
+ 0x0022 line=128
+ 0x0027 line=129
+ 0x002e line=130
+ locals :
+
+ Virtual methods -
+ #0 : (in LTestInvocationKinds;)
+ name : 'getMaxIntegerValue'
+ type : '(II)I'
+ access : 0x0001 (PUBLIC)
+ code -
+ registers : 4
+ ins : 3
+ outs : 0
+ insns size : 6 16-bit code units
+002b0c: |[002b0c] TestInvocationKinds.getMaxIntegerValue:(II)I
+002b1c: 3732 0400 |0000: if-le v2, v3, 0004 // +0004
+002b20: 0120 |0002: move v0, v2
+002b22: 2802 |0003: goto 0005 // +0002
+002b24: 0130 |0004: move v0, v3
+002b26: 0f00 |0005: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=164
+ locals :
+ 0x0000 - 0x0006 reg=1 this LTestInvocationKinds;
+ 0x0000 - 0x0006 reg=2 x I
+ 0x0000 - 0x0006 reg=3 y I
+
+ source_file_idx : 148 (TestInvocationKinds.java)
+
+Class #9 header:
+class_idx : 14
+access_flags : 1 (0x0001)
+superclass_idx : 9
+interfaces_off : 18256 (0x004750)
+source_file_idx : 149
+annotations_off : 31132 (0x00799c)
+class_data_off : 29344 (0x0072a0)
+static_fields_size : 7
+instance_fields_size: 0
+direct_methods_size : 8
+virtual_methods_size: 1
+
+Class #9 annotations:
+Annotations on field #10 'threadIndex'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "Ljava/lang/ThreadLocal<" "Ljava/lang/Integer;" ">;" }
+Annotations on method #106 'linkerMethod'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #109 'setCalled'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvokeCustomWithConcurrentThreads; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } } fieldOrMethodName="setCalled" parameterTypes={ I } returnType=I
+Annotations on method #110 'test'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #9 -
+ Class descriptor : 'LTestInvokeCustomWithConcurrentThreads;'
+ Access flags : 0x0001 (PUBLIC)
+ Superclass : 'LTestBase;'
+ Interfaces -
+ #0 : 'Ljava/lang/Runnable;'
+ Static fields -
+ #0 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'NUMBER_OF_THREADS'
+ type : 'I'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ value : 16
+ #1 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'barrier'
+ type : 'Ljava/util/concurrent/CyclicBarrier;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ #2 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'called'
+ type : '[Ljava/util/concurrent/atomic/AtomicInteger;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ #3 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'instantiated'
+ type : '[Ljava/lang/invoke/CallSite;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ #4 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'nextIndex'
+ type : 'Ljava/util/concurrent/atomic/AtomicInteger;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ #5 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'targetted'
+ type : '[Ljava/util/concurrent/atomic/AtomicInteger;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ #6 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'threadIndex'
+ type : 'Ljava/lang/ThreadLocal;'
+ access : 0x001a (PRIVATE STATIC FINAL)
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : '<clinit>'
+ type : '()V'
+ access : 0x10008 (STATIC CONSTRUCTOR)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 37 16-bit code units
+003064: |[003064] TestInvokeCustomWithConcurrentThreads.<clinit>:()V
+003074: 2200 3e00 |0000: new-instance v0, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003078: 1201 |0002: const/4 v1, #int 0 // #0
+00307a: 7020 ef00 1000 |0003: invoke-direct {v0, v1}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003080: 6900 0800 |0006: sput-object v0, LTestInvokeCustomWithConcurrentThreads;.nextIndex:Ljava/util/concurrent/atomic/AtomicInteger; // field@0008
+003084: 2200 0d00 |0008: new-instance v0, LTestInvokeCustomWithConcurrentThreads$1; // type@000d
+003088: 7010 6000 0000 |000a: invoke-direct {v0}, LTestInvokeCustomWithConcurrentThreads$1;.<init>:()V // method@0060
+00308e: 6900 0a00 |000d: sput-object v0, LTestInvokeCustomWithConcurrentThreads;.threadIndex:Ljava/lang/ThreadLocal; // field@000a
+003092: 1300 1000 |000f: const/16 v0, #int 16 // #10
+003096: 2301 4b00 |0011: new-array v1, v0, [Ljava/lang/invoke/CallSite; // type@004b
+00309a: 6901 0700 |0013: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00309e: 2301 4c00 |0015: new-array v1, v0, [Ljava/util/concurrent/atomic/AtomicInteger; // type@004c
+0030a2: 6901 0600 |0017: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0030a6: 2301 4c00 |0019: new-array v1, v0, [Ljava/util/concurrent/atomic/AtomicInteger; // type@004c
+0030aa: 6901 0900 |001b: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+0030ae: 2201 3d00 |001d: new-instance v1, Ljava/util/concurrent/CyclicBarrier; // type@003d
+0030b2: 7020 ed00 0100 |001f: invoke-direct {v1, v0}, Ljava/util/concurrent/CyclicBarrier;.<init>:(I)V // method@00ed
+0030b8: 6901 0500 |0022: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.barrier:Ljava/util/concurrent/CyclicBarrier; // field@0005
+0030bc: 0e00 |0024: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=30
+ 0x0008 line=32
+ 0x000f line=41
+ 0x0015 line=44
+ 0x0019 line=47
+ 0x001d line=50
+ locals :
+
+ #1 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : '<init>'
+ type : '()V'
+ access : 0x10002 (PRIVATE CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+0030c0: |[0030c0] TestInvokeCustomWithConcurrentThreads.<init>:()V
+0030d0: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0030d6: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=52
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestInvokeCustomWithConcurrentThreads;
+
+ #2 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'access$000'
+ type : '()Ljava/util/concurrent/atomic/AtomicInteger;'
+ access : 0x1008 (STATIC SYNTHETIC)
+ code -
+ registers : 1
+ ins : 0
+ outs : 0
+ insns size : 3 16-bit code units
+00304c: |[00304c] TestInvokeCustomWithConcurrentThreads.access$000:()Ljava/util/concurrent/atomic/AtomicInteger;
+00305c: 6200 0800 |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.nextIndex:Ljava/util/concurrent/atomic/AtomicInteger; // field@0008
+003060: 1100 |0002: return-object v0
+ catches : (none)
+ positions :
+ 0x0000 line=27
+ locals :
+
+ #3 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'getThreadIndex'
+ type : '()I'
+ access : 0x000a (PRIVATE STATIC)
code -
registers : 1
ins : 0
outs : 1
- insns size : 16 16-bit code units
-001444: |[001444] invokecustom.InvokeCustom.test8:()V
-001454: 1a00 1500 |0000: const-string v0, "First invokedynamic invocation" // string@0015
-001458: fc10 0800 0000 |0002: invoke-custom {v0}, call_site@0008
-00145e: 1a00 4700 |0005: const-string v0, "Second invokedynamic invocation" // string@0047
-001462: fc10 0900 0000 |0007: invoke-custom {v0}, call_site@0009
-001468: 1a00 1000 |000a: const-string v0, "Dupe first invokedynamic invocation" // string@0010
-00146c: fc10 0a00 0000 |000c: invoke-custom {v0}, call_site@000a
-001472: 0e00 |000f: return-void
+ insns size : 13 16-bit code units
+002f00: |[002f00] TestInvokeCustomWithConcurrentThreads.getThreadIndex:()I
+002f10: 6200 0a00 |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.threadIndex:Ljava/lang/ThreadLocal; // field@000a
+002f14: 6e10 d000 0000 |0002: invoke-virtual {v0}, Ljava/lang/ThreadLocal;.get:()Ljava/lang/Object; // method@00d0
+002f1a: 0c00 |0005: move-result-object v0
+002f1c: 1f00 2700 |0006: check-cast v0, Ljava/lang/Integer; // type@0027
+002f20: 6e10 bc00 0000 |0008: invoke-virtual {v0}, Ljava/lang/Integer;.intValue:()I // method@00bc
+002f26: 0a00 |000b: move-result v0
+002f28: 0f00 |000c: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=55
+ locals :
+
+ #4 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'linkerMethod'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 8
+ ins : 3
+ outs : 4
+ insns size : 97 16-bit code units
+002f78: |[002f78] TestInvokeCustomWithConcurrentThreads.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002f88: 1c00 0e00 |0000: const-class v0, LTestInvokeCustomWithConcurrentThreads; // type@000e
+002f8c: 6e40 d800 0576 |0002: invoke-virtual {v5, v0, v6, v7}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+002f92: 0c00 |0005: move-result-object v0
+002f94: 6e10 d400 0000 |0006: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002f9a: 0c01 |0009: move-result-object v1
+002f9c: 7120 6700 1700 |000a: invoke-static {v7, v1}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0067
+002fa2: 6e10 d400 0000 |000d: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002fa8: 0c01 |0010: move-result-object v1
+002faa: 6e10 e300 0100 |0011: invoke-virtual {v1}, Ljava/lang/invoke/MethodType;.parameterCount:()I // method@00e3
+002fb0: 0a01 |0014: move-result v1
+002fb2: 1212 |0015: const/4 v2, #int 1 // #1
+002fb4: 7120 6600 2100 |0016: invoke-static {v1, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+002fba: 2321 4800 |0019: new-array v1, v2, [Ljava/lang/Object; // type@0048
+002fbe: 7100 6900 0000 |001b: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+002fc4: 0a03 |001e: move-result v3
+002fc6: 7110 bd00 0300 |001f: invoke-static {v3}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+002fcc: 0c03 |0022: move-result-object v3
+002fce: 1204 |0023: const/4 v4, #int 0 // #0
+002fd0: 4d03 0104 |0024: aput-object v3, v1, v4
+002fd4: 7130 de00 4001 |0026: invoke-static {v0, v4, v1}, Ljava/lang/invoke/MethodHandles;.insertArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; // method@00de
+002fda: 0c00 |0029: move-result-object v0
+002fdc: 2321 4600 |002a: new-array v1, v2, [Ljava/lang/Class; // type@0046
+002fe0: 6203 1200 |002c: sget-object v3, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+002fe4: 4d03 0104 |002e: aput-object v3, v1, v4
+002fe8: 7130 dd00 4001 |0030: invoke-static {v0, v4, v1}, Ljava/lang/invoke/MethodHandles;.dropArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00dd
+002fee: 0c00 |0033: move-result-object v0
+002ff0: 6e10 d400 0000 |0034: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002ff6: 0c01 |0037: move-result-object v1
+002ff8: 6e10 e300 0100 |0038: invoke-virtual {v1}, Ljava/lang/invoke/MethodType;.parameterCount:()I // method@00e3
+002ffe: 0a01 |003b: move-result v1
+003000: 7120 6600 2100 |003c: invoke-static {v1, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+003006: 6e10 d400 0000 |003f: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+00300c: 0c01 |0042: move-result-object v1
+00300e: 7120 6700 1700 |0043: invoke-static {v7, v1}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0067
+003014: 6201 0500 |0046: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.barrier:Ljava/util/concurrent/CyclicBarrier; // field@0005
+003018: 6e10 ee00 0100 |0048: invoke-virtual {v1}, Ljava/util/concurrent/CyclicBarrier;.await:()I // method@00ee
+00301e: 6201 0700 |004b: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+003022: 7100 6900 0000 |004d: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+003028: 0a02 |0050: move-result v2
+00302a: 2203 3400 |0051: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00302e: 7020 d200 0300 |0053: invoke-direct {v3, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003034: 4d03 0102 |0056: aput-object v3, v1, v2
+003038: 6201 0700 |0058: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00303c: 7100 6900 0000 |005a: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+003042: 0a02 |005d: move-result v2
+003044: 4601 0102 |005e: aget-object v1, v1, v2
+003048: 1101 |0060: return-object v1
catches : (none)
positions :
+ 0x0000 line=87
+ 0x0002 line=88
+ 0x0006 line=89
+ 0x000d line=90
+ 0x0019 line=91
+ 0x002a line=92
+ 0x0034 line=93
+ 0x003f line=94
+ 0x0046 line=99
+ 0x004b line=101
+ 0x0058 line=102
locals :
+ 0x0006 - 0x0061 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0061 reg=5 caller Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0061 reg=6 name Ljava/lang/String;
+ 0x0000 - 0x0061 reg=7 methodType Ljava/lang/invoke/MethodType;
- #28 : (in Linvokecustom/InvokeCustom;)
- name : 'test9'
+ #5 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'notUsed'
+ type : '(I)I'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 1
+ ins : 1
+ outs : 0
+ insns size : 1 16-bit code units
+002f2c: |[002f2c] TestInvokeCustomWithConcurrentThreads.notUsed:(I)I
+002f3c: 0f00 |0000: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=59
+ locals :
+ 0x0000 - 0x0001 reg=0 x I
+
+ #6 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'setCalled'
+ type : '(I)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 1
+ outs : 2
+ insns size : 20 16-bit code units
+002f40: |[002f40] TestInvokeCustomWithConcurrentThreads.setCalled:(I)I
+002f50: 6200 0600 |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+002f54: 4600 0002 |0002: aget-object v0, v0, v2
+002f58: 6e10 f100 0000 |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1
+002f5e: 6200 0900 |0007: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+002f62: 7100 6900 0000 |0009: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+002f68: 0a01 |000c: move-result v1
+002f6a: 4600 0001 |000d: aget-object v0, v0, v1
+002f6e: 6e20 f200 2000 |000f: invoke-virtual {v0, v2}, Ljava/util/concurrent/atomic/AtomicInteger;.set:(I)V // method@00f2
+002f74: 1200 |0012: const/4 v0, #int 0 // #0
+002f76: 0f00 |0013: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=79
+ 0x0007 line=80
+ 0x0012 line=81
+ locals :
+ 0x0000 - 0x0014 reg=2 index I
+
+ #7 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'test'
type : '()V'
access : 0x0009 (PUBLIC STATIC)
code -
- registers : 0
+ registers : 12
ins : 0
- outs : 0
- insns size : 4 16-bit code units
-001474: |[001474] invokecustom.InvokeCustom.test9:()V
-001484: fc00 0d00 0000 |0000: invoke-custom {}, call_site@000d
-00148a: 0e00 |0003: return-void
+ outs : 3
+ insns size : 229 16-bit code units
+0030fc: |[0030fc] TestInvokeCustomWithConcurrentThreads.test:()V
+00310c: 1200 |0000: const/4 v0, #int 0 // #0
+00310e: 0101 |0001: move v1, v0
+003110: 1302 1000 |0002: const/16 v2, #int 16 // #10
+003114: 3521 1700 |0004: if-ge v1, v2, 001b // +0017
+003118: 6202 0600 |0006: sget-object v2, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+00311c: 2203 3e00 |0008: new-instance v3, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003120: 7020 ef00 0300 |000a: invoke-direct {v3, v0}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003126: 4d03 0201 |000d: aput-object v3, v2, v1
+00312a: 6202 0900 |000f: sget-object v2, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+00312e: 2203 3e00 |0011: new-instance v3, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003132: 7020 ef00 0300 |0013: invoke-direct {v3, v0}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003138: 4d03 0201 |0016: aput-object v3, v2, v1
+00313c: d801 0101 |0018: add-int/lit8 v1, v1, #int 1 // #01
+003140: 28e8 |001a: goto 0002 // -0018
+003142: 2321 4a00 |001b: new-array v1, v2, [Ljava/lang/Thread; // type@004a
+003146: 0103 |001d: move v3, v0
+003148: 3523 1600 |001e: if-ge v3, v2, 0034 // +0016
+00314c: 2204 2f00 |0020: new-instance v4, Ljava/lang/Thread; // type@002f
+003150: 2205 0e00 |0022: new-instance v5, LTestInvokeCustomWithConcurrentThreads; // type@000e
+003154: 7010 6400 0500 |0024: invoke-direct {v5}, LTestInvokeCustomWithConcurrentThreads;.<init>:()V // method@0064
+00315a: 7020 cb00 5400 |0027: invoke-direct {v4, v5}, Ljava/lang/Thread;.<init>:(Ljava/lang/Runnable;)V // method@00cb
+003160: 4d04 0103 |002a: aput-object v4, v1, v3
+003164: 4604 0103 |002c: aget-object v4, v1, v3
+003168: 6e10 ce00 0400 |002e: invoke-virtual {v4}, Ljava/lang/Thread;.start:()V // method@00ce
+00316e: d803 0301 |0031: add-int/lit8 v3, v3, #int 1 // #01
+003172: 28eb |0033: goto 001e // -0015
+003174: 0103 |0034: move v3, v0
+003176: 3523 0a00 |0035: if-ge v3, v2, 003f // +000a
+00317a: 4604 0103 |0037: aget-object v4, v1, v3
+00317e: 6e10 cd00 0400 |0039: invoke-virtual {v4}, Ljava/lang/Thread;.join:()V // method@00cd
+003184: d803 0301 |003c: add-int/lit8 v3, v3, #int 1 // #01
+003188: 28f7 |003e: goto 0035 // -0009
+00318a: 1203 |003f: const/4 v3, #int 0 // #0
+00318c: 1204 |0040: const/4 v4, #int 0 // #0
+00318e: 0145 |0041: move v5, v4
+003190: 0134 |0042: move v4, v3
+003192: 0103 |0043: move v3, v0
+003194: 3523 2200 |0044: if-ge v3, v2, 0066 // +0022
+003198: 6206 0700 |0046: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00319c: 4606 0603 |0048: aget-object v6, v6, v3
+0031a0: 1207 |004a: const/4 v7, #int 0 // #0
+0031a2: 7120 6800 7600 |004b: invoke-static {v6, v7}, LTestInvokeCustomWithConcurrentThreads;.assertNotEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0068
+0031a8: 6206 0600 |004e: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0031ac: 4606 0603 |0050: aget-object v6, v6, v3
+0031b0: 6e10 f000 0600 |0052: invoke-virtual {v6}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0031b6: 0a06 |0055: move-result v6
+0031b8: 3806 0d00 |0056: if-eqz v6, 0063 // +000d
+0031bc: d804 0401 |0058: add-int/lit8 v4, v4, #int 1 // #01
+0031c0: 6206 0600 |005a: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0031c4: 4606 0603 |005c: aget-object v6, v6, v3
+0031c8: 6e10 f000 0600 |005e: invoke-virtual {v6}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0031ce: 0a06 |0061: move-result v6
+0031d0: b065 |0062: add-int/2addr v5, v6
+0031d2: d803 0301 |0063: add-int/lit8 v3, v3, #int 1 // #01
+0031d6: 28df |0065: goto 0044 // -0021
+0031d8: 6203 1300 |0066: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0031dc: 2206 2d00 |0068: new-instance v6, Ljava/lang/StringBuilder; // type@002d
+0031e0: 7010 c100 0600 |006a: invoke-direct {v6}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0031e6: 1a07 b800 |006d: const-string v7, "Winners " // string@00b8
+0031ea: 6e20 c800 7600 |006f: invoke-virtual {v6, v7}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0031f0: 6e20 c500 4600 |0072: invoke-virtual {v6, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0031f6: 1a07 0500 |0075: const-string v7, " Votes " // string@0005
+0031fa: 6e20 c800 7600 |0077: invoke-virtual {v6, v7}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003200: 6e20 c500 5600 |007a: invoke-virtual {v6, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+003206: 6e10 ca00 0600 |007d: invoke-virtual {v6}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00320c: 0c06 |0080: move-result-object v6
+00320e: 6e20 b300 6300 |0081: invoke-virtual {v3, v6}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003214: 1223 |0084: const/4 v3, #int 2 // #2
+003216: 1216 |0085: const/4 v6, #int 1 // #1
+003218: 3264 2c00 |0086: if-eq v4, v6, 00b2 // +002c
+00321c: 6207 1300 |0088: sget-object v7, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003220: 1a08 9e00 |008a: const-string v8, "Threads did not the same call-sites:" // string@009e
+003224: 6e20 b300 8700 |008c: invoke-virtual {v7, v8}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+00322a: 0107 |008f: move v7, v0
+00322c: 3527 2200 |0090: if-ge v7, v2, 00b2 // +0022
+003230: 6208 1300 |0092: sget-object v8, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003234: 1a09 0400 |0094: const-string v9, " Thread % 2d invoked call site instance #%02d
+" // string@0004
+003238: 233a 4800 |0096: new-array v10, v3, [Ljava/lang/Object; // type@0048
+00323c: 7110 bd00 0700 |0098: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+003242: 0c0b |009b: move-result-object v11
+003244: 4d0b 0a00 |009c: aput-object v11, v10, v0
+003248: 620b 0900 |009e: sget-object v11, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+00324c: 460b 0b07 |00a0: aget-object v11, v11, v7
+003250: 6e10 f000 0b00 |00a2: invoke-virtual {v11}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+003256: 0a0b |00a5: move-result v11
+003258: 7110 bd00 0b00 |00a6: invoke-static {v11}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00325e: 0c0b |00a9: move-result-object v11
+003260: 4d0b 0a06 |00aa: aput-object v11, v10, v6
+003264: 6e30 ab00 980a |00ac: invoke-virtual {v8, v9, v10}, Ljava/io/PrintStream;.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; // method@00ab
+00326a: d807 0701 |00af: add-int/lit8 v7, v7, #int 1 // #01
+00326e: 28df |00b1: goto 0090 // -0021
+003270: 3225 2c00 |00b2: if-eq v5, v2, 00de // +002c
+003274: 6207 1300 |00b4: sget-object v7, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003278: 1a08 2000 |00b6: const-string v8, "Call-sites invocations :" // string@0020
+00327c: 6e20 b300 8700 |00b8: invoke-virtual {v7, v8}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003282: 0107 |00bb: move v7, v0
+003284: 3527 2200 |00bc: if-ge v7, v2, 00de // +0022
+003288: 6208 1300 |00be: sget-object v8, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00328c: 1a09 0300 |00c0: const-string v9, " Call site instance #%02d was invoked % 2d times
+" // string@0003
+003290: 233a 4800 |00c2: new-array v10, v3, [Ljava/lang/Object; // type@0048
+003294: 7110 bd00 0700 |00c4: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00329a: 0c0b |00c7: move-result-object v11
+00329c: 4d0b 0a00 |00c8: aput-object v11, v10, v0
+0032a0: 620b 0600 |00ca: sget-object v11, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0032a4: 460b 0b07 |00cc: aget-object v11, v11, v7
+0032a8: 6e10 f000 0b00 |00ce: invoke-virtual {v11}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0032ae: 0a0b |00d1: move-result v11
+0032b0: 7110 bd00 0b00 |00d2: invoke-static {v11}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+0032b6: 0c0b |00d5: move-result-object v11
+0032b8: 4d0b 0a06 |00d6: aput-object v11, v10, v6
+0032bc: 6e30 ab00 980a |00d8: invoke-virtual {v8, v9, v10}, Ljava/io/PrintStream;.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; // method@00ab
+0032c2: d807 0701 |00db: add-int/lit8 v7, v7, #int 1 // #01
+0032c6: 28df |00dd: goto 00bc // -0021
+0032c8: 7120 6600 6400 |00de: invoke-static {v4, v6}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+0032ce: 7120 6600 2500 |00e1: invoke-static {v5, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+0032d4: 0e00 |00e4: return-void
catches : (none)
positions :
+ 0x0000 line=107
+ 0x0006 line=108
+ 0x000f line=109
+ 0x0018 line=107
+ 0x001b line=113
+ 0x001d line=114
+ 0x0020 line=115
+ 0x002c line=116
+ 0x0031 line=114
+ 0x0034 line=120
+ 0x0037 line=121
+ 0x003c line=120
+ 0x003f line=125
+ 0x0040 line=126
+ 0x0041 line=127
+ 0x0046 line=128
+ 0x004e line=129
+ 0x0058 line=130
+ 0x005a line=131
+ 0x0063 line=127
+ 0x0066 line=135
+ 0x0084 line=139
+ 0x0088 line=140
+ 0x008f line=141
+ 0x0092 line=142
+ 0x0098 line=143
+ 0x00ac line=142
+ 0x00af line=141
+ 0x00b2 line=149
+ 0x00b4 line=150
+ 0x00bb line=151
+ 0x00be line=152
+ 0x00c4 line=153
+ 0x00d8 line=152
+ 0x00db line=151
+ 0x00de line=157
+ 0x00e1 line=158
+ 0x00e4 line=159
locals :
+ 0x0002 - 0x001b reg=1 i I
+ 0x001e - 0x0034 reg=3 i I
+ 0x0035 - 0x003f reg=3 i I
+ 0x0040 - 0x0044 reg=3 winners I
+ 0x0041 - 0x0044 reg=4 votes I
+ 0x0044 - 0x0066 reg=3 i I
+ 0x0090 - 0x00b2 reg=7 i I
+ 0x00bc - 0x00de reg=7 i I
+ 0x001d - 0x00e5 reg=1 threads [Ljava/lang/Thread;
+ 0x0044 - 0x00e5 reg=4 winners I
+ 0x0044 - 0x00e5 reg=5 votes I
Virtual methods -
- #0 : (in Linvokecustom/InvokeCustom;)
- name : 'helperMethodTest9'
+ #0 : (in LTestInvokeCustomWithConcurrentThreads;)
+ name : 'run'
type : '()V'
access : 0x0001 (PUBLIC)
code -
- registers : 4
+ registers : 2
ins : 1
+ outs : 1
+ insns size : 9 16-bit code units
+0030d8: |[0030d8] TestInvokeCustomWithConcurrentThreads.run:()V
+0030e8: 12f0 |0000: const/4 v0, #int -1 // #ff
+0030ea: fc10 1a00 0000 |0001: invoke-custom {v0}, call_site@001a
+0030f0: 0a00 |0004: move-result v0
+0030f2: 7110 6b00 0000 |0005: invoke-static {v0}, LTestInvokeCustomWithConcurrentThreads;.notUsed:(I)I // method@006b
+0030f8: 0e00 |0008: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=63
+ 0x0005 line=64
+ 0x0008 line=65
+ locals :
+ 0x0005 - 0x0009 reg=0 x I
+ 0x0000 - 0x0009 reg=1 this LTestInvokeCustomWithConcurrentThreads;
+
+ source_file_idx : 149 (TestInvokeCustomWithConcurrentThreads.java)
+
+Class #10 header:
+class_idx : 15
+access_flags : 1 (0x0001)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 151
+annotations_off : 31180 (0x0079cc)
+class_data_off : 29403 (0x0072db)
+static_fields_size : 5
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 0
+
+Class #10 annotations:
+Annotations on method #114 'add'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestLinkerMethodMinimalArguments; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } } fieldOrMethodName="_add" parameterTypes={ I I } returnType=I
+Annotations on method #118 'linkerMethod'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #119 'test'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #10 -
+ Class descriptor : 'LTestLinkerMethodMinimalArguments;'
+ Access flags : 0x0001 (PUBLIC)
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ #0 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL'
+ type : 'I'
+ access : 0x0018 (STATIC FINAL)
+ value : 1
+ #1 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'FAILURE_TYPE_LINKER_METHOD_THROWS'
+ type : 'I'
+ access : 0x0018 (STATIC FINAL)
+ value : 2
+ #2 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'FAILURE_TYPE_NONE'
+ type : 'I'
+ access : 0x0018 (STATIC FINAL)
+ value : 0
+ #3 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'FAILURE_TYPE_TARGET_METHOD_THROWS'
+ type : 'I'
+ access : 0x0018 (STATIC FINAL)
+ value : 3
+ #4 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'forceFailureType'
+ type : 'I'
+ access : 0x000a (PRIVATE STATIC)
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestLinkerMethodMinimalArguments;)
+ name : '<clinit>'
+ type : '()V'
+ access : 0x10008 (STATIC CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003404: |[003404] TestLinkerMethodMinimalArguments.<clinit>:()V
+003414: 1200 |0000: const/4 v0, #int 0 // #0
+003416: 6700 0f00 |0001: sput v0, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+00341a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=26
+ locals :
+
+ #1 : (in LTestLinkerMethodMinimalArguments;)
+ name : '<init>'
+ type : '()V'
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+00341c: |[00341c] TestLinkerMethodMinimalArguments.<init>:()V
+00342c: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003432: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=25
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestLinkerMethodMinimalArguments;
+
+ #2 : (in LTestLinkerMethodMinimalArguments;)
+ name : '_add'
+ type : '(II)I'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 4
+ ins : 2
outs : 2
- insns size : 27 16-bit code units
-00148c: |[00148c] invokecustom.InvokeCustom.helperMethodTest9:()V
-00149c: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0014a0: 2201 1000 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0010
-0014a4: 7010 3000 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0030
-0014aa: 1a02 7300 |0007: const-string v2, "helperMethodTest9 in " // string@0073
-0014ae: 6e20 3600 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0036
-0014b4: 0c01 |000c: move-result-object v1
-0014b6: 1c02 0700 |000d: const-class v2, Linvokecustom/InvokeCustom; // type@0007
-0014ba: 6e20 3500 2100 |000f: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@0035
-0014c0: 0c01 |0012: move-result-object v1
-0014c2: 6e10 3700 0100 |0013: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0037
-0014c8: 0c01 |0016: move-result-object v1
-0014ca: 6e20 2900 1000 |0017: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0014d0: 0e00 |001a: return-void
- catches : (none)
- positions :
- 0x0000 line=129
- 0x001a line=130
- locals :
- 0x0000 - 0x001b reg=3 this Linvokecustom/InvokeCustom;
-
- #1 : (in Linvokecustom/InvokeCustom;)
- name : 'run'
+ insns size : 23 16-bit code units
+0032d8: |[0032d8] TestLinkerMethodMinimalArguments._add:(II)I
+0032e8: 6000 0f00 |0000: sget v0, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+0032ec: 1231 |0002: const/4 v1, #int 3 // #3
+0032ee: 3210 0500 |0003: if-eq v0, v1, 0008 // +0005
+0032f2: 9000 0203 |0005: add-int v0, v2, v3
+0032f6: 0f00 |0007: return v0
+0032f8: 6200 1300 |0008: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0032fc: 1a01 a000 |000a: const-string v1, "Throwing ArithmeticException in add()" // string@00a0
+003300: 6e20 b300 1000 |000c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003306: 2200 1d00 |000f: new-instance v0, Ljava/lang/ArithmeticException; // type@001d
+00330a: 1a01 cc00 |0011: const-string v1, "add" // string@00cc
+00330e: 7020 b400 1000 |0013: invoke-direct {v0, v1}, Ljava/lang/ArithmeticException;.<init>:(Ljava/lang/String;)V // method@00b4
+003314: 2700 |0016: throw v0
+ catches : (none)
+ positions :
+ 0x0000 line=51
+ 0x0005 line=55
+ 0x0008 line=52
+ 0x000f line=53
+ locals :
+ 0x0000 - 0x0017 reg=2 a I
+ 0x0000 - 0x0017 reg=3 b I
+
+ #3 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'add'
+ type : '(II)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 5 16-bit code units
+003318: |[003318] TestLinkerMethodMinimalArguments.add:(II)I
+003328: 7100 7400 0000 |0000: invoke-static {}, LTestLinkerMethodMinimalArguments;.assertNotReached:()V // method@0074
+00332e: 12f0 |0003: const/4 v0, #int -1 // #ff
+003330: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=45
+ 0x0003 line=46
+ locals :
+ 0x0000 - 0x0005 reg=1 a I
+ 0x0000 - 0x0005 reg=2 b I
+
+ #4 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'linkerMethod'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 7
+ ins : 3
+ outs : 4
+ insns size : 96 16-bit code units
+003334: |[003334] TestLinkerMethodMinimalArguments.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+003344: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003348: 2201 2d00 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00334c: 7010 c100 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+003352: 1a02 6701 |0007: const-string v2, "linkerMethod failure type " // string@0167
+003356: 6e20 c800 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00335c: 6002 0f00 |000c: sget v2, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+003360: 6e20 c500 2100 |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+003366: 6e10 ca00 0100 |0011: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00336c: 0c01 |0014: move-result-object v1
+00336e: 6e20 b300 1000 |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003374: 1c00 0f00 |0018: const-class v0, LTestLinkerMethodMinimalArguments; // type@000f
+003378: 6e40 d800 0465 |001a: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+00337e: 0c00 |001d: move-result-object v0
+003380: 6001 0f00 |001e: sget v1, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+003384: 2b01 3800 0000 |0020: packed-switch v1, 00000058 // +00000038
+00338a: 2201 3400 |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00338e: 7020 d200 0100 |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003394: 1101 |0028: return-object v1
+003396: 6201 1300 |0029: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00339a: 1a02 a100 |002b: const-string v2, "Throwing InstantiationException in linkerMethod()" // string@00a1
+00339e: 6e20 b300 2100 |002d: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0033a4: 2201 2600 |0030: new-instance v1, Ljava/lang/InstantiationException; // type@0026
+0033a8: 1a02 6601 |0032: const-string v2, "linkerMethod" // string@0166
+0033ac: 7020 bb00 2100 |0034: invoke-direct {v1, v2}, Ljava/lang/InstantiationException;.<init>:(Ljava/lang/String;)V // method@00bb
+0033b2: 2701 |0037: throw v1
+0033b4: 6201 1300 |0038: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0033b8: 2202 2d00 |003a: new-instance v2, Ljava/lang/StringBuilder; // type@002d
+0033bc: 7010 c100 0200 |003c: invoke-direct {v2}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0033c2: 1a03 8c00 |003f: const-string v3, "Returning null instead of CallSite for " // string@008c
+0033c6: 6e20 c800 3200 |0041: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033cc: 6e20 c800 5200 |0044: invoke-virtual {v2, v5}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033d2: 1a03 0000 |0047: const-string v3, " " // string@0000
+0033d6: 6e20 c800 3200 |0049: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033dc: 6e20 c700 6200 |004c: invoke-virtual {v2, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+0033e2: 6e10 ca00 0200 |004f: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0033e8: 0c02 |0052: move-result-object v2
+0033ea: 6e20 b300 2100 |0053: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0033f0: 1201 |0056: const/4 v1, #int 0 // #0
+0033f2: 1101 |0057: return-object v1
+0033f4: 0001 0200 0100 0000 1800 0000 0900 ... |0058: packed-switch-data (8 units)
+ catches : (none)
+ positions :
+ 0x0000 line=61
+ 0x0018 line=62
+ 0x001a line=63
+ 0x001e line=64
+ 0x0023 line=73
+ 0x0029 line=70
+ 0x0030 line=71
+ 0x0038 line=66
+ 0x0056 line=68
+ locals :
+ 0x001e - 0x0060 reg=0 mh_add Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0060 reg=4 caller Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0060 reg=5 name Ljava/lang/String;
+ 0x0000 - 0x0060 reg=6 methodType Ljava/lang/invoke/MethodType;
+
+ #5 : (in LTestLinkerMethodMinimalArguments;)
+ name : 'test'
+ type : '(III)V'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 6
+ ins : 3
+ outs : 2
+ insns size : 68 16-bit code units
+003434: |[003434] TestLinkerMethodMinimalArguments.test:(III)V
+003444: 1200 |0000: const/4 v0, #int 0 // #0
+003446: 1211 |0001: const/4 v1, #int 1 // #1
+003448: 3a03 0400 |0002: if-ltz v3, 0006 // +0004
+00344c: 0112 |0004: move v2, v1
+00344e: 2802 |0005: goto 0007 // +0002
+003450: 0102 |0006: move v2, v0
+003452: 7110 7500 0200 |0007: invoke-static {v2}, LTestLinkerMethodMinimalArguments;.assertTrue:(Z)V // method@0075
+003458: 1232 |000a: const/4 v2, #int 3 // #3
+00345a: 3623 0400 |000b: if-gt v3, v2, 000f // +0004
+00345e: 0110 |000d: move v0, v1
+003460: 0000 |000e: nop // spacer
+003462: 7110 7500 0000 |000f: invoke-static {v0}, LTestLinkerMethodMinimalArguments;.assertTrue:(Z)V // method@0075
+003468: 6703 0f00 |0012: sput v3, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+00346c: 9000 0405 |0014: add-int v0, v4, v5
+003470: fc20 1b00 5400 |0016: invoke-custom {v4, v5}, call_site@001b
+003476: 0a01 |0019: move-result v1
+003478: 7120 7300 1000 |001a: invoke-static {v0, v1}, LTestLinkerMethodMinimalArguments;.assertEquals:(II)V // method@0073
+00347e: 6200 1300 |001d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003482: 2201 2d00 |001f: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+003486: 7010 c100 0100 |0021: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00348c: 1a02 2a00 |0024: const-string v2, "Failure Type + " // string@002a
+003490: 6e20 c800 2100 |0026: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003496: 6e20 c500 3100 |0029: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+00349c: 1a02 0100 |002c: const-string v2, " (" // string@0001
+0034a0: 6e20 c800 2100 |002e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0034a6: 6e20 c500 4100 |0031: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0034ac: 6e20 c500 5100 |0034: invoke-virtual {v1, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0034b2: 1a02 0700 |0037: const-string v2, ")" // string@0007
+0034b6: 6e20 c800 2100 |0039: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0034bc: 6e10 ca00 0100 |003c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0034c2: 0c01 |003f: move-result-object v1
+0034c4: 6e20 b300 1000 |0040: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0034ca: 0e00 |0043: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=78
+ 0x000a line=79
+ 0x0012 line=80
+ 0x0014 line=81
+ 0x001d line=82
+ 0x0043 line=83
+ locals :
+ 0x0000 - 0x0044 reg=3 failureType I
+ 0x0000 - 0x0044 reg=4 x I
+ 0x0000 - 0x0044 reg=5 y I
+
+ Virtual methods -
+ source_file_idx : 151 (TestLinkerMethodMinimalArguments.java)
+
+Class #11 header:
+class_idx : 16
+access_flags : 1 (0x0001)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 153
+annotations_off : 31220 (0x0079f4)
+class_data_off : 29445 (0x007305)
+static_fields_size : 1
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 1
+
+Class #11 annotations:
+Annotations on method #124 'add'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestLinkerMethodMultipleArgumentTypes; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I I I I I F D Ljava/lang/String; Ljava/lang/Class; J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; intValue={ 97 } Lannotations/Constant; intValue={ 1024 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; floatValue={ 11.1 } Lannotations/Constant; doubleValue={ 2.2 } Lannotations/Constant; stringValue={ "Hello" } Lannotations/Constant; classValue={ LTestLinkerMethodMultipleArgumentTypes; } Lannotations/Constant; longValue={ 123456789 } } fieldOrMethodName="_add" parameterTypes={ I I } returnType=I
+Annotations on method #131 'linkerMethod'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "IIIIIFD" "Ljava/lang/String;" "Ljava/lang/Class<" "*>;J)" "Ljava/lang/invoke/CallSite;" }
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #132 'test'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #11 -
+ Class descriptor : 'LTestLinkerMethodMultipleArgumentTypes;'
+ Access flags : 0x0001 (PUBLIC)
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ #0 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : 'bootstrapRunCount'
+ type : 'I'
+ access : 0x000a (PRIVATE STATIC)
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : '<clinit>'
+ type : '()V'
+ access : 0x10008 (STATIC CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003618: |[003618] TestLinkerMethodMultipleArgumentTypes.<clinit>:()V
+003628: 1200 |0000: const/4 v0, #int 0 // #0
+00362a: 6700 1000 |0001: sput v0, LTestLinkerMethodMultipleArgumentTypes;.bootstrapRunCount:I // field@0010
+00362e: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=28
+ locals :
+
+ #1 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : '<init>'
type : '()V'
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+003630: |[003630] TestLinkerMethodMultipleArgumentTypes.<init>:()V
+003640: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003646: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=26
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestLinkerMethodMultipleArgumentTypes;
+
+ #2 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : '_add'
+ type : '(II)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 3 16-bit code units
+0034e4: |[0034e4] TestLinkerMethodMultipleArgumentTypes._add:(II)I
+0034f4: 9000 0102 |0000: add-int v0, v1, v2
+0034f8: 0f00 |0002: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=74
+ locals :
+ 0x0000 - 0x0003 reg=1 a I
+ 0x0000 - 0x0003 reg=2 b I
+
+ #3 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : 'add'
+ type : '(II)I'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 5 16-bit code units
+0034fc: |[0034fc] TestLinkerMethodMultipleArgumentTypes.add:(II)I
+00350c: 7100 8200 0000 |0000: invoke-static {}, LTestLinkerMethodMultipleArgumentTypes;.assertNotReached:()V // method@0082
+003512: 12f0 |0003: const/4 v0, #int -1 // #ff
+003514: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=68
+ 0x0003 line=69
+ locals :
+ 0x0000 - 0x0005 reg=1 a I
+ 0x0000 - 0x0005 reg=2 b I
+
+ #4 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : 'linkerMethod'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 31
+ ins : 15
+ outs : 4
+ insns size : 119 16-bit code units
+003518: |[003518] TestLinkerMethodMultipleArgumentTypes.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;
+003528: 0800 1100 |0000: move-object/from16 v0, v17
+00352c: 0801 1200 |0002: move-object/from16 v1, v18
+003530: 6202 1300 |0004: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003534: 2203 2d00 |0006: new-instance v3, Ljava/lang/StringBuilder; // type@002d
+003538: 7010 c100 0300 |0008: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00353e: 1a04 6100 |000b: const-string v4, "Linking " // string@0061
+003542: 6e20 c800 4300 |000d: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003548: 6e20 c800 0300 |0010: invoke-virtual {v3, v0}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00354e: 1a04 0000 |0013: const-string v4, " " // string@0000
+003552: 6e20 c800 4300 |0015: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003558: 6e20 c700 1300 |0018: invoke-virtual {v3, v1}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00355e: 6e10 ca00 0300 |001b: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+003564: 0c03 |001e: move-result-object v3
+003566: 6e20 b300 3200 |001f: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+00356c: 12f2 |0022: const/4 v2, #int -1 // #ff
+00356e: 0203 1300 |0023: move/from16 v3, v19
+003572: 7120 7f00 3200 |0025: invoke-static {v2, v3}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003578: 1212 |0028: const/4 v2, #int 1 // #1
+00357a: 0204 1400 |0029: move/from16 v4, v20
+00357e: 7120 7f00 4200 |002b: invoke-static {v2, v4}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003584: 1305 6100 |002e: const/16 v5, #int 97 // #61
+003588: 0206 1500 |0030: move/from16 v6, v21
+00358c: 7120 7f00 6500 |0032: invoke-static {v5, v6}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003592: 1305 0004 |0035: const/16 v5, #int 1024 // #400
+003596: 0207 1600 |0037: move/from16 v7, v22
+00359a: 7120 7f00 7500 |0039: invoke-static {v5, v7}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+0035a0: 0205 1700 |003c: move/from16 v5, v23
+0035a4: 7120 7f00 5200 |003e: invoke-static {v2, v5}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+0035aa: 1402 9a99 3141 |0041: const v2, #float 11.1 // #4131999a
+0035b0: 0208 1800 |0044: move/from16 v8, v24
+0035b4: 7120 7e00 8200 |0046: invoke-static {v2, v8}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(FF)V // method@007e
+0035ba: 1809 9a99 9999 9999 0140 |0049: const-wide v9, #double 2.2 // #400199999999999a
+0035c4: 050b 1900 |004e: move-wide/from16 v11, v25
+0035c8: 7140 7d00 a9cb |0050: invoke-static {v9, v10, v11, v12}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(DD)V // method@007d
+0035ce: 1a02 2c00 |0053: const-string v2, "Hello" // string@002c
+0035d2: 0809 1b00 |0055: move-object/from16 v9, v27
+0035d6: 7120 8100 9200 |0057: invoke-static {v2, v9}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0081
+0035dc: 1c02 1000 |005a: const-class v2, LTestLinkerMethodMultipleArgumentTypes; // type@0010
+0035e0: 080a 1c00 |005c: move-object/from16 v10, v28
+0035e4: 7120 8100 a200 |005e: invoke-static {v2, v10}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0081
+0035ea: 170d 15cd 5b07 |0061: const-wide/32 v13, #float 1.6536e-34 // #075bcd15
+0035f0: 0502 1d00 |0064: move-wide/from16 v2, v29
+0035f4: 7140 8000 ed32 |0066: invoke-static {v13, v14, v2, v3}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(JJ)V // method@0080
+0035fa: 1c0d 1000 |0069: const-class v13, LTestLinkerMethodMultipleArgumentTypes; // type@0010
+0035fe: 080e 1000 |006b: move-object/from16 v14, v16
+003602: 6e40 d800 de10 |006d: invoke-virtual {v14, v13, v0, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003608: 0c0d |0070: move-result-object v13
+00360a: 220f 3400 |0071: new-instance v15, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00360e: 7020 d200 df00 |0073: invoke-direct {v15, v13}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003614: 110f |0076: return-object v15
+ catches : (none)
+ positions :
+ 0x0000 line=93
+ 0x0022 line=94
+ 0x0028 line=95
+ 0x002e line=96
+ 0x0035 line=97
+ 0x003c line=98
+ 0x0041 line=99
+ 0x0049 line=100
+ 0x0053 line=101
+ 0x005a line=102
+ 0x0061 line=103
+ 0x0069 line=104
+ 0x006b line=105
+ 0x0071 line=106
+ locals :
+ 0x0000 - 0x0000 reg=28 (null) Ljava/lang/Class;
+ 0x0071 - 0x0077 reg=13 mh_add Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0077 reg=16 caller Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0077 reg=17 name Ljava/lang/String;
+ 0x0000 - 0x0077 reg=18 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0077 reg=19 v1 I
+ 0x0000 - 0x0077 reg=20 v2 I
+ 0x0000 - 0x0077 reg=21 v3 I
+ 0x0000 - 0x0077 reg=22 v4 I
+ 0x0000 - 0x0077 reg=23 v5 I
+ 0x0000 - 0x0077 reg=24 v6 F
+ 0x0000 - 0x0077 reg=25 v7 D
+ 0x0000 - 0x0077 reg=27 v8 Ljava/lang/String;
+ 0x0000 - 0x0077 reg=28 v9 Ljava/lang/Class; Ljava/lang/Class<*>;
+ 0x0000 - 0x0077 reg=29 v10 J
+
+ #5 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : 'test'
+ type : '(II)V'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 4
+ ins : 2
+ outs : 2
+ insns size : 17 16-bit code units
+003648: |[003648] TestLinkerMethodMultipleArgumentTypes.test:(II)V
+003658: 9000 0203 |0000: add-int v0, v2, v3
+00365c: fc20 1c00 3200 |0002: invoke-custom {v2, v3}, call_site@001c
+003662: 0a01 |0005: move-result v1
+003664: 7120 7f00 1000 |0006: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+00366a: 6200 1300 |0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00366e: 9001 0203 |000b: add-int v1, v2, v3
+003672: 6e20 b100 1000 |000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V // method@00b1
+003678: 0e00 |0010: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=114
+ 0x0009 line=115
+ 0x0010 line=116
+ locals :
+ 0x0000 - 0x0011 reg=2 x I
+ 0x0000 - 0x0011 reg=3 y I
+
+ Virtual methods -
+ #0 : (in LTestLinkerMethodMultipleArgumentTypes;)
+ name : 'GetBootstrapRunCount'
+ type : '()I'
access : 0x0001 (PUBLIC)
code -
+ registers : 2
+ ins : 1
+ outs : 0
+ insns size : 3 16-bit code units
+0034cc: |[0034cc] TestLinkerMethodMultipleArgumentTypes.GetBootstrapRunCount:()I
+0034dc: 6000 1000 |0000: sget v0, LTestLinkerMethodMultipleArgumentTypes;.bootstrapRunCount:I // field@0010
+0034e0: 0f00 |0002: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=110
+ locals :
+ 0x0000 - 0x0003 reg=1 this LTestLinkerMethodMultipleArgumentTypes;
+
+ source_file_idx : 153 (TestLinkerMethodMultipleArgumentTypes.java)
+
+Class #12 header:
+class_idx : 17
+access_flags : 0 (0x0000)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 154
+annotations_off : 31260 (0x007a1c)
+class_data_off : 29483 (0x00732b)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 0
+
+Class #12 annotations:
+Annotations on method #136 'addf'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LUnrelatedBSM; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ LTestLinkerUnrelatedBSM; } } fieldOrMethodName="_addf" parameterTypes={ F F } returnType=F
+Annotations on method #139 'subf'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LUnrelatedBSM; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ LTestLinkerUnrelatedBSM; } } fieldOrMethodName="_subf" parameterTypes={ F F } returnType=F
+
+Class #12 -
+ Class descriptor : 'LTestLinkerUnrelatedBSM;'
+ Access flags : 0x0000 ()
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestLinkerUnrelatedBSM;)
+ name : '<init>'
+ type : '()V'
+ access : 0x10000 (CONSTRUCTOR)
+ code -
+ registers : 1
+ ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+0036e4: |[0036e4] TestLinkerUnrelatedBSM.<init>:()V
+0036f4: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0036fa: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=23
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestLinkerUnrelatedBSM;
+
+ #1 : (in LTestLinkerUnrelatedBSM;)
+ name : '_addf'
+ type : '(FF)F'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 3 16-bit code units
+00367c: |[00367c] TestLinkerUnrelatedBSM._addf:(FF)F
+00368c: a600 0102 |0000: add-float v0, v1, v2
+003690: 0f00 |0002: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=47
+ locals :
+ 0x0000 - 0x0003 reg=1 a F
+ 0x0000 - 0x0003 reg=2 b F
+
+ #2 : (in LTestLinkerUnrelatedBSM;)
+ name : '_subf'
+ type : '(FF)F'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 3 16-bit code units
+003694: |[003694] TestLinkerUnrelatedBSM._subf:(FF)F
+0036a4: a700 0102 |0000: sub-float v0, v1, v2
+0036a8: 0f00 |0002: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=73
+ locals :
+ 0x0000 - 0x0003 reg=1 a F
+ 0x0000 - 0x0003 reg=2 b F
+
+ #3 : (in LTestLinkerUnrelatedBSM;)
+ name : 'addf'
+ type : '(FF)F'
+ access : 0x000a (PRIVATE STATIC)
+ code -
registers : 3
+ ins : 2
+ outs : 0
+ insns size : 5 16-bit code units
+0036ac: |[0036ac] TestLinkerUnrelatedBSM.addf:(FF)F
+0036bc: 7100 8a00 0000 |0000: invoke-static {}, LTestLinkerUnrelatedBSM;.assertNotReached:()V // method@008a
+0036c2: 1210 |0003: const/4 v0, #int 1 // #1
+0036c4: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=42
+ 0x0003 line=43
+ locals :
+ 0x0000 - 0x0005 reg=1 a F
+ 0x0000 - 0x0005 reg=2 b F
+
+ #4 : (in LTestLinkerUnrelatedBSM;)
+ name : 'subf'
+ type : '(FF)F'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 3
+ ins : 2
+ outs : 0
+ insns size : 5 16-bit code units
+0036c8: |[0036c8] TestLinkerUnrelatedBSM.subf:(FF)F
+0036d8: 7100 8a00 0000 |0000: invoke-static {}, LTestLinkerUnrelatedBSM;.assertNotReached:()V // method@008a
+0036de: 1210 |0003: const/4 v0, #int 1 // #1
+0036e0: 0f00 |0004: return v0
+ catches : (none)
+ positions :
+ 0x0000 line=68
+ 0x0003 line=69
+ locals :
+ 0x0000 - 0x0005 reg=1 a F
+ 0x0000 - 0x0005 reg=2 b F
+
+ #5 : (in LTestLinkerUnrelatedBSM;)
+ name : 'test'
+ type : '()V'
+ access : 0x0009 (PUBLIC STATIC)
+ code -
+ registers : 4
+ ins : 0
+ outs : 2
+ insns size : 34 16-bit code units
+0036fc: |[0036fc] TestLinkerUnrelatedBSM.test:()V
+00370c: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003710: 1c01 1100 |0002: const-class v1, LTestLinkerUnrelatedBSM; // type@0011
+003714: 6e10 b700 0100 |0004: invoke-virtual {v1}, Ljava/lang/Class;.getName:()Ljava/lang/String; // method@00b7
+00371a: 0c01 |0007: move-result-object v1
+00371c: 6e20 b300 1000 |0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003722: 1500 003f |000b: const/high16 v0, #int 1056964608 // #3f00
+003726: 1501 0040 |000d: const/high16 v1, #int 1073741824 // #4000
+00372a: fc20 1d00 0100 |000f: invoke-custom {v1, v0}, call_site@001d
+003730: 0a02 |0012: move-result v2
+003732: 1503 2040 |0013: const/high16 v3, #int 1075838976 // #4020
+003736: 7120 8900 2300 |0015: invoke-static {v3, v2}, LTestLinkerUnrelatedBSM;.assertEquals:(FF)V // method@0089
+00373c: fc20 1e00 0100 |0018: invoke-custom {v1, v0}, call_site@001e
+003742: 0a00 |001b: move-result v0
+003744: 1501 c03f |001c: const/high16 v1, #int 1069547520 // #3fc0
+003748: 7120 8900 0100 |001e: invoke-static {v1, v0}, LTestLinkerUnrelatedBSM;.assertEquals:(FF)V // method@0089
+00374e: 0e00 |0021: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=77
+ 0x000b line=78
+ 0x0018 line=79
+ 0x0021 line=80
+ locals :
+
+ Virtual methods -
+ source_file_idx : 154 (TestLinkerUnrelatedBSM.java)
+
+Class #13 header:
+class_idx : 18
+access_flags : 1 (0x0001)
+superclass_idx : 9
+interfaces_off : 0 (0x000000)
+source_file_idx : 156
+annotations_off : 31292 (0x007a3c)
+class_data_off : 29514 (0x00734a)
+static_fields_size : 0
+instance_fields_size: 0
+direct_methods_size : 27
+virtual_methods_size: 0
+
+Class #13 annotations:
+Annotations on method #143 'bsmWithBoxedArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #144 'bsmWithClassAndFloatArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "Ljava/lang/Class<" "*>;[F)" "Ljava/lang/invoke/CallSite;" }
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #145 'bsmWithClassArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #146 'bsmWithDoubleArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #147 'bsmWithFloatAndLongArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #148 'bsmWithIntAndStringArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #149 'bsmWithLongAndIntArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #150 'bsmWithStringArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #151 'bsmWithWiderArray'
+ VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #152 'methodA'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "Aachen" } Lannotations/Constant; stringValue={ "Aalborg" } Lannotations/Constant; stringValue={ "Aalto" } } fieldOrMethodName="methodA"
+Annotations on method #153 'methodB'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "barium" } } fieldOrMethodName="methodB"
+Annotations on method #154 'methodC'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } fieldOrMethodName="methodC"
+Annotations on method #155 'methodD'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 101 } Lannotations/Constant; stringValue={ "zoo" } Lannotations/Constant; stringValue={ "zoogene" } Lannotations/Constant; stringValue={ "zoogenic" } } fieldOrMethodName="methodD"
+Annotations on method #156 'methodE'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 102 } Lannotations/Constant; stringValue={ "zonic" } } fieldOrMethodName="methodE"
+Annotations on method #157 'methodF'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } } fieldOrMethodName="methodF"
+Annotations on method #158 'methodG'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithLongAndIntArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; J [I } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; longValue={ 81985529216486895 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; intValue={ -1 } Lannotations/Constant; intValue={ 2 } Lannotations/Constant; intValue={ -2 } } fieldOrMethodName="methodG"
+Annotations on method #159 'methodH'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithFloatAndLongArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; F [J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; floatValue={ -2.71828 } Lannotations/Constant; longValue={ 999999999999 } Lannotations/Constant; longValue={ -8888888888888 } } fieldOrMethodName="methodH"
+Annotations on method #160 'methodI'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithClassAndFloatArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; [F } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ Ljava/lang/Throwable; } Lannotations/Constant; floatValue={ 3.40282e+38 } Lannotations/Constant; floatValue={ 1.4013e-45 } Lannotations/Constant; floatValue={ 3.14159 } Lannotations/Constant; floatValue={ -3.14159 } } fieldOrMethodName="methodI"
+Annotations on method #161 'methodJ'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithDoubleArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [D } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; doubleValue={ 4.94066e-324 } Lannotations/Constant; doubleValue={ 2.71828 } Lannotations/Constant; doubleValue={ -3.14159 } } fieldOrMethodName="methodJ"
+Annotations on method #162 'methodK'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithClassArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ Ljava/lang/Integer; } Lannotations/Constant; classValue={ Ljava/lang/invoke/MethodHandles; } Lannotations/Constant; classValue={ Ljava/util/Arrays; } } fieldOrMethodName="methodK"
+Annotations on method #163 'methodO'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; intValue={ 104 } } fieldOrMethodName="methodO"
+Annotations on method #164 'methodP'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; stringValue={ "A" } Lannotations/Constant; stringValue={ "B" } Lannotations/Constant; intValue={ 42 } } fieldOrMethodName="methodP"
+Annotations on method #165 'methodQ'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithWiderArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; intValue={ 42 } } fieldOrMethodName="methodQ"
+Annotations on method #166 'methodR'
+ VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithBoxedArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/Integer; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 1030 } Lannotations/Constant; intValue={ 420 } } fieldOrMethodName="methodR"
+
+Class #13 -
+ Class descriptor : 'LTestVariableArityLinkerMethod;'
+ Access flags : 0x0001 (PUBLIC)
+ Superclass : 'LTestBase;'
+ Interfaces -
+ Static fields -
+ Instance fields -
+ Direct methods -
+ #0 : (in LTestVariableArityLinkerMethod;)
+ name : '<init>'
+ type : '()V'
+ access : 0x10001 (PUBLIC CONSTRUCTOR)
+ code -
+ registers : 1
ins : 1
+ outs : 1
+ insns size : 4 16-bit code units
+003a7c: |[003a7c] TestVariableArityLinkerMethod.<init>:()V
+003a8c: 7010 3200 0000 |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003a92: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=27
+ locals :
+ 0x0000 - 0x0004 reg=0 this LTestVariableArityLinkerMethod;
+
+ #1 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithBoxedArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 7
+ ins : 4
+ outs : 4
+ insns size : 34 16-bit code units
+003750: |[003750] TestVariableArityLinkerMethod.bsmWithBoxedArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;
+003760: 1a00 f800 |0000: const-string v0, "bsmWithBoxedArray" // string@00f8
+003764: 1241 |0002: const/4 v1, #int 4 // #4
+003766: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00376a: 1202 |0005: const/4 v2, #int 0 // #0
+00376c: 4d03 0102 |0006: aput-object v3, v1, v2
+003770: 1212 |0008: const/4 v2, #int 1 // #1
+003772: 4d04 0102 |0009: aput-object v4, v1, v2
+003776: 1222 |000b: const/4 v2, #int 2 // #2
+003778: 4d05 0102 |000c: aput-object v5, v1, v2
+00377c: 1232 |000e: const/4 v2, #int 3 // #3
+00377e: 4d06 0102 |000f: aput-object v6, v1, v2
+003782: 7120 a700 1000 |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003788: 6e10 dc00 0300 |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+00378e: 0c00 |0017: move-result-object v0
+003790: 6e40 d800 0354 |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003796: 0c00 |001b: move-result-object v0
+003798: 2201 3400 |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00379c: 7020 d200 0100 |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0037a2: 1101 |0021: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=477
+ 0x0014 line=478
+ 0x001c line=479
+ locals :
+ 0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0022 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0022 reg=6 extraArgs [Ljava/lang/Integer;
+
+ #2 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithClassAndFloatArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 8
+ ins : 5
+ outs : 4
+ insns size : 37 16-bit code units
+0037a4: |[0037a4] TestVariableArityLinkerMethod.bsmWithClassAndFloatArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;
+0037b4: 1a00 f900 |0000: const-string v0, "bsmWithClassAndFloatArray" // string@00f9
+0037b8: 1251 |0002: const/4 v1, #int 5 // #5
+0037ba: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0037be: 1202 |0005: const/4 v2, #int 0 // #0
+0037c0: 4d03 0102 |0006: aput-object v3, v1, v2
+0037c4: 1212 |0008: const/4 v2, #int 1 // #1
+0037c6: 4d04 0102 |0009: aput-object v4, v1, v2
+0037ca: 1222 |000b: const/4 v2, #int 2 // #2
+0037cc: 4d05 0102 |000c: aput-object v5, v1, v2
+0037d0: 1232 |000e: const/4 v2, #int 3 // #3
+0037d2: 4d06 0102 |000f: aput-object v6, v1, v2
+0037d6: 1242 |0011: const/4 v2, #int 4 // #4
+0037d8: 4d07 0102 |0012: aput-object v7, v1, v2
+0037dc: 7120 a700 1000 |0014: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0037e2: 6e10 dc00 0300 |0017: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0037e8: 0c00 |001a: move-result-object v0
+0037ea: 6e40 d800 0354 |001b: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0037f0: 0c00 |001e: move-result-object v0
+0037f2: 2201 3400 |001f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0037f6: 7020 d200 0100 |0021: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0037fc: 1101 |0024: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=294
+ 0x0017 line=296
+ 0x001f line=297
+ locals :
+ 0x0000 - 0x0000 reg=6 (null) Ljava/lang/Class;
+ 0x001f - 0x0025 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0025 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0025 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0025 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0025 reg=6 extraArg Ljava/lang/Class; Ljava/lang/Class<*>;
+ 0x0000 - 0x0025 reg=7 arityArgs [F
+
+ #3 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithClassArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 7
+ ins : 4
+ outs : 4
+ insns size : 34 16-bit code units
+003800: |[003800] TestVariableArityLinkerMethod.bsmWithClassArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+003810: 1a00 fa00 |0000: const-string v0, "bsmWithClassArray" // string@00fa
+003814: 1241 |0002: const/4 v1, #int 4 // #4
+003816: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00381a: 1202 |0005: const/4 v2, #int 0 // #0
+00381c: 4d03 0102 |0006: aput-object v3, v1, v2
+003820: 1212 |0008: const/4 v2, #int 1 // #1
+003822: 4d04 0102 |0009: aput-object v4, v1, v2
+003826: 1222 |000b: const/4 v2, #int 2 // #2
+003828: 4d05 0102 |000c: aput-object v5, v1, v2
+00382c: 1232 |000e: const/4 v2, #int 3 // #3
+00382e: 4d06 0102 |000f: aput-object v6, v1, v2
+003832: 7120 a700 1000 |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003838: 6e10 dc00 0300 |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+00383e: 0c00 |0017: move-result-object v0
+003840: 6e40 d800 0354 |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003846: 0c00 |001b: move-result-object v0
+003848: 2201 3400 |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00384c: 7020 d200 0100 |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003852: 1101 |0021: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=367
+ 0x0014 line=368
+ 0x001c line=369
+ locals :
+ 0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0022 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0022 reg=6 arityArgs [Ljava/lang/Class;
+
+ #4 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithDoubleArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 7
+ ins : 4
+ outs : 4
+ insns size : 34 16-bit code units
+003854: |[003854] TestVariableArityLinkerMethod.bsmWithDoubleArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;
+003864: 1a00 fb00 |0000: const-string v0, "bsmWithDoubleArray" // string@00fb
+003868: 1241 |0002: const/4 v1, #int 4 // #4
+00386a: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00386e: 1202 |0005: const/4 v2, #int 0 // #0
+003870: 4d03 0102 |0006: aput-object v3, v1, v2
+003874: 1212 |0008: const/4 v2, #int 1 // #1
+003876: 4d04 0102 |0009: aput-object v4, v1, v2
+00387a: 1222 |000b: const/4 v2, #int 2 // #2
+00387c: 4d05 0102 |000c: aput-object v5, v1, v2
+003880: 1232 |000e: const/4 v2, #int 3 // #3
+003882: 4d06 0102 |000f: aput-object v6, v1, v2
+003886: 7120 a700 1000 |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+00388c: 6e10 dc00 0300 |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003892: 0c00 |0017: move-result-object v0
+003894: 6e40 d800 0354 |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+00389a: 0c00 |001b: move-result-object v0
+00389c: 2201 3400 |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0038a0: 7020 d200 0100 |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0038a6: 1101 |0021: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=332
+ 0x0014 line=333
+ 0x001c line=334
+ locals :
+ 0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0022 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0022 reg=6 arityArgs [D
+
+ #5 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithFloatAndLongArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 9
+ ins : 5
+ outs : 4
+ insns size : 41 16-bit code units
+0038a8: |[0038a8] TestVariableArityLinkerMethod.bsmWithFloatAndLongArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;
+0038b8: 1a00 fc00 |0000: const-string v0, "bsmWithFloatAndLongArray" // string@00fc
+0038bc: 1251 |0002: const/4 v1, #int 5 // #5
+0038be: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0038c2: 1202 |0005: const/4 v2, #int 0 // #0
+0038c4: 4d04 0102 |0006: aput-object v4, v1, v2
+0038c8: 1212 |0008: const/4 v2, #int 1 // #1
+0038ca: 4d05 0102 |0009: aput-object v5, v1, v2
+0038ce: 1222 |000b: const/4 v2, #int 2 // #2
+0038d0: 4d06 0102 |000c: aput-object v6, v1, v2
+0038d4: 7110 ba00 0700 |000e: invoke-static {v7}, Ljava/lang/Float;.valueOf:(F)Ljava/lang/Float; // method@00ba
+0038da: 0c02 |0011: move-result-object v2
+0038dc: 1233 |0012: const/4 v3, #int 3 // #3
+0038de: 4d02 0103 |0013: aput-object v2, v1, v3
+0038e2: 1242 |0015: const/4 v2, #int 4 // #4
+0038e4: 4d08 0102 |0016: aput-object v8, v1, v2
+0038e8: 7120 a700 1000 |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0038ee: 6e10 dc00 0400 |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0038f4: 0c00 |001e: move-result-object v0
+0038f6: 6e40 d800 0465 |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0038fc: 0c00 |0022: move-result-object v0
+0038fe: 2201 3400 |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003902: 7020 d200 0100 |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003908: 1101 |0028: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=257
+ 0x000e line=258
+ 0x0018 line=257
+ 0x001b line=259
+ 0x0023 line=260
+ locals :
+ 0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0029 reg=5 methodName Ljava/lang/String;
+ 0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0029 reg=7 extraArg F
+ 0x0000 - 0x0029 reg=8 arityArgs [J
+
+ #6 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithIntAndStringArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 9
+ ins : 5
+ outs : 4
+ insns size : 41 16-bit code units
+00390c: |[00390c] TestVariableArityLinkerMethod.bsmWithIntAndStringArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+00391c: 1a00 fd00 |0000: const-string v0, "bsmWithIntAndStringArray" // string@00fd
+003920: 1251 |0002: const/4 v1, #int 5 // #5
+003922: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+003926: 1202 |0005: const/4 v2, #int 0 // #0
+003928: 4d04 0102 |0006: aput-object v4, v1, v2
+00392c: 1212 |0008: const/4 v2, #int 1 // #1
+00392e: 4d05 0102 |0009: aput-object v5, v1, v2
+003932: 1222 |000b: const/4 v2, #int 2 // #2
+003934: 4d06 0102 |000c: aput-object v6, v1, v2
+003938: 7110 bd00 0700 |000e: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00393e: 0c02 |0011: move-result-object v2
+003940: 1233 |0012: const/4 v3, #int 3 // #3
+003942: 4d02 0103 |0013: aput-object v2, v1, v3
+003946: 1242 |0015: const/4 v2, #int 4 // #4
+003948: 4d08 0102 |0016: aput-object v8, v1, v2
+00394c: 7120 a700 1000 |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003952: 6e10 dc00 0400 |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003958: 0c00 |001e: move-result-object v0
+00395a: 6e40 d800 0465 |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003960: 0c00 |0022: move-result-object v0
+003962: 2201 3400 |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003966: 7020 d200 0100 |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+00396c: 1101 |0028: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=133
+ 0x000e line=138
+ 0x0018 line=133
+ 0x001b line=140
+ 0x0023 line=141
+ locals :
+ 0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0029 reg=5 methodName Ljava/lang/String;
+ 0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0029 reg=7 extraInt I
+ 0x0000 - 0x0029 reg=8 extraArityArgs [Ljava/lang/String;
+
+ #7 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithLongAndIntArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 10
+ ins : 6
+ outs : 4
+ insns size : 41 16-bit code units
+003970: |[003970] TestVariableArityLinkerMethod.bsmWithLongAndIntArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;
+003980: 1a00 fe00 |0000: const-string v0, "bsmWithLongAndIntArray" // string@00fe
+003984: 1251 |0002: const/4 v1, #int 5 // #5
+003986: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00398a: 1202 |0005: const/4 v2, #int 0 // #0
+00398c: 4d04 0102 |0006: aput-object v4, v1, v2
+003990: 1212 |0008: const/4 v2, #int 1 // #1
+003992: 4d05 0102 |0009: aput-object v5, v1, v2
+003996: 1222 |000b: const/4 v2, #int 2 // #2
+003998: 4d06 0102 |000c: aput-object v6, v1, v2
+00399c: 7120 be00 8700 |000e: invoke-static {v7, v8}, Ljava/lang/Long;.valueOf:(J)Ljava/lang/Long; // method@00be
+0039a2: 0c02 |0011: move-result-object v2
+0039a4: 1233 |0012: const/4 v3, #int 3 // #3
+0039a6: 4d02 0103 |0013: aput-object v2, v1, v3
+0039aa: 1242 |0015: const/4 v2, #int 4 // #4
+0039ac: 4d09 0102 |0016: aput-object v9, v1, v2
+0039b0: 7120 a700 1000 |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0039b6: 6e10 dc00 0400 |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0039bc: 0c00 |001e: move-result-object v0
+0039be: 6e40 d800 0465 |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0039c4: 0c00 |0022: move-result-object v0
+0039c6: 2201 3400 |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0039ca: 7020 d200 0100 |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0039d0: 1101 |0028: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=219
+ 0x001b line=220
+ 0x0023 line=221
+ locals :
+ 0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0029 reg=5 methodName Ljava/lang/String;
+ 0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0029 reg=7 extraArg J
+ 0x0000 - 0x0029 reg=9 arityArgs [I
+
+ #8 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithStringArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 7
+ ins : 4
+ outs : 4
+ insns size : 34 16-bit code units
+0039d4: |[0039d4] TestVariableArityLinkerMethod.bsmWithStringArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+0039e4: 1a00 ff00 |0000: const-string v0, "bsmWithStringArray" // string@00ff
+0039e8: 1241 |0002: const/4 v1, #int 4 // #4
+0039ea: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0039ee: 1202 |0005: const/4 v2, #int 0 // #0
+0039f0: 4d03 0102 |0006: aput-object v3, v1, v2
+0039f4: 1212 |0008: const/4 v2, #int 1 // #1
+0039f6: 4d04 0102 |0009: aput-object v4, v1, v2
+0039fa: 1222 |000b: const/4 v2, #int 2 // #2
+0039fc: 4d05 0102 |000c: aput-object v5, v1, v2
+003a00: 1232 |000e: const/4 v2, #int 3 // #3
+003a02: 4d06 0102 |000f: aput-object v6, v1, v2
+003a06: 7120 a700 1000 |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003a0c: 6e10 dc00 0300 |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003a12: 0c00 |0017: move-result-object v0
+003a14: 6e40 d800 0354 |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003a1a: 0c00 |001b: move-result-object v0
+003a1c: 2201 3400 |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003a20: 7020 d200 0100 |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003a26: 1101 |0021: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=61
+ 0x0014 line=62
+ 0x001c line=63
+ locals :
+ 0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0022 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0022 reg=6 arityArgs [Ljava/lang/String;
+
+ #9 : (in LTestVariableArityLinkerMethod;)
+ name : 'bsmWithWiderArray'
+ type : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 7
+ ins : 4
+ outs : 4
+ insns size : 34 16-bit code units
+003a28: |[003a28] TestVariableArityLinkerMethod.bsmWithWiderArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;
+003a38: 1a00 0001 |0000: const-string v0, "bsmWithWiderArray" // string@0100
+003a3c: 1241 |0002: const/4 v1, #int 4 // #4
+003a3e: 2311 4800 |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+003a42: 1202 |0005: const/4 v2, #int 0 // #0
+003a44: 4d03 0102 |0006: aput-object v3, v1, v2
+003a48: 1212 |0008: const/4 v2, #int 1 // #1
+003a4a: 4d04 0102 |0009: aput-object v4, v1, v2
+003a4e: 1222 |000b: const/4 v2, #int 2 // #2
+003a50: 4d05 0102 |000c: aput-object v5, v1, v2
+003a54: 1232 |000e: const/4 v2, #int 3 // #3
+003a56: 4d06 0102 |000f: aput-object v6, v1, v2
+003a5a: 7120 a700 1000 |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003a60: 6e10 dc00 0300 |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003a66: 0c00 |0017: move-result-object v0
+003a68: 6e40 d800 0354 |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003a6e: 0c00 |001b: move-result-object v0
+003a70: 2201 3400 |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003a74: 7020 d200 0100 |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003a7a: 1101 |0021: return-object v1
+ catches : (none)
+ positions :
+ 0x0000 line=447
+ 0x0014 line=448
+ 0x001c line=449
+ locals :
+ 0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle;
+ 0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup;
+ 0x0000 - 0x0022 reg=4 methodName Ljava/lang/String;
+ 0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType;
+ 0x0000 - 0x0022 reg=6 extraArgs [J
+
+ #10 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodA'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
outs : 2
insns size : 8 16-bit code units
-0014d4: |[0014d4] invokecustom.InvokeCustom.run:()V
-0014e4: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-0014e8: 1a01 8200 |0002: const-string v1, "run() for Test9" // string@0082
-0014ec: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-0014f2: 0e00 |0007: return-void
+003a94: |[003a94] TestVariableArityLinkerMethod.methodA:()V
+003aa4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003aa8: 1a01 7501 |0002: const-string v1, "methodA" // string@0175
+003aac: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003ab2: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=137
- 0x0007 line=138
+ 0x0000 line=86
+ 0x0007 line=87
locals :
- 0x0000 - 0x0008 reg=2 this Linvokecustom/InvokeCustom;
- #2 : (in Linvokecustom/InvokeCustom;)
- name : 'targetMethodTest4'
+ #11 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodB'
type : '()V'
- access : 0x0001 (PUBLIC)
+ access : 0x000a (PRIVATE STATIC)
code -
- registers : 3
- ins : 1
+ registers : 2
+ ins : 0
outs : 2
insns size : 8 16-bit code units
-0014f4: |[0014f4] invokecustom.InvokeCustom.targetMethodTest4:()V
-001504: 6200 0200 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0002
-001508: 1a01 8a00 |0002: const-string v1, "targetMethodTest4 from InvokeCustom (oops!)" // string@008a
-00150c: 6e20 2900 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0029
-001512: 0e00 |0007: return-void
+003ab4: |[003ab4] TestVariableArityLinkerMethod.methodB:()V
+003ac4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ac8: 1a01 7601 |0002: const-string v1, "methodB" // string@0176
+003acc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003ad2: 0e00 |0007: return-void
catches : (none)
positions :
- 0x0000 line=68
- 0x0007 line=69
+ 0x0000 line=105
+ 0x0007 line=106
+ locals :
+
+ #12 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodC'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003ad4: |[003ad4] TestVariableArityLinkerMethod.methodC:()V
+003ae4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ae8: 1a01 7701 |0002: const-string v1, "methodC" // string@0177
+003aec: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003af2: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=123
+ 0x0007 line=124
+ locals :
+
+ #13 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodD'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003af4: |[003af4] TestVariableArityLinkerMethod.methodD:()V
+003b04: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b08: 1a01 7801 |0002: const-string v1, "methodD" // string@0178
+003b0c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b12: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=166
+ 0x0007 line=167
+ locals :
+
+ #14 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodE'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003b14: |[003b14] TestVariableArityLinkerMethod.methodE:()V
+003b24: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b28: 1a01 7901 |0002: const-string v1, "methodE" // string@0179
+003b2c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b32: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=189
+ 0x0007 line=190
+ locals :
+
+ #15 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodF'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003b34: |[003b34] TestVariableArityLinkerMethod.methodF:()V
+003b44: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b48: 1a01 7a01 |0002: const-string v1, "methodF" // string@017a
+003b4c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b52: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=209
+ 0x0007 line=210
locals :
- 0x0000 - 0x0008 reg=2 this Linvokecustom/InvokeCustom;
- source_file_idx : 27 (InvokeCustom.java)
+ #16 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodG'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003b54: |[003b54] TestVariableArityLinkerMethod.methodG:()V
+003b64: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b68: 1a01 7b01 |0002: const-string v1, "methodG" // string@017b
+003b6c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b72: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=247
+ 0x0007 line=248
+ locals :
+
+ #17 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodH'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003b74: |[003b74] TestVariableArityLinkerMethod.methodH:()V
+003b84: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b88: 1a01 7c01 |0002: const-string v1, "methodH" // string@017c
+003b8c: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b92: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=284
+ 0x0007 line=285
+ locals :
+
+ #18 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodI'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003b94: |[003b94] TestVariableArityLinkerMethod.methodI:()V
+003ba4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ba8: 1a01 7d01 |0002: const-string v1, "methodI" // string@017d
+003bac: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bb2: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=323
+ 0x0007 line=324
+ locals :
+
+ #19 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodJ'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003bb4: |[003bb4] TestVariableArityLinkerMethod.methodJ:()V
+003bc4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003bc8: 1a01 7e01 |0002: const-string v1, "methodJ" // string@017e
+003bcc: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bd2: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=358
+ 0x0007 line=359
+ locals :
+
+ #20 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodK'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 2
+ ins : 0
+ outs : 2
+ insns size : 8 16-bit code units
+003bd4: |[003bd4] TestVariableArityLinkerMethod.methodK:()V
+003be4: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003be8: 1a01 7f01 |0002: const-string v1, "methodK" // string@017f
+003bec: 6e20 b300 1000 |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bf2: 0e00 |0007: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=392
+ 0x0007 line=393
+ locals :
+
+ #21 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodO'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003bf4: |[003bf4] TestVariableArityLinkerMethod.methodO:()V
+003c04: 7100 8e00 0000 |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c0a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=413
+ 0x0003 line=414
+ locals :
+
+ #22 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodP'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003c0c: |[003c0c] TestVariableArityLinkerMethod.methodP:()V
+003c1c: 7100 8e00 0000 |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c22: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=441
+ 0x0003 line=442
+ locals :
+
+ #23 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodQ'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003c24: |[003c24] TestVariableArityLinkerMethod.methodQ:()V
+003c34: 7100 8e00 0000 |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c3a: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=468
+ 0x0003 line=469
+ locals :
+
+ #24 : (in LTestVariableArityLinkerMethod;)
+ name : 'methodR'
+ type : '()V'
+ access : 0x000a (PRIVATE STATIC)
+ code -
+ registers : 0
+ ins : 0
+ outs : 0
+ insns size : 4 16-bit code units
+003c3c: |[003c3c] TestVariableArityLinkerMethod.methodR:()V
+003c4c: 7100 8e00 0000 |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c52: 0e00 |0003: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=501
+ 0x0003 line=502
+ locals :
+
+ #25 : (in LTestVariableArityLinkerMethod;)
+ name : 'printBsmArgs'
+ type : '(Ljava/lang/String;[Ljava/lang/Object;)V'
+ access : 0x008a (PRIVATE STATIC VARARGS)
+ code -
+ registers : 6
+ ins : 2
+ outs : 2
+ insns size : 159 16-bit code units
+003c54: |[003c54] TestVariableArityLinkerMethod.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V
+003c64: 6200 1300 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c68: 6e20 b000 4000 |0002: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c6e: 6200 1300 |0005: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c72: 1a01 0600 |0007: const-string v1, "(" // string@0006
+003c76: 6e20 b000 1000 |0009: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c7c: 1200 |000c: const/4 v0, #int 0 // #0
+003c7e: 2151 |000d: array-length v1, v5
+003c80: 3510 8900 |000e: if-ge v0, v1, 0097 // +0089
+003c84: 3800 0900 |0010: if-eqz v0, 0019 // +0009
+003c88: 6201 1300 |0012: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c8c: 1a02 0c00 |0014: const-string v2, ", " // string@000c
+003c90: 6e20 b000 2100 |0016: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c96: 4601 0500 |0019: aget-object v1, v5, v0
+003c9a: 3801 7100 |001b: if-eqz v1, 008c // +0071
+003c9e: 4601 0500 |001d: aget-object v1, v5, v0
+003ca2: 6e10 c000 0100 |001f: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003ca8: 0c01 |0022: move-result-object v1
+003caa: 6e10 b800 0100 |0023: invoke-virtual {v1}, Ljava/lang/Class;.isArray:()Z // method@00b8
+003cb0: 0a01 |0026: move-result v1
+003cb2: 3801 6500 |0027: if-eqz v1, 008c // +0065
+003cb6: 4601 0500 |0029: aget-object v1, v5, v0
+003cba: 6e10 c000 0100 |002b: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003cc0: 0c02 |002e: move-result-object v2
+003cc2: 1c03 4400 |002f: const-class v3, [I // type@0044
+003cc6: 3332 0f00 |0031: if-ne v2, v3, 0040 // +000f
+003cca: 6202 1300 |0033: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003cce: 0713 |0035: move-object v3, v1
+003cd0: 1f03 4400 |0036: check-cast v3, [I // type@0044
+003cd4: 7110 e900 0300 |0038: invoke-static {v3}, Ljava/util/Arrays;.toString:([I)Ljava/lang/String; // method@00e9
+003cda: 0c03 |003b: move-result-object v3
+003cdc: 6e20 b000 3200 |003c: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ce2: 284c |003f: goto 008b // +004c
+003ce4: 6e10 c000 0100 |0040: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003cea: 0c02 |0043: move-result-object v2
+003cec: 1c03 4500 |0044: const-class v3, [J // type@0045
+003cf0: 3332 0f00 |0046: if-ne v2, v3, 0055 // +000f
+003cf4: 6202 1300 |0048: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003cf8: 0713 |004a: move-object v3, v1
+003cfa: 1f03 4500 |004b: check-cast v3, [J // type@0045
+003cfe: 7110 ea00 0300 |004d: invoke-static {v3}, Ljava/util/Arrays;.toString:([J)Ljava/lang/String; // method@00ea
+003d04: 0c03 |0050: move-result-object v3
+003d06: 6e20 b000 3200 |0051: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d0c: 2837 |0054: goto 008b // +0037
+003d0e: 6e10 c000 0100 |0055: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003d14: 0c02 |0058: move-result-object v2
+003d16: 1c03 4300 |0059: const-class v3, [F // type@0043
+003d1a: 3332 0f00 |005b: if-ne v2, v3, 006a // +000f
+003d1e: 6202 1300 |005d: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d22: 0713 |005f: move-object v3, v1
+003d24: 1f03 4300 |0060: check-cast v3, [F // type@0043
+003d28: 7110 e800 0300 |0062: invoke-static {v3}, Ljava/util/Arrays;.toString:([F)Ljava/lang/String; // method@00e8
+003d2e: 0c03 |0065: move-result-object v3
+003d30: 6e20 b000 3200 |0066: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d36: 2822 |0069: goto 008b // +0022
+003d38: 6e10 c000 0100 |006a: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003d3e: 0c02 |006d: move-result-object v2
+003d40: 1c03 4200 |006e: const-class v3, [D // type@0042
+003d44: 3332 0f00 |0070: if-ne v2, v3, 007f // +000f
+003d48: 6202 1300 |0072: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d4c: 0713 |0074: move-object v3, v1
+003d4e: 1f03 4200 |0075: check-cast v3, [D // type@0042
+003d52: 7110 e700 0300 |0077: invoke-static {v3}, Ljava/util/Arrays;.toString:([D)Ljava/lang/String; // method@00e7
+003d58: 0c03 |007a: move-result-object v3
+003d5a: 6e20 b000 3200 |007b: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d60: 280d |007e: goto 008b // +000d
+003d62: 6202 1300 |007f: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d66: 0713 |0081: move-object v3, v1
+003d68: 1f03 4800 |0082: check-cast v3, [Ljava/lang/Object; // type@0048
+003d6c: 7110 eb00 0300 |0084: invoke-static {v3}, Ljava/util/Arrays;.toString:([Ljava/lang/Object;)Ljava/lang/String; // method@00eb
+003d72: 0c03 |0087: move-result-object v3
+003d74: 6e20 b000 3200 |0088: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d7a: 2808 |008b: goto 0093 // +0008
+003d7c: 6201 1300 |008c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d80: 4602 0500 |008e: aget-object v2, v5, v0
+003d84: 6e20 af00 2100 |0090: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003d8a: d800 0001 |0093: add-int/lit8 v0, v0, #int 1 // #01
+003d8e: 2900 78ff |0095: goto/16 000d // -0088
+003d92: 6200 1300 |0097: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d96: 1a01 0800 |0099: const-string v1, ");" // string@0008
+003d9a: 6e20 b300 1000 |009b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003da0: 0e00 |009e: return-void
+ catches : (none)
+ positions :
+ 0x0000 line=29
+ 0x0005 line=30
+ 0x000c line=31
+ 0x0010 line=32
+ 0x0012 line=33
+ 0x0019 line=35
+ 0x0029 line=36
+ 0x002b line=37
+ 0x0033 line=38
+ 0x0040 line=39
+ 0x0048 line=40
+ 0x0055 line=41
+ 0x005d line=42
+ 0x006a line=43
+ 0x0072 line=44
+ 0x007f line=46
+ 0x008b line=48
+ 0x008c line=49
+ 0x0093 line=31
+ 0x0097 line=52
+ 0x009e line=53
+ locals :
+ 0x002b - 0x008b reg=1 array Ljava/lang/Object;
+ 0x000d - 0x0097 reg=0 i I
+ 0x0000 - 0x009f reg=4 method Ljava/lang/String;
+ 0x0000 - 0x009f reg=5 args [Ljava/lang/Object;
+
+ #26 : (in LTestVariableArityLinkerMethod;)
+ name : 'test'
+ type : '()V'
+ access : 0x0008 (STATIC)
+ code -
+ registers : 3
+ ins : 0
+ outs : 2
+ insns size : 224 16-bit code units
+003da4: |[003da4] TestVariableArityLinkerMethod.test:()V
+003db4: 1200 |0000: const/4 v0, #int 0 // #0
+003db6: 0101 |0001: move v1, v0
+003db8: 1222 |0002: const/4 v2, #int 2 // #2
+003dba: 3521 0e00 |0003: if-ge v1, v2, 0011 // +000e
+003dbe: fc00 1f00 0000 |0005: invoke-custom {}, call_site@001f
+003dc4: fc00 2000 0000 |0008: invoke-custom {}, call_site@0020
+003dca: fc00 2100 0000 |000b: invoke-custom {}, call_site@0021
+003dd0: d801 0101 |000e: add-int/lit8 v1, v1, #int 1 // #01
+003dd4: 28f2 |0010: goto 0002 // -000e
+003dd6: 0000 |0011: nop // spacer
+003dd8: 3520 0e00 |0012: if-ge v0, v2, 0020 // +000e
+003ddc: fc00 2200 0000 |0014: invoke-custom {}, call_site@0022
+003de2: fc00 2300 0000 |0017: invoke-custom {}, call_site@0023
+003de8: fc00 2400 0000 |001a: invoke-custom {}, call_site@0024
+003dee: d800 0001 |001d: add-int/lit8 v0, v0, #int 1 // #01
+003df2: 28f3 |001f: goto 0012 // -000d
+003df4: fc00 2500 0000 |0020: invoke-custom {}, call_site@0025
+003dfa: fc00 2600 0000 |0023: invoke-custom {}, call_site@0026
+003e00: fc00 2700 0000 |0026: invoke-custom {}, call_site@0027
+003e06: fc00 2800 0000 |0029: invoke-custom {}, call_site@0028
+003e0c: fc00 2900 0000 |002c: invoke-custom {}, call_site@0029
+003e12: fc00 2a00 0000 |002f: invoke-custom {}, call_site@002a
+003e18: 7100 8e00 0000 |0032: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003e1e: 2826 |0035: goto 005b // +0026
+003e20: 0d00 |0036: move-exception v0
+003e22: 6201 1300 |0037: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e26: 1a02 8201 |0039: const-string v2, "methodO => " // string@0182
+003e2a: 6e20 b000 2100 |003b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e30: 6201 1300 |003e: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e34: 6e10 c000 0000 |0040: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e3a: 0c02 |0043: move-result-object v2
+003e3c: 6e20 af00 2100 |0044: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003e42: 6201 1300 |0047: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e46: 1a02 0200 |0049: const-string v2, " => " // string@0002
+003e4a: 6e20 b000 2100 |004b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e50: 6201 1300 |004e: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e54: 6e10 b600 0000 |0050: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003e5a: 0c02 |0053: move-result-object v2
+003e5c: 6e10 c000 0200 |0054: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e62: 0c02 |0057: move-result-object v2
+003e64: 6e20 b200 2100 |0058: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003e6a: fc00 2b00 0000 |005b: invoke-custom {}, call_site@002b
+003e70: 7100 8e00 0000 |005e: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003e76: 2826 |0061: goto 0087 // +0026
+003e78: 0d00 |0062: move-exception v0
+003e7a: 6201 1300 |0063: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e7e: 1a02 8401 |0065: const-string v2, "methodP => " // string@0184
+003e82: 6e20 b000 2100 |0067: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e88: 6201 1300 |006a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e8c: 6e10 c000 0000 |006c: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e92: 0c02 |006f: move-result-object v2
+003e94: 6e20 af00 2100 |0070: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003e9a: 6201 1300 |0073: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e9e: 1a02 0200 |0075: const-string v2, " => " // string@0002
+003ea2: 6e20 b000 2100 |0077: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ea8: 6201 1300 |007a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003eac: 6e10 b600 0000 |007c: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003eb2: 0c02 |007f: move-result-object v2
+003eb4: 6e10 c000 0200 |0080: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003eba: 0c02 |0083: move-result-object v2
+003ebc: 6e20 b200 2100 |0084: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003ec2: fc00 2c00 0000 |0087: invoke-custom {}, call_site@002c
+003ec8: 7100 8e00 0000 |008a: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003ece: 2826 |008d: goto 00b3 // +0026
+003ed0: 0d00 |008e: move-exception v0
+003ed2: 6201 1300 |008f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ed6: 1a02 8601 |0091: const-string v2, "methodQ => " // string@0186
+003eda: 6e20 b000 2100 |0093: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ee0: 6201 1300 |0096: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ee4: 6e10 c000 0000 |0098: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003eea: 0c02 |009b: move-result-object v2
+003eec: 6e20 af00 2100 |009c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003ef2: 6201 1300 |009f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ef6: 1a02 0200 |00a1: const-string v2, " => " // string@0002
+003efa: 6e20 b000 2100 |00a3: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f00: 6201 1300 |00a6: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f04: 6e10 b600 0000 |00a8: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003f0a: 0c02 |00ab: move-result-object v2
+003f0c: 6e10 c000 0200 |00ac: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f12: 0c02 |00af: move-result-object v2
+003f14: 6e20 b200 2100 |00b0: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003f1a: fc00 2d00 0000 |00b3: invoke-custom {}, call_site@002d
+003f20: 7100 8e00 0000 |00b6: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003f26: 2826 |00b9: goto 00df // +0026
+003f28: 0d00 |00ba: move-exception v0
+003f2a: 6201 1300 |00bb: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f2e: 1a02 8801 |00bd: const-string v2, "methodR => " // string@0188
+003f32: 6e20 b000 2100 |00bf: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f38: 6201 1300 |00c2: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f3c: 6e10 c000 0000 |00c4: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f42: 0c02 |00c7: move-result-object v2
+003f44: 6e20 af00 2100 |00c8: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003f4a: 6201 1300 |00cb: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f4e: 1a02 0200 |00cd: const-string v2, " => " // string@0002
+003f52: 6e20 b000 2100 |00cf: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f58: 6201 1300 |00d2: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f5c: 6e10 b600 0000 |00d4: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003f62: 0c02 |00d7: move-result-object v2
+003f64: 6e10 c000 0200 |00d8: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f6a: 0c02 |00db: move-result-object v2
+003f6c: 6e20 b200 2100 |00dc: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003f72: 0e00 |00df: return-void
+ catches : 4
+ 0x002f - 0x0035
+ Ljava/lang/BootstrapMethodError; -> 0x0036
+ 0x005b - 0x0061
+ Ljava/lang/BootstrapMethodError; -> 0x0062
+ 0x0087 - 0x008d
+ Ljava/lang/BootstrapMethodError; -> 0x008e
+ 0x00b3 - 0x00b9
+ Ljava/lang/BootstrapMethodError; -> 0x00ba
+ positions :
+ 0x0000 line=506
+ 0x0005 line=507
+ 0x0008 line=508
+ 0x000b line=509
+ 0x000e line=506
+ 0x0011 line=511
+ 0x0014 line=512
+ 0x0017 line=513
+ 0x001a line=514
+ 0x001d line=511
+ 0x0020 line=516
+ 0x0023 line=517
+ 0x0026 line=518
+ 0x0029 line=519
+ 0x002c line=520
+ 0x002f line=527
+ 0x0032 line=528
+ 0x0035 line=534
+ 0x0036 line=529
+ 0x0037 line=530
+ 0x003e line=531
+ 0x0047 line=532
+ 0x004e line=533
+ 0x005b line=538
+ 0x005e line=539
+ 0x0061 line=545
+ 0x0062 line=540
+ 0x0063 line=541
+ 0x006a line=542
+ 0x0073 line=543
+ 0x007a line=544
+ 0x0087 line=549
+ 0x008a line=550
+ 0x008d line=556
+ 0x008e line=551
+ 0x008f line=552
+ 0x0096 line=553
+ 0x009f line=554
+ 0x00a6 line=555
+ 0x00b3 line=560
+ 0x00b6 line=561
+ 0x00b9 line=567
+ 0x00ba line=562
+ 0x00bb line=563
+ 0x00c2 line=564
+ 0x00cb line=565
+ 0x00d2 line=566
+ 0x00df line=568
+ locals :
+ 0x0002 - 0x0011 reg=1 i I
+ 0x0012 - 0x0020 reg=0 i I
+ 0x0037 - 0x005b reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x0063 - 0x0087 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x008f - 0x00b3 reg=0 expected Ljava/lang/BootstrapMethodError;
+ 0x00bb - 0x00df reg=0 expected Ljava/lang/BootstrapMethodError;
+
+ Virtual methods -
+ source_file_idx : 156 (TestVariableArityLinkerMethod.java)
Method handle #0:
- type : put-static
- target : Linvokecustom/InvokeCustom; staticFieldTest9
- target_type : I
+ type : invoke-static
+ target : LTestBadBootstrapArguments; bsm
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ID)Ljava/lang/invoke/CallSite;
Method handle #1:
- type : get-static
- target : Linvokecustom/InvokeCustom; staticFieldTest9
- target_type : I
+ type : invoke-static
+ target : LTestBadBootstrapArguments; bsm
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;
Method handle #2:
- type : put-instance
- target : Linvokecustom/InvokeCustom; fieldTest9
- target_type : (Linvokecustom/InvokeCustom;
+ type : invoke-static
+ target : LTestBadBootstrapArguments; bsmDJ
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;
Method handle #3:
- type : get-instance
- target : Linvokecustom/InvokeCustom; fieldTest9
- target_type : (Linvokecustom/InvokeCustom;
+ type : invoke-static
+ target : LTestBadBootstrapArguments; bsmDoubleLong
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;
Method handle #4:
type : invoke-static
- target : Linvokecustom/InvokeCustom; bsmCreateCallSite
- target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
+ target : LTestBadBootstrapArguments; bsmReturningInteger
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;
Method handle #5:
type : invoke-static
- target : Linvokecustom/InvokeCustom; bsmLookupStatic
- target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+ target : LTestBadBootstrapArguments; bsmReturningObject
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;
Method handle #6:
type : invoke-static
- target : Linvokecustom/InvokeCustom; bsmLookupStaticWithExtraArgs
- target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IJFD)Ljava/lang/invoke/CallSite;
+ target : LTestBadBootstrapArguments; bsmReturningTestersConstantCallsite
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;
Method handle #7:
type : invoke-static
- target : Linvokecustom/InvokeCustom; bsmLookupTest9
- target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
+ target : LTestBadBootstrapArguments; bsmReturningVoid
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V
Method handle #8:
type : invoke-static
- target : Linvokecustom/InvokeCustom; lambda$lambdaTest$0
- target_type : (Ljava/lang/String;)Z
+ target : LTestBadBootstrapArguments; bsmZBCS
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;
Method handle #9:
type : invoke-static
- target : Ljava/lang/invoke/LambdaMetafactory; metafactory
- target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+ target : LTestDynamicBootstrapArguments; bsm
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;
Method handle #10:
- type : invoke-instance
- target : Linvokecustom/InvokeCustom; helperMethodTest9
- target_type : (Linvokecustom/InvokeCustom;)V
+ type : invoke-static
+ target : LTestInvocationKinds; lookupConstructor
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method handle #11:
- type : invoke-instance
- target : Ljava/io/PrintStream; println
- target_type : (Ljava/io/PrintStream;Ljava/lang/String;)V
+ type : invoke-static
+ target : LTestInvocationKinds; lookupInstanceFieldGetter
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method handle #12:
- type : invoke-instance
- target : Ljava/lang/String; trim
- target_type : (Ljava/lang/String;)Ljava/lang/String;
+ type : invoke-static
+ target : LTestInvocationKinds; lookupInstanceFieldSetter
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method handle #13:
- type : invoke-constructor
- target : Linvokecustom/InvokeCustom; <init>
- target_type : (Linvokecustom/InvokeCustom;I)V
+ type : invoke-static
+ target : LTestInvocationKinds; lookupStaticFieldGetter
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method handle #14:
- type : invoke-direct
- target : Linvokecustom/Super; targetMethodTest4
- target_type : (Linvokecustom/Super;)V
+ type : invoke-static
+ target : LTestInvocationKinds; lookupStaticFieldSetter
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method handle #15:
- type : invoke-interface
- target : Ljava/lang/Runnable; run
- target_type : (Ljava/lang/Runnable;)V
-Call site #0: // offset 8450
+ type : invoke-static
+ target : LTestInvocationKinds; lookupVirtual
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #16:
+ type : invoke-static
+ target : LTestInvokeCustomWithConcurrentThreads; linkerMethod
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #17:
+ type : invoke-static
+ target : LTestLinkerMethodMinimalArguments; linkerMethod
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #18:
+ type : invoke-static
+ target : LTestLinkerMethodMultipleArgumentTypes; linkerMethod
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;
+Method handle #19:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithBoxedArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;
+Method handle #20:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithClassAndFloatArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;
+Method handle #21:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithClassArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+Method handle #22:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithDoubleArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;
+Method handle #23:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithFloatAndLongArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;
+Method handle #24:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithIntAndStringArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+Method handle #25:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithLongAndIntArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;
+Method handle #26:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithStringArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+Method handle #27:
+ type : invoke-static
+ target : LTestVariableArityLinkerMethod; bsmWithWiderArray
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;
+Method handle #28:
+ type : invoke-static
+ target : LUnrelatedBSM; bsm
+ target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+Call site #0: // offset 29649
+ link_argument[0] : 1 (MethodHandle)
+ link_argument[1] : happy (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : -1 (int)
+ link_argument[4] : very (String)
+Call site #1: // offset 29662
+ link_argument[0] : 0 (MethodHandle)
+ link_argument[1] : wrongParameterTypes (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : -1 (int)
+ link_argument[4] : very (String)
+Call site #2: // offset 29675
+ link_argument[0] : 0 (MethodHandle)
+ link_argument[1] : missingParameterTypes (String)
+ link_argument[2] : ()V (MethodType)
+Call site #3: // offset 29683
+ link_argument[0] : 1 (MethodHandle)
+ link_argument[1] : extraArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1 (int)
+ link_argument[4] : 2 (String)
+ link_argument[5] : 3 (int)
+Call site #4: // offset 29697
+ link_argument[0] : 1 (MethodHandle)
+ link_argument[1] : wrongArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1 (String)
+ link_argument[4] : 3.14159 (double)
+Call site #5: // offset 29697
+ link_argument[0] : 1 (MethodHandle)
+ link_argument[1] : wrongArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1 (String)
+ link_argument[4] : 3.14159 (double)
+Call site #6: // offset 29716
+ link_argument[0] : 1 (MethodHandle)
+ link_argument[1] : wrongArgumentsAgain (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 3.14159 (double)
+ link_argument[4] : pie (String)
+Call site #7: // offset 29736
+ link_argument[0] : 8 (MethodHandle)
+ link_argument[1] : narrowArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1 (int)
+ link_argument[4] : 127 (int)
+ link_argument[5] : 65 (int)
+ link_argument[6] : -32768 (int)
+Call site #8: // offset 29753
+ link_argument[0] : 2 (MethodHandle)
+ link_argument[1] : wideningArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1.79769e+308 (double)
+ link_argument[4] : 2147483647 (int)
+Call site #9: // offset 29775
+ link_argument[0] : 3 (MethodHandle)
+ link_argument[1] : boxingArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1.79769e+308 (double)
+ link_argument[4] : 9223372036854775807 (long)
+Call site #10: // offset 29800
+ link_argument[0] : 3 (MethodHandle)
+ link_argument[1] : wideningBoxingArguments (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 3.40282e+38 (float)
+ link_argument[4] : 2147483647 (long)
+Call site #11: // offset 29818
+ link_argument[0] : 7 (MethodHandle)
+ link_argument[1] : voidReturnType (String)
+ link_argument[2] : ()V (MethodType)
+Call site #12: // offset 29826
+ link_argument[0] : 5 (MethodHandle)
+ link_argument[1] : ObjectReturnType (String)
+ link_argument[2] : ()V (MethodType)
+Call site #13: // offset 29833
+ link_argument[0] : 4 (MethodHandle)
+ link_argument[1] : integerReturnType (String)
+ link_argument[2] : ()V (MethodType)
+Call site #14: // offset 29841
+ link_argument[0] : 6 (MethodHandle)
+ link_argument[1] : sayHello (String)
+ link_argument[2] : ()V (MethodType)
+Call site #15: // offset 29849
link_argument[0] : 9 (MethodHandle)
- link_argument[1] : test (String)
- link_argument[2] : ()Ljava/util/function/Predicate; (MethodType)
- link_argument[3] : (Ljava/lang/Object;)Z (MethodType)
- link_argument[4] : 8 (MethodHandle)
- link_argument[5] : (Ljava/lang/String;)Z (MethodType)
-Call site #1: // offset 8463
+ link_argument[1] : target (String)
+ link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+ link_argument[3] : A (String)
+ link_argument[4] : 100000000 (long)
+Call site #16: // offset 29849
link_argument[0] : 9 (MethodHandle)
- link_argument[1] : apply (String)
- link_argument[2] : ()Ljava/util/function/Function; (MethodType)
- link_argument[3] : (Ljava/lang/Object;)Ljava/lang/Object; (MethodType)
- link_argument[4] : 12 (MethodHandle)
- link_argument[5] : (Ljava/lang/String;)Ljava/lang/String; (MethodType)
-Call site #2: // offset 8476
+ link_argument[1] : target (String)
+ link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+ link_argument[3] : A (String)
+ link_argument[4] : 100000000 (long)
+Call site #17: // offset 29849
link_argument[0] : 9 (MethodHandle)
- link_argument[1] : accept (String)
- link_argument[2] : (Ljava/io/PrintStream;)Ljava/util/function/Consumer; (MethodType)
- link_argument[3] : (Ljava/lang/Object;)V (MethodType)
- link_argument[4] : 11 (MethodHandle)
- link_argument[5] : (Ljava/lang/String;)V (MethodType)
-Call site #3: // offset 8489
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest1 (String)
+ link_argument[1] : target (String)
+ link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+ link_argument[3] : A (String)
+ link_argument[4] : 100000000 (long)
+Call site #18: // offset 29864
+ link_argument[0] : 10 (MethodHandle)
+ link_argument[1] : unused (String)
+ link_argument[2] : (I)LTestInvocationKinds$Widget; (MethodType)
+Call site #19: // offset 29872
+ link_argument[0] : 12 (MethodHandle)
+ link_argument[1] : instance_field (String)
+ link_argument[2] : (LTestInvocationKinds;D)V (MethodType)
+Call site #20: // offset 29880
+ link_argument[0] : 11 (MethodHandle)
+ link_argument[1] : instance_field (String)
+ link_argument[2] : (LTestInvocationKinds;)D (MethodType)
+Call site #21: // offset 29888
+ link_argument[0] : 15 (MethodHandle)
+ link_argument[1] : getMaxIntegerValue (String)
+ link_argument[2] : (LTestInvocationKinds;II)I (MethodType)
+Call site #22: // offset 29896
+ link_argument[0] : 14 (MethodHandle)
+ link_argument[1] : static_field (String)
+ link_argument[2] : (I)V (MethodType)
+Call site #23: // offset 29896
+ link_argument[0] : 14 (MethodHandle)
+ link_argument[1] : static_field (String)
+ link_argument[2] : (I)V (MethodType)
+Call site #24: // offset 29904
+ link_argument[0] : 13 (MethodHandle)
+ link_argument[1] : static_field (String)
+ link_argument[2] : ()I (MethodType)
+Call site #25: // offset 29904
+ link_argument[0] : 13 (MethodHandle)
+ link_argument[1] : static_field (String)
+ link_argument[2] : ()I (MethodType)
+Call site #26: // offset 29912
+ link_argument[0] : 16 (MethodHandle)
+ link_argument[1] : setCalled (String)
+ link_argument[2] : (I)I (MethodType)
+Call site #27: // offset 29920
+ link_argument[0] : 17 (MethodHandle)
+ link_argument[1] : _add (String)
+ link_argument[2] : (II)I (MethodType)
+Call site #28: // offset 29927
+ link_argument[0] : 18 (MethodHandle)
+ link_argument[1] : _add (String)
+ link_argument[2] : (II)I (MethodType)
+ link_argument[3] : -1 (int)
+ link_argument[4] : 1 (int)
+ link_argument[5] : 97 (int)
+ link_argument[6] : 1024 (int)
+ link_argument[7] : 1 (int)
+ link_argument[8] : 11.1 (float)
+ link_argument[9] : 2.2 (double)
+ link_argument[10] : Hello (String)
+ link_argument[11] : LTestLinkerMethodMultipleArgumentTypes; (Class)
+ link_argument[12] : 123456789 (long)
+Call site #29: // offset 29968
+ link_argument[0] : 28 (MethodHandle)
+ link_argument[1] : _addf (String)
+ link_argument[2] : (FF)F (MethodType)
+ link_argument[3] : LTestLinkerUnrelatedBSM; (Class)
+Call site #30: // offset 29977
+ link_argument[0] : 28 (MethodHandle)
+ link_argument[1] : _subf (String)
+ link_argument[2] : (FF)F (MethodType)
+ link_argument[3] : LTestLinkerUnrelatedBSM; (Class)
+Call site #31: // offset 29986
+ link_argument[0] : 26 (MethodHandle)
+ link_argument[1] : methodA (String)
link_argument[2] : ()V (MethodType)
-Call site #4: // offset 8496
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest2 (String)
- link_argument[2] : (ZBCSIFJDLjava/lang/String;)V (MethodType)
-Call site #5: // offset 8503
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest5 (String)
- link_argument[2] : (III)I (MethodType)
-Call site #6: // offset 8510
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest6 (String)
- link_argument[2] : (JJJ)J (MethodType)
-Call site #7: // offset 8517
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest7 (String)
- link_argument[2] : (FFD)D (MethodType)
-Call site #8: // offset 8524
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest8 (String)
- link_argument[2] : (Ljava/lang/String;)V (MethodType)
-Call site #9: // offset 8524
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest8 (String)
- link_argument[2] : (Ljava/lang/String;)V (MethodType)
-Call site #10: // offset 8524
- link_argument[0] : 5 (MethodHandle)
- link_argument[1] : targetMethodTest8 (String)
- link_argument[2] : (Ljava/lang/String;)V (MethodType)
-Call site #11: // offset 8531
- link_argument[0] : 6 (MethodHandle)
- link_argument[1] : targetMethodTest3 (String)
+ link_argument[3] : Aachen (String)
+ link_argument[4] : Aalborg (String)
+ link_argument[5] : Aalto (String)
+Call site #32: // offset 30000
+ link_argument[0] : 26 (MethodHandle)
+ link_argument[1] : methodB (String)
link_argument[2] : ()V (MethodType)
- link_argument[3] : 1 (int)
- link_argument[4] : 123456789 (long)
- link_argument[5] : 123.456 (float)
- link_argument[6] : 123457 (double)
-Call site #12: // offset 8559
- link_argument[0] : 4 (MethodHandle)
- link_argument[1] : targetMethodTest4 (String)
- link_argument[2] : (Linvokecustom/InvokeCustom;)V (MethodType)
- link_argument[3] : 14 (MethodHandle)
-Call site #13: // offset 8568
- link_argument[0] : 7 (MethodHandle)
- link_argument[1] : targetMethodTest9 (String)
+ link_argument[3] : barium (String)
+Call site #33: // offset 30010
+ link_argument[0] : 26 (MethodHandle)
+ link_argument[1] : methodC (String)
+ link_argument[2] : ()V (MethodType)
+Call site #34: // offset 30018
+ link_argument[0] : 24 (MethodHandle)
+ link_argument[1] : methodD (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 101 (int)
+ link_argument[4] : zoo (String)
+ link_argument[5] : zoogene (String)
+ link_argument[6] : zoogenic (String)
+Call site #35: // offset 30037
+ link_argument[0] : 24 (MethodHandle)
+ link_argument[1] : methodE (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 102 (int)
+ link_argument[4] : zonic (String)
+Call site #36: // offset 30050
+ link_argument[0] : 24 (MethodHandle)
+ link_argument[1] : methodF (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 103 (int)
+Call site #37: // offset 30060
+ link_argument[0] : 25 (MethodHandle)
+ link_argument[1] : methodG (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 81985529216486895 (long)
+ link_argument[4] : 1 (int)
+ link_argument[5] : -1 (int)
+ link_argument[6] : 2 (int)
+ link_argument[7] : -2 (int)
+Call site #38: // offset 30085
+ link_argument[0] : 23 (MethodHandle)
+ link_argument[1] : methodH (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : -2.71828 (float)
+ link_argument[4] : 999999999999 (long)
+ link_argument[5] : -8888888888888 (long)
+Call site #39: // offset 30112
+ link_argument[0] : 20 (MethodHandle)
+ link_argument[1] : methodI (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : Ljava/lang/Throwable; (Class)
+ link_argument[4] : 3.40282e+38 (float)
+ link_argument[5] : 1.4013e-45 (float)
+ link_argument[6] : 3.14159 (float)
+ link_argument[7] : -3.14159 (float)
+Call site #40: // offset 30142
+ link_argument[0] : 22 (MethodHandle)
+ link_argument[1] : methodJ (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 1.79769e+308 (double)
+ link_argument[4] : 4.94066e-324 (double)
+ link_argument[5] : 2.71828 (double)
+ link_argument[6] : -3.14159 (double)
+Call site #41: // offset 30186
+ link_argument[0] : 21 (MethodHandle)
+ link_argument[1] : methodK (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : Ljava/lang/Integer; (Class)
+ link_argument[4] : Ljava/lang/invoke/MethodHandles; (Class)
+ link_argument[5] : Ljava/util/Arrays; (Class)
+Call site #42: // offset 30200
+ link_argument[0] : 24 (MethodHandle)
+ link_argument[1] : methodO (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 103 (int)
+ link_argument[4] : 104 (int)
+Call site #43: // offset 30212
+ link_argument[0] : 24 (MethodHandle)
+ link_argument[1] : methodP (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 103 (int)
+ link_argument[4] : A (String)
+ link_argument[5] : B (String)
+ link_argument[6] : 42 (int)
+Call site #44: // offset 30228
+ link_argument[0] : 27 (MethodHandle)
+ link_argument[1] : methodQ (String)
+ link_argument[2] : ()V (MethodType)
+ link_argument[3] : 103 (int)
+ link_argument[4] : 42 (int)
+Call site #45: // offset 30240
+ link_argument[0] : 19 (MethodHandle)
+ link_argument[1] : methodR (String)
link_argument[2] : ()V (MethodType)
- link_argument[3] : 1 (MethodHandle)
- link_argument[4] : 0 (MethodHandle)
- link_argument[5] : 3 (MethodHandle)
- link_argument[6] : 2 (MethodHandle)
- link_argument[7] : 10 (MethodHandle)
- link_argument[8] : 13 (MethodHandle)
- link_argument[9] : 15 (MethodHandle)
+ link_argument[3] : 1030 (int)
+ link_argument[4] : 420 (int)
diff --git a/test/dexdump/invoke-custom.xml b/test/dexdump/invoke-custom.xml
index 8b22a9d9ee..6d49ce1292 100644
--- a/test/dexdump/invoke-custom.xml
+++ b/test/dexdump/invoke-custom.xml
@@ -1,130 +1,21 @@
<api>
-<package name="invokecustom"
+<package name=""
>
-<class name="InvokeCustom"
- extends="invokecustom.Super"
+<class name="Main"
+ extends="TestBase"
interface="false"
abstract="false"
static="false"
final="false"
visibility="public"
>
-<implements name="java.lang.Runnable">
-</implements>
-<constructor name="InvokeCustom"
- type="invokecustom.InvokeCustom"
- static="false"
- final="false"
- visibility="public"
->
-</constructor>
-<constructor name="InvokeCustom"
- type="invokecustom.InvokeCustom"
+<constructor name="Main"
+ type="Main"
static="false"
final="false"
visibility="public"
>
-<parameter name="arg0" type="int">
-</parameter>
</constructor>
-<method name="bsmCreateCallSite"
- return="java.lang.invoke.CallSite"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-<parameter name="arg0" type="java.lang.invoke.MethodHandles.Lookup">
-</parameter>
-<parameter name="arg1" type="java.lang.String">
-</parameter>
-<parameter name="arg2" type="java.lang.invoke.MethodType">
-</parameter>
-<parameter name="arg3" type="java.lang.invoke.MethodHandle">
-</parameter>
-</method>
-<method name="bsmLookupStatic"
- return="java.lang.invoke.CallSite"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-<parameter name="arg0" type="java.lang.invoke.MethodHandles.Lookup">
-</parameter>
-<parameter name="arg1" type="java.lang.String">
-</parameter>
-<parameter name="arg2" type="java.lang.invoke.MethodType">
-</parameter>
-</method>
-<method name="bsmLookupStaticWithExtraArgs"
- return="java.lang.invoke.CallSite"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-<parameter name="arg0" type="java.lang.invoke.MethodHandles.Lookup">
-</parameter>
-<parameter name="arg1" type="java.lang.String">
-</parameter>
-<parameter name="arg2" type="java.lang.invoke.MethodType">
-</parameter>
-<parameter name="arg3" type="int">
-</parameter>
-<parameter name="arg4" type="long">
-</parameter>
-<parameter name="arg5" type="float">
-</parameter>
-<parameter name="arg6" type="double">
-</parameter>
-</method>
-<method name="bsmLookupTest9"
- return="java.lang.invoke.CallSite"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-<parameter name="arg0" type="java.lang.invoke.MethodHandles.Lookup">
-</parameter>
-<parameter name="arg1" type="java.lang.String">
-</parameter>
-<parameter name="arg2" type="java.lang.invoke.MethodType">
-</parameter>
-<parameter name="arg3" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg4" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg5" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg6" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg7" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg8" type="java.lang.invoke.MethodHandle">
-</parameter>
-<parameter name="arg9" type="java.lang.invoke.MethodHandle">
-</parameter>
-</method>
-<method name="lambdaTest"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-</method>
<method name="main"
return="void"
abstract="false"
@@ -137,56 +28,35 @@
<parameter name="arg0" type="java.lang.String[]">
</parameter>
</method>
-<method name="targetMethodTest5"
- return="int"
+</class>
+<class name="TestBadBootstrapArguments"
+ extends="TestBase"
+ interface="false"
abstract="false"
- native="false"
- synchronized="false"
- static="true"
+ static="false"
final="false"
visibility="public"
>
-<parameter name="arg0" type="int">
-</parameter>
-<parameter name="arg1" type="int">
-</parameter>
-<parameter name="arg2" type="int">
-</parameter>
-</method>
-<method name="targetMethodTest6"
- return="long"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
+<constructor name="TestBadBootstrapArguments"
+ type="TestBadBootstrapArguments"
+ static="false"
final="false"
visibility="public"
>
-<parameter name="arg0" type="long">
-</parameter>
-<parameter name="arg1" type="long">
-</parameter>
-<parameter name="arg2" type="long">
-</parameter>
-</method>
-<method name="targetMethodTest7"
- return="double"
+</constructor>
+</class>
+<class name="TestInvokeCustomWithConcurrentThreads"
+ extends="TestBase"
+ interface="false"
abstract="false"
- native="false"
- synchronized="false"
- static="true"
+ static="false"
final="false"
visibility="public"
>
-<parameter name="arg0" type="float">
-</parameter>
-<parameter name="arg1" type="float">
-</parameter>
-<parameter name="arg2" type="double">
-</parameter>
-</method>
-<method name="targetMethodTest8"
- return="void"
+<implements name="java.lang.Runnable">
+</implements>
+<method name="notUsed"
+ return="int"
abstract="false"
native="false"
synchronized="false"
@@ -194,10 +64,10 @@
final="false"
visibility="public"
>
-<parameter name="arg0" type="java.lang.String">
+<parameter name="arg0" type="int">
</parameter>
</method>
-<method name="test1"
+<method name="test"
return="void"
abstract="false"
native="false"
@@ -207,47 +77,33 @@
visibility="public"
>
</method>
-<method name="test2"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- visibility="public"
->
-</method>
-<method name="test3"
+<method name="run"
return="void"
abstract="false"
native="false"
synchronized="false"
- static="true"
+ static="false"
final="false"
visibility="public"
>
</method>
-<method name="test4"
- return="void"
+</class>
+<class name="TestLinkerMethodMinimalArguments"
+ extends="TestBase"
+ interface="false"
abstract="false"
- native="false"
- synchronized="false"
- static="true"
+ static="false"
final="false"
visibility="public"
>
-</method>
-<method name="test5"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
+<constructor name="TestLinkerMethodMinimalArguments"
+ type="TestLinkerMethodMinimalArguments"
+ static="false"
final="false"
visibility="public"
>
-</method>
-<method name="test6"
+</constructor>
+<method name="test"
return="void"
abstract="false"
native="false"
@@ -256,28 +112,30 @@
final="false"
visibility="public"
>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+<parameter name="arg2" type="int">
+</parameter>
</method>
-<method name="test7"
- return="void"
+</class>
+<class name="TestLinkerMethodMultipleArgumentTypes"
+ extends="TestBase"
+ interface="false"
abstract="false"
- native="false"
- synchronized="false"
- static="true"
+ static="false"
final="false"
visibility="public"
>
-</method>
-<method name="test8"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
+<constructor name="TestLinkerMethodMultipleArgumentTypes"
+ type="TestLinkerMethodMultipleArgumentTypes"
+ static="false"
final="false"
visibility="public"
>
-</method>
-<method name="test9"
+</constructor>
+<method name="test"
return="void"
abstract="false"
native="false"
@@ -286,9 +144,13 @@
final="false"
visibility="public"
>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
</method>
-<method name="helperMethodTest9"
- return="void"
+<method name="GetBootstrapRunCount"
+ return="int"
abstract="false"
native="false"
synchronized="false"
@@ -297,229 +159,537 @@
visibility="public"
>
</method>
-<method name="run"
- return="void"
+</class>
+<class name="TestVariableArityLinkerMethod"
+ extends="TestBase"
+ interface="false"
abstract="false"
- native="false"
- synchronized="false"
static="false"
final="false"
visibility="public"
>
-</method>
-<method name="targetMethodTest4"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
+<constructor name="TestVariableArityLinkerMethod"
+ type="TestVariableArityLinkerMethod"
static="false"
final="false"
visibility="public"
>
-</method>
+</constructor>
</class>
<method_handle index="0"
- type="put-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="staticFieldTest9"
- target_member_type="I"
+ type="invoke-static"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsm"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ID)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="1"
- type="get-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="staticFieldTest9"
- target_member_type="I"
+ type="invoke-static"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsm"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="2"
- type="put-instance"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="fieldTest9"
- target_member_type="(Linvokecustom/InvokeCustom;"
+ type="invoke-static"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmDJ"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="3"
- type="get-instance"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="fieldTest9"
- target_member_type="(Linvokecustom/InvokeCustom;"
+ type="invoke-static"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmDoubleLong"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="4"
type="invoke-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="bsmCreateCallSite"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmReturningInteger"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;"
>
</method_handle>
<method_handle index="5"
type="invoke-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="bsmLookupStatic"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmReturningObject"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;"
>
</method_handle>
<method_handle index="6"
type="invoke-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="bsmLookupStaticWithExtraArgs"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IJFD)Ljava/lang/invoke/CallSite;"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmReturningTestersConstantCallsite"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;"
>
</method_handle>
<method_handle index="7"
type="invoke-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="bsmLookupTest9"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmReturningVoid"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V"
>
</method_handle>
<method_handle index="8"
type="invoke-static"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="lambda$lambdaTest$0"
- target_member_type="(Ljava/lang/String;)Z"
+ target_class="LTestBadBootstrapArguments;"
+ target_member="bsmZBCS"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="9"
type="invoke-static"
- target_class="Ljava/lang/invoke/LambdaMetafactory;"
- target_member="metafactory"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+ target_class="LTestDynamicBootstrapArguments;"
+ target_member="bsm"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="10"
- type="invoke-instance"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="helperMethodTest9"
- target_member_type="(Linvokecustom/InvokeCustom;)V"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupConstructor"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="11"
- type="invoke-instance"
- target_class="Ljava/io/PrintStream;"
- target_member="println"
- target_member_type="(Ljava/io/PrintStream;Ljava/lang/String;)V"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupInstanceFieldGetter"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="12"
- type="invoke-instance"
- target_class="Ljava/lang/String;"
- target_member="trim"
- target_member_type="(Ljava/lang/String;)Ljava/lang/String;"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupInstanceFieldSetter"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="13"
- type="invoke-constructor"
- target_class="Linvokecustom/InvokeCustom;"
- target_member="<init>"
- target_member_type="(Linvokecustom/InvokeCustom;I)V"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupStaticFieldGetter"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="14"
- type="invoke-direct"
- target_class="Linvokecustom/Super;"
- target_member="targetMethodTest4"
- target_member_type="(Linvokecustom/Super;)V"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupStaticFieldSetter"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
<method_handle index="15"
- type="invoke-interface"
- target_class="Ljava/lang/Runnable;"
- target_member="run"
- target_member_type="(Ljava/lang/Runnable;)V"
+ type="invoke-static"
+ target_class="LTestInvocationKinds;"
+ target_member="lookupVirtual"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="16"
+ type="invoke-static"
+ target_class="LTestInvokeCustomWithConcurrentThreads;"
+ target_member="linkerMethod"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="17"
+ type="invoke-static"
+ target_class="LTestLinkerMethodMinimalArguments;"
+ target_member="linkerMethod"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="18"
+ type="invoke-static"
+ target_class="LTestLinkerMethodMultipleArgumentTypes;"
+ target_member="linkerMethod"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="19"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithBoxedArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="20"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithClassAndFloatArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="21"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithClassArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="22"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithDoubleArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="23"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithFloatAndLongArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="24"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithIntAndStringArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="25"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithLongAndIntArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="26"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithStringArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="27"
+ type="invoke-static"
+ target_class="LTestVariableArityLinkerMethod;"
+ target_member="bsmWithWiderArray"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;"
+>
+</method_handle>
+<method_handle index="28"
+ type="invoke-static"
+ target_class="LUnrelatedBSM;"
+ target_member="bsm"
+ target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;"
>
</method_handle>
-<call_site index="0" offset="8450">
+<call_site index="0" offset="29649">
+<link_argument index="0" type="MethodHandle" value="1"/>
+<link_argument index="1" type="String" values="happy"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="-1"/>
+<link_argument index="4" type="String" value="very"/>
+</call_site>
+<call_site index="1" offset="29662">
+<link_argument index="0" type="MethodHandle" value="0"/>
+<link_argument index="1" type="String" values="wrongParameterTypes"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="-1"/>
+<link_argument index="4" type="String" value="very"/>
+</call_site>
+<call_site index="2" offset="29675">
+<link_argument index="0" type="MethodHandle" value="0"/>
+<link_argument index="1" type="String" values="missingParameterTypes"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+</call_site>
+<call_site index="3" offset="29683">
+<link_argument index="0" type="MethodHandle" value="1"/>
+<link_argument index="1" type="String" values="extraArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="1"/>
+<link_argument index="4" type="String" value="2"/>
+<link_argument index="5" type="int" value="3"/>
+</call_site>
+<call_site index="4" offset="29697">
+<link_argument index="0" type="MethodHandle" value="1"/>
+<link_argument index="1" type="String" values="wrongArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="String" value="1"/>
+<link_argument index="4" type="double" value="3.14159"/>
+</call_site>
+<call_site index="5" offset="29697">
+<link_argument index="0" type="MethodHandle" value="1"/>
+<link_argument index="1" type="String" values="wrongArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="String" value="1"/>
+<link_argument index="4" type="double" value="3.14159"/>
+</call_site>
+<call_site index="6" offset="29716">
+<link_argument index="0" type="MethodHandle" value="1"/>
+<link_argument index="1" type="String" values="wrongArgumentsAgain"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="double" value="3.14159"/>
+<link_argument index="4" type="String" value="pie"/>
+</call_site>
+<call_site index="7" offset="29736">
+<link_argument index="0" type="MethodHandle" value="8"/>
+<link_argument index="1" type="String" values="narrowArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="1"/>
+<link_argument index="4" type="int" value="127"/>
+<link_argument index="5" type="int" value="65"/>
+<link_argument index="6" type="int" value="-32768"/>
+</call_site>
+<call_site index="8" offset="29753">
+<link_argument index="0" type="MethodHandle" value="2"/>
+<link_argument index="1" type="String" values="wideningArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="double" value="1.79769e+308"/>
+<link_argument index="4" type="int" value="2147483647"/>
+</call_site>
+<call_site index="9" offset="29775">
+<link_argument index="0" type="MethodHandle" value="3"/>
+<link_argument index="1" type="String" values="boxingArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="double" value="1.79769e+308"/>
+<link_argument index="4" type="long" value="9223372036854775807"/>
+</call_site>
+<call_site index="10" offset="29800">
+<link_argument index="0" type="MethodHandle" value="3"/>
+<link_argument index="1" type="String" values="wideningBoxingArguments"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="float" value="3.40282e+38"/>
+<link_argument index="4" type="long" value="2147483647"/>
+</call_site>
+<call_site index="11" offset="29818">
+<link_argument index="0" type="MethodHandle" value="7"/>
+<link_argument index="1" type="String" values="voidReturnType"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+</call_site>
+<call_site index="12" offset="29826">
+<link_argument index="0" type="MethodHandle" value="5"/>
+<link_argument index="1" type="String" values="ObjectReturnType"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+</call_site>
+<call_site index="13" offset="29833">
+<link_argument index="0" type="MethodHandle" value="4"/>
+<link_argument index="1" type="String" values="integerReturnType"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+</call_site>
+<call_site index="14" offset="29841">
+<link_argument index="0" type="MethodHandle" value="6"/>
+<link_argument index="1" type="String" values="sayHello"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+</call_site>
+<call_site index="15" offset="29849">
<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="test"/>
-<link_argument index="2" type="MethodType" value="()Ljava/util/function/Predicate;"/>
-<link_argument index="3" type="MethodType" value="(Ljava/lang/Object;)Z"/>
-<link_argument index="4" type="MethodHandle" value="8"/>
-<link_argument index="5" type="MethodType" value="(Ljava/lang/String;)Z"/>
+<link_argument index="1" type="String" values="target"/>
+<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
+<link_argument index="3" type="String" value="A"/>
+<link_argument index="4" type="long" value="100000000"/>
</call_site>
-<call_site index="1" offset="8463">
+<call_site index="16" offset="29849">
<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="apply"/>
-<link_argument index="2" type="MethodType" value="()Ljava/util/function/Function;"/>
-<link_argument index="3" type="MethodType" value="(Ljava/lang/Object;)Ljava/lang/Object;"/>
-<link_argument index="4" type="MethodHandle" value="12"/>
-<link_argument index="5" type="MethodType" value="(Ljava/lang/String;)Ljava/lang/String;"/>
+<link_argument index="1" type="String" values="target"/>
+<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
+<link_argument index="3" type="String" value="A"/>
+<link_argument index="4" type="long" value="100000000"/>
</call_site>
-<call_site index="2" offset="8476">
+<call_site index="17" offset="29849">
<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="accept"/>
-<link_argument index="2" type="MethodType" value="(Ljava/io/PrintStream;)Ljava/util/function/Consumer;"/>
-<link_argument index="3" type="MethodType" value="(Ljava/lang/Object;)V"/>
-<link_argument index="4" type="MethodHandle" value="11"/>
-<link_argument index="5" type="MethodType" value="(Ljava/lang/String;)V"/>
+<link_argument index="1" type="String" values="target"/>
+<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
+<link_argument index="3" type="String" value="A"/>
+<link_argument index="4" type="long" value="100000000"/>
</call_site>
-<call_site index="3" offset="8489">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest1"/>
+<call_site index="18" offset="29864">
+<link_argument index="0" type="MethodHandle" value="10"/>
+<link_argument index="1" type="String" values="unused"/>
+<link_argument index="2" type="MethodType" value="(I)LTestInvocationKinds$Widget;"/>
+</call_site>
+<call_site index="19" offset="29872">
+<link_argument index="0" type="MethodHandle" value="12"/>
+<link_argument index="1" type="String" values="instance_field"/>
+<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;D)V"/>
+</call_site>
+<call_site index="20" offset="29880">
+<link_argument index="0" type="MethodHandle" value="11"/>
+<link_argument index="1" type="String" values="instance_field"/>
+<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;)D"/>
+</call_site>
+<call_site index="21" offset="29888">
+<link_argument index="0" type="MethodHandle" value="15"/>
+<link_argument index="1" type="String" values="getMaxIntegerValue"/>
+<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;II)I"/>
+</call_site>
+<call_site index="22" offset="29896">
+<link_argument index="0" type="MethodHandle" value="14"/>
+<link_argument index="1" type="String" values="static_field"/>
+<link_argument index="2" type="MethodType" value="(I)V"/>
+</call_site>
+<call_site index="23" offset="29896">
+<link_argument index="0" type="MethodHandle" value="14"/>
+<link_argument index="1" type="String" values="static_field"/>
+<link_argument index="2" type="MethodType" value="(I)V"/>
+</call_site>
+<call_site index="24" offset="29904">
+<link_argument index="0" type="MethodHandle" value="13"/>
+<link_argument index="1" type="String" values="static_field"/>
+<link_argument index="2" type="MethodType" value="()I"/>
+</call_site>
+<call_site index="25" offset="29904">
+<link_argument index="0" type="MethodHandle" value="13"/>
+<link_argument index="1" type="String" values="static_field"/>
+<link_argument index="2" type="MethodType" value="()I"/>
+</call_site>
+<call_site index="26" offset="29912">
+<link_argument index="0" type="MethodHandle" value="16"/>
+<link_argument index="1" type="String" values="setCalled"/>
+<link_argument index="2" type="MethodType" value="(I)I"/>
+</call_site>
+<call_site index="27" offset="29920">
+<link_argument index="0" type="MethodHandle" value="17"/>
+<link_argument index="1" type="String" values="_add"/>
+<link_argument index="2" type="MethodType" value="(II)I"/>
+</call_site>
+<call_site index="28" offset="29927">
+<link_argument index="0" type="MethodHandle" value="18"/>
+<link_argument index="1" type="String" values="_add"/>
+<link_argument index="2" type="MethodType" value="(II)I"/>
+<link_argument index="3" type="int" value="-1"/>
+<link_argument index="4" type="int" value="1"/>
+<link_argument index="5" type="int" value="97"/>
+<link_argument index="6" type="int" value="1024"/>
+<link_argument index="7" type="int" value="1"/>
+<link_argument index="8" type="float" value="11.1"/>
+<link_argument index="9" type="double" value="2.2"/>
+<link_argument index="10" type="String" value="Hello"/>
+<link_argument index="11" type="Class" value="LTestLinkerMethodMultipleArgumentTypes;"/>
+<link_argument index="12" type="long" value="123456789"/>
+</call_site>
+<call_site index="29" offset="29968">
+<link_argument index="0" type="MethodHandle" value="28"/>
+<link_argument index="1" type="String" values="_addf"/>
+<link_argument index="2" type="MethodType" value="(FF)F"/>
+<link_argument index="3" type="Class" value="LTestLinkerUnrelatedBSM;"/>
+</call_site>
+<call_site index="30" offset="29977">
+<link_argument index="0" type="MethodHandle" value="28"/>
+<link_argument index="1" type="String" values="_subf"/>
+<link_argument index="2" type="MethodType" value="(FF)F"/>
+<link_argument index="3" type="Class" value="LTestLinkerUnrelatedBSM;"/>
+</call_site>
+<call_site index="31" offset="29986">
+<link_argument index="0" type="MethodHandle" value="26"/>
+<link_argument index="1" type="String" values="methodA"/>
<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="String" value="Aachen"/>
+<link_argument index="4" type="String" value="Aalborg"/>
+<link_argument index="5" type="String" value="Aalto"/>
</call_site>
-<call_site index="4" offset="8496">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest2"/>
-<link_argument index="2" type="MethodType" value="(ZBCSIFJDLjava/lang/String;)V"/>
+<call_site index="32" offset="30000">
+<link_argument index="0" type="MethodHandle" value="26"/>
+<link_argument index="1" type="String" values="methodB"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="String" value="barium"/>
</call_site>
-<call_site index="5" offset="8503">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest5"/>
-<link_argument index="2" type="MethodType" value="(III)I"/>
+<call_site index="33" offset="30010">
+<link_argument index="0" type="MethodHandle" value="26"/>
+<link_argument index="1" type="String" values="methodC"/>
+<link_argument index="2" type="MethodType" value="()V"/>
</call_site>
-<call_site index="6" offset="8510">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest6"/>
-<link_argument index="2" type="MethodType" value="(JJJ)J"/>
+<call_site index="34" offset="30018">
+<link_argument index="0" type="MethodHandle" value="24"/>
+<link_argument index="1" type="String" values="methodD"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="101"/>
+<link_argument index="4" type="String" value="zoo"/>
+<link_argument index="5" type="String" value="zoogene"/>
+<link_argument index="6" type="String" value="zoogenic"/>
</call_site>
-<call_site index="7" offset="8517">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest7"/>
-<link_argument index="2" type="MethodType" value="(FFD)D"/>
+<call_site index="35" offset="30037">
+<link_argument index="0" type="MethodHandle" value="24"/>
+<link_argument index="1" type="String" values="methodE"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="102"/>
+<link_argument index="4" type="String" value="zonic"/>
</call_site>
-<call_site index="8" offset="8524">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest8"/>
-<link_argument index="2" type="MethodType" value="(Ljava/lang/String;)V"/>
+<call_site index="36" offset="30050">
+<link_argument index="0" type="MethodHandle" value="24"/>
+<link_argument index="1" type="String" values="methodF"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="103"/>
</call_site>
-<call_site index="9" offset="8524">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest8"/>
-<link_argument index="2" type="MethodType" value="(Ljava/lang/String;)V"/>
+<call_site index="37" offset="30060">
+<link_argument index="0" type="MethodHandle" value="25"/>
+<link_argument index="1" type="String" values="methodG"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="long" value="81985529216486895"/>
+<link_argument index="4" type="int" value="1"/>
+<link_argument index="5" type="int" value="-1"/>
+<link_argument index="6" type="int" value="2"/>
+<link_argument index="7" type="int" value="-2"/>
</call_site>
-<call_site index="10" offset="8524">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="targetMethodTest8"/>
-<link_argument index="2" type="MethodType" value="(Ljava/lang/String;)V"/>
+<call_site index="38" offset="30085">
+<link_argument index="0" type="MethodHandle" value="23"/>
+<link_argument index="1" type="String" values="methodH"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="float" value="-2.71828"/>
+<link_argument index="4" type="long" value="999999999999"/>
+<link_argument index="5" type="long" value="-8888888888888"/>
</call_site>
-<call_site index="11" offset="8531">
-<link_argument index="0" type="MethodHandle" value="6"/>
-<link_argument index="1" type="String" values="targetMethodTest3"/>
+<call_site index="39" offset="30112">
+<link_argument index="0" type="MethodHandle" value="20"/>
+<link_argument index="1" type="String" values="methodI"/>
<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="1"/>
-<link_argument index="4" type="long" value="123456789"/>
-<link_argument index="5" type="float" value="123.456"/>
-<link_argument index="6" type="double" value="123457"/>
+<link_argument index="3" type="Class" value="Ljava/lang/Throwable;"/>
+<link_argument index="4" type="float" value="3.40282e+38"/>
+<link_argument index="5" type="float" value="1.4013e-45"/>
+<link_argument index="6" type="float" value="3.14159"/>
+<link_argument index="7" type="float" value="-3.14159"/>
</call_site>
-<call_site index="12" offset="8559">
-<link_argument index="0" type="MethodHandle" value="4"/>
-<link_argument index="1" type="String" values="targetMethodTest4"/>
-<link_argument index="2" type="MethodType" value="(Linvokecustom/InvokeCustom;)V"/>
-<link_argument index="3" type="MethodHandle" value="14"/>
+<call_site index="40" offset="30142">
+<link_argument index="0" type="MethodHandle" value="22"/>
+<link_argument index="1" type="String" values="methodJ"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="double" value="1.79769e+308"/>
+<link_argument index="4" type="double" value="4.94066e-324"/>
+<link_argument index="5" type="double" value="2.71828"/>
+<link_argument index="6" type="double" value="-3.14159"/>
</call_site>
-<call_site index="13" offset="8568">
-<link_argument index="0" type="MethodHandle" value="7"/>
-<link_argument index="1" type="String" values="targetMethodTest9"/>
+<call_site index="41" offset="30186">
+<link_argument index="0" type="MethodHandle" value="21"/>
+<link_argument index="1" type="String" values="methodK"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="Class" value="Ljava/lang/Integer;"/>
+<link_argument index="4" type="Class" value="Ljava/lang/invoke/MethodHandles;"/>
+<link_argument index="5" type="Class" value="Ljava/util/Arrays;"/>
+</call_site>
+<call_site index="42" offset="30200">
+<link_argument index="0" type="MethodHandle" value="24"/>
+<link_argument index="1" type="String" values="methodO"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="103"/>
+<link_argument index="4" type="int" value="104"/>
+</call_site>
+<call_site index="43" offset="30212">
+<link_argument index="0" type="MethodHandle" value="24"/>
+<link_argument index="1" type="String" values="methodP"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="103"/>
+<link_argument index="4" type="String" value="A"/>
+<link_argument index="5" type="String" value="B"/>
+<link_argument index="6" type="int" value="42"/>
+</call_site>
+<call_site index="44" offset="30228">
+<link_argument index="0" type="MethodHandle" value="27"/>
+<link_argument index="1" type="String" values="methodQ"/>
+<link_argument index="2" type="MethodType" value="()V"/>
+<link_argument index="3" type="int" value="103"/>
+<link_argument index="4" type="int" value="42"/>
+</call_site>
+<call_site index="45" offset="30240">
+<link_argument index="0" type="MethodHandle" value="19"/>
+<link_argument index="1" type="String" values="methodR"/>
<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="MethodHandle" value="1"/>
-<link_argument index="4" type="MethodHandle" value="0"/>
-<link_argument index="5" type="MethodHandle" value="3"/>
-<link_argument index="6" type="MethodHandle" value="2"/>
-<link_argument index="7" type="MethodHandle" value="10"/>
-<link_argument index="8" type="MethodHandle" value="13"/>
-<link_argument index="9" type="MethodHandle" value="15"/>
+<link_argument index="3" type="int" value="1030"/>
+<link_argument index="4" type="int" value="420"/>
</call_site>
</package>
</api>
diff --git a/test/dexdump/run-all-tests b/test/dexdump/run-all-tests
index c9976cd090..e555a44e5d 100755
--- a/test/dexdump/run-all-tests
+++ b/test/dexdump/run-all-tests
@@ -37,51 +37,73 @@ prog="${progdir}"/`basename "${prog}"`
tmpdir=/tmp/test-$$
mkdir ${tmpdir}
-# Set up dexdump binary and flags to test.
-DEXD="${ANDROID_HOST_OUT}/bin/dexdump2"
-DEXDFLAGS1="-adfh"
-DEXDFLAGS2="-e -l xml"
+# Set up tools and commands to run
+DEXDUMP="${ANDROID_HOST_OUT}/bin/dexdump2"
+DEXLIST="${ANDROID_HOST_OUT}/bin/dexlist"
-# Set up dexlist binary and flags to test.
-DEXL="${ANDROID_HOST_OUT}/bin/dexlist"
-DEXLFLAGS=""
+declare -A SUFFIX_COMMAND_MAP
+SUFFIX_COMMAND_MAP[txt]="${DEXDUMP} -adfh"
+SUFFIX_COMMAND_MAP[xml]="${DEXDUMP} -e -l xml"
+SUFFIX_COMMAND_MAP[lst]="${DEXLIST}"
+
+# Parse command-line options
+UPDATE="no"
+USAGE="no"
+while [ $# -ne 0 ]; do
+ case "$1" in
+ --update)
+ UPDATE="yes"
+ ;;
+ *)
+ echo "Unknown option $1" 1>&2
+ USAGE="yes"
+ ;;
+ esac
+ shift
+done
+
+if [ "${USAGE}" = "yes" ]; then
+ cat 1>&2 <<USAGE_END
+Usage:
+ ${prog##*/} [--update]
+Options:
+ --update Update reference outputs
+USAGE_END
+ exit 1
+fi
+
+if [ "${UPDATE}" = "yes" ]; then
+ for dex in *.dex; do
+ for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
+ new_output=${dex%%.*}.${suffix}
+ ${SUFFIX_COMMAND_MAP[${suffix}]} ${dex} > ${new_output}
+ if [ $? -ne 0 ]; then
+ echo "Failed running ${SUFFIX_COMMAND_MAP[${suffix}]} ${dex} > ${new_output}" 2>&1
+ exit 1
+ fi
+ done
+ done
+ exit 0
+fi
# Run the tests.
passed=0
failed=0
-for i in *.dex; do
- echo $i
- basenm=`basename "${i}" .dex`
- txtfile=${basenm}.txt
- xmlfile=${basenm}.xml
- lstfile=${basenm}.lst
- gentxtfile=${tmpdir}/${txtfile}
- genxmlfile=${tmpdir}/${xmlfile}
- genlstfile=${tmpdir}/${lstfile}
- ${DEXD} ${DEXDFLAGS1} ${i} > ${gentxtfile}
- cmp ${txtfile} ${gentxtfile}
- if [ "$?" = "0" ]; then
- ((passed += 1))
- else
- ((failed += 1))
- echo failed: ${i}
- fi
- ${DEXD} ${DEXDFLAGS2} ${i} > ${genxmlfile}
- cmp ${xmlfile} ${genxmlfile}
- if [ "$?" = "0" ]; then
- ((passed += 1))
- else
- ((failed += 1))
- echo failed: ${i}
- fi
- ${DEXL} ${DEXLFLAGS} ${i} > ${genlstfile}
- cmp ${lstfile} ${genlstfile}
+for dex in *.dex; do
+ echo ${dex}
+ for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
+ expected_output=${dex%%.*}.${suffix}
+ actual_output=${tmpdir}/${expected_output}
+ cmd="${SUFFIX_COMMAND_MAP[${suffix}]} ${dex}"
+ ${cmd} > ${actual_output}
+ cmp ${expected_output} ${actual_output}
if [ "$?" = "0" ]; then
((passed += 1))
else
((failed += 1))
- echo failed: ${i}
+ echo failed: ${cmd}
fi
+ done
done
# Report results.
diff --git a/test/etc/default-build b/test/etc/default-build
index d0ebe80e68..9dbc73c6b4 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -169,6 +169,9 @@ while true; do
elif [ "x$1" = "x--no-smali" ]; then
HAS_SMALI=false
shift
+ elif [ "x$1" = "x--no-jasmin" ]; then
+ HAS_JASMIN=false
+ shift
elif [ "x$1" = "x--experimental" ]; then
shift
# We have a specific experimental configuration so don't use the default.
diff --git a/test/run-test b/test/run-test
index 8e012d13fb..5bd8b3b348 100755
--- a/test/run-test
+++ b/test/run-test
@@ -441,6 +441,11 @@ while true; do
fi
done
+if [ "$usage" = "no" -a "x$1" = "x" ]; then
+ echo "missing test to run" 1>&2
+ usage="yes"
+fi
+
# The DEX_LOCATION with the chroot prefix, if any.
chroot_dex_location="$chroot$DEX_LOCATION"
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 09b9b210fc..2d1398e3fe 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -320,12 +320,6 @@ def run_tests(tests):
if env.ART_TEST_BISECTION:
options_all += ' --bisection-search'
- if env.ART_TEST_CHROOT:
- options_all += ' --chroot ' + env.ART_TEST_CHROOT
-
- if env.ART_TEST_ANDROID_ROOT:
- options_all += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
-
if gdb:
options_all += ' --gdb'
if gdb_arg:
@@ -401,6 +395,13 @@ def run_tests(tests):
elif target == 'jvm':
options_test += ' --jvm'
+ # Honor ART_TEST_CHROOT and ART_TEST_ANDROID_ROOT, but only for target tests.
+ if target == 'target':
+ if env.ART_TEST_CHROOT:
+ options_test += ' --chroot ' + env.ART_TEST_CHROOT
+ if env.ART_TEST_ANDROID_ROOT:
+ options_test += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
+
if run == 'ndebug':
options_test += ' -O'
@@ -411,8 +412,9 @@ def run_tests(tests):
elif prebuild == 'no-dex2oat':
options_test += ' --no-prebuild --no-dex2oat'
- # Add option and remove the cdex- prefix.
- options_test += ' --compact-dex-level ' + cdex_level.replace('cdex-','')
+ if cdex_level:
+ # Add option and remove the cdex- prefix.
+ options_test += ' --compact-dex-level ' + cdex_level.replace('cdex-','')
if compiler == 'optimizing':
options_test += ' --optimizing'
diff --git a/tools/build/var_list b/tools/build/var_list
index adcb066f7c..bb005cf77c 100644
--- a/tools/build/var_list
+++ b/tools/build/var_list
@@ -33,5 +33,4 @@ TARGET_ARCH
HOST_PREFER_32_BIT
HOST_OUT_EXECUTABLES
ANDROID_JAVA_TOOLCHAIN
-ANDROID_COMPILE_WITH_JACK
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 10eb9360af..830505124e 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -32,8 +32,6 @@ else
out_dir=${OUT_DIR}
fi
-using_jack=$(get_build_var ANDROID_COMPILE_WITH_JACK)
-
java_libraries_dir=${out_dir}/target/common/obj/JAVA_LIBRARIES
common_targets="vogar core-tests apache-harmony-jdwp-tests-hostdex jsr166-tests mockito-target"
mode="target"
@@ -62,10 +60,6 @@ while true; do
fi
done
-if [[ $using_jack == "true" ]]; then
- common_targets="$common_targets ${out_dir}/host/linux-x86/bin/jack"
-fi
-
# Allow to build successfully in master-art.
extra_args=SOONG_ALLOW_MISSING_DEPENDENCIES=true
diff --git a/tools/cleanup-buildbot-device.sh b/tools/cleanup-buildbot-device.sh
index 2144b02c2f..ca5219aa25 100755
--- a/tools/cleanup-buildbot-device.sh
+++ b/tools/cleanup-buildbot-device.sh
@@ -40,7 +40,7 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then
#
# TODO: Reorder ART Buildbot steps so that "device cleanup" happens
# before "setup device" and remove this special case.
- adb shell test -f "$ART_TEST_CHROOT/system" \
+ adb shell test -d "$ART_TEST_CHROOT/system" \
"&&" find "$ART_TEST_CHROOT/system" \
! -path "$ART_TEST_CHROOT/system/etc/selinux/plat_property_contexts" \
! -type d \
diff --git a/tools/common/common.py b/tools/common/common.py
index 735bbaa4a4..b728e8d927 100755
--- a/tools/common/common.py
+++ b/tools/common/common.py
@@ -116,14 +116,6 @@ def GetEnvVariableOrError(variable_name):
return top
-def GetJackClassPath():
- """Returns Jack's classpath."""
- top = GetEnvVariableOrError('ANDROID_BUILD_TOP')
- libdir = top + '/out/host/common/obj/JAVA_LIBRARIES'
- return libdir + '/core-libart-hostdex_intermediates/classes.jack:' \
- + libdir + '/core-oj-hostdex_intermediates/classes.jack'
-
-
def _DexArchCachePaths(android_data_path):
"""Returns paths to architecture specific caches.
diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc
index 46c48520e3..7a9b8fb018 100644
--- a/tools/dexanalyze/dexanalyze.cc
+++ b/tools/dexanalyze/dexanalyze.cc
@@ -49,7 +49,9 @@ class DexAnalyze {
<< "Usage " << argv[0] << " [options] <dex files>\n"
<< " [options] is a combination of the following\n"
<< " -count_indices (Count dex indices accessed from code items)\n"
- << " -i (Ignore DEX checksum failure)\n"
+ << " -analyze-strings (Analyze string data)\n"
+ << " -analyze-debug-info (Analyze debug info)\n"
+ << " -i (Ignore Dex checksum and verification failures)\n"
<< " -a (Run all experiments)\n"
<< " -d (Dump on per DEX basis)\n";
return kExitCodeUsageError;
@@ -62,12 +64,15 @@ class DexAnalyze {
const std::string arg = argv[i];
if (arg == "-i") {
verify_checksum_ = false;
+ run_dex_file_verifier_ = false;
} else if (arg == "-a") {
run_all_experiments_ = true;
} else if (arg == "-count-indices") {
exp_count_indices_ = true;
} else if (arg == "-analyze-strings") {
exp_analyze_strings_ = true;
+ } else if (arg == "-analyze-debug-info") {
+ exp_debug_info_ = true;
} else if (arg == "-d") {
dump_per_input_dex_ = true;
} else if (!arg.empty() && arg[0] == '-') {
@@ -87,7 +92,9 @@ class DexAnalyze {
bool run_dex_file_verifier_ = true;
bool dump_per_input_dex_ = false;
bool exp_count_indices_ = false;
+ bool exp_code_metrics_ = false;
bool exp_analyze_strings_ = false;
+ bool exp_debug_info_ = false;
bool run_all_experiments_ = false;
std::vector<std::string> filenames_;
};
@@ -101,20 +108,29 @@ class DexAnalyze {
if (options->run_all_experiments_ || options->exp_analyze_strings_) {
experiments_.emplace_back(new AnalyzeStrings);
}
+ if (options->run_all_experiments_ || options->exp_code_metrics_) {
+ experiments_.emplace_back(new CodeMetrics);
+ }
+ if (options->run_all_experiments_ || options->exp_debug_info_) {
+ experiments_.emplace_back(new AnalyzeDebugInfo);
+ }
}
- bool ProcessDexFile(const DexFile& dex_file) {
+ bool ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
for (std::unique_ptr<Experiment>& experiment : experiments_) {
- experiment->ProcessDexFile(dex_file);
+ experiment->ProcessDexFiles(dex_files);
+ }
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ total_size_ += dex_file->Size();
}
- total_size_ += dex_file.Size();
- ++dex_count_;
+ dex_count_ += dex_files.size();
return true;
}
void Dump(std::ostream& os) {
for (std::unique_ptr<Experiment>& experiment : experiments_) {
experiment->Dump(os, total_size_);
+ os << "\n";
}
}
@@ -155,18 +171,16 @@ class DexAnalyze {
LOG(ERROR) << "OpenAll failed for " + filename << " with " << error_msg << std::endl;
return kExitCodeFailedToOpenDex;
}
- for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
- if (options.dump_per_input_dex_) {
- Analysis current(&options);
- if (!current.ProcessDexFile(*dex_file)) {
- LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg;
- return kExitCodeFailedToProcessDex;
- }
- LOG(INFO) << "Analysis for " << dex_file->GetLocation() << std::endl;
- current.Dump(LOG_STREAM(INFO));
+ if (options.dump_per_input_dex_) {
+ Analysis current(&options);
+ if (!current.ProcessDexFiles(dex_files)) {
+ LOG(ERROR) << "Failed to process " << filename << " with error " << error_msg;
+ return kExitCodeFailedToProcessDex;
}
- cumulative.ProcessDexFile(*dex_file);
+ LOG(INFO) << "Analysis for " << filename << std::endl;
+ current.Dump(LOG_STREAM(INFO));
}
+ cumulative.ProcessDexFiles(dex_files);
}
LOG(INFO) << "Cumulative analysis for " << cumulative.dex_count_ << " DEX files" << std::endl;
cumulative.Dump(LOG_STREAM(INFO));
diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc
index 312a7b3159..244f45bbe6 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -32,13 +32,41 @@
namespace art {
+static inline bool IsRange(Instruction::Code code) {
+ return code == Instruction::INVOKE_VIRTUAL_RANGE ||
+ code == Instruction::INVOKE_DIRECT_RANGE ||
+ code == Instruction::INVOKE_SUPER_RANGE ||
+ code == Instruction::INVOKE_STATIC_RANGE ||
+ code == Instruction::INVOKE_INTERFACE_RANGE;
+}
+
+static inline uint16_t NumberOfArgs(const Instruction& inst) {
+ return IsRange(inst.Opcode()) ? inst.VRegA_3rc() : inst.VRegA_35c();
+}
+
+static inline uint16_t DexMethodIndex(const Instruction& inst) {
+ return IsRange(inst.Opcode()) ? inst.VRegB_3rc() : inst.VRegB_35c();
+}
+
std::string Percent(uint64_t value, uint64_t max) {
if (max == 0) {
- ++max;
+ return "0";
}
- return android::base::StringPrintf("%" PRId64 "(%.2f%%)",
- value,
- static_cast<double>(value * 100) / static_cast<double>(max));
+ return android::base::StringPrintf(
+ "%" PRId64 "(%.2f%%)",
+ value,
+ static_cast<double>(value * 100) / static_cast<double>(max));
+}
+
+std::string PercentDivide(uint64_t value, uint64_t max) {
+ if (max == 0) {
+ return "0";
+ }
+ return android::base::StringPrintf(
+ "%" PRId64 "/%" PRId64 "(%.2f%%)",
+ value,
+ max,
+ static_cast<double>(value * 100) / static_cast<double>(max));
}
static size_t PrefixLen(const std::string& a, const std::string& b) {
@@ -47,6 +75,137 @@ static size_t PrefixLen(const std::string& a, const std::string& b) {
return len;
}
+void Experiment::ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ ProcessDexFile(*dex_file);
+ }
+}
+
+void AnalyzeDebugInfo::ProcessDexFiles(
+ const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
+ std::set<const uint8_t*> seen;
+ std::vector<size_t> counts(256, 0u);
+ std::vector<size_t> opcode_counts(256, 0u);
+ std::set<std::vector<uint8_t>> unique_non_header;
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ CodeItemDebugInfoAccessor code_item(*dex_file, method.GetCodeItem(), method.GetIndex());
+ const uint8_t* debug_info = dex_file->GetDebugInfoStream(code_item.DebugInfoOffset());
+ if (debug_info != nullptr && seen.insert(debug_info).second) {
+ const uint8_t* stream = debug_info;
+ DecodeUnsignedLeb128(&stream); // line_start
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ for (uint32_t i = 0; i < parameters_size; ++i) {
+ DecodeUnsignedLeb128P1(&stream); // Parameter name.
+ }
+ bool done = false;
+ const uint8_t* after_header_start = stream;
+ while (!done) {
+ const uint8_t* const op_start = stream;
+ uint8_t opcode = *stream++;
+ ++opcode_counts[opcode];
+ ++total_opcode_bytes_;
+ switch (opcode) {
+ case DexFile::DBG_END_SEQUENCE:
+ ++total_end_seq_bytes_;
+ done = true;
+ break;
+ case DexFile::DBG_ADVANCE_PC:
+ DecodeUnsignedLeb128(&stream); // addr_diff
+ total_advance_pc_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_ADVANCE_LINE:
+ DecodeSignedLeb128(&stream); // line_diff
+ total_advance_line_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_START_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ total_start_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_START_LOCAL_EXTENDED:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ DecodeUnsignedLeb128P1(&stream); // sig_idx
+ total_start_local_extended_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_END_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ total_end_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_RESTART_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ total_restart_local_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_SET_PROLOGUE_END:
+ case DexFile::DBG_SET_EPILOGUE_BEGIN:
+ total_epilogue_bytes_ += stream - op_start;
+ break;
+ case DexFile::DBG_SET_FILE: {
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ total_set_file_bytes_ += stream - op_start;
+ break;
+ }
+ default: {
+ total_other_bytes_ += stream - op_start;
+ break;
+ }
+ }
+ }
+ const size_t bytes = stream - debug_info;
+ total_bytes_ += bytes;
+ total_non_header_bytes_ += stream - after_header_start;
+ if (unique_non_header.insert(std::vector<uint8_t>(after_header_start, stream)).second) {
+ total_unique_non_header_bytes_ += stream - after_header_start;
+ }
+ for (size_t i = 0; i < bytes; ++i) {
+ ++counts[debug_info[i]];
+ }
+ }
+ }
+ }
+ }
+ auto calc_entropy = [](std::vector<size_t> data) {
+ size_t total = std::accumulate(data.begin(), data.end(), 0u);
+ double avg_entropy = 0.0;
+ for (size_t c : data) {
+ if (c > 0) {
+ double ratio = static_cast<double>(c) / static_cast<double>(total);
+ avg_entropy -= ratio * log(ratio) / log(256.0);
+ }
+ }
+ return avg_entropy * total;
+ };
+ total_entropy_ += calc_entropy(counts);
+ total_opcode_entropy_ += calc_entropy(opcode_counts);
+}
+
+void AnalyzeDebugInfo::Dump(std::ostream& os, uint64_t total_size) const {
+ os << "Debug info bytes " << Percent(total_bytes_, total_size) << "\n";
+
+ os << " DBG_END_SEQUENCE: " << Percent(total_end_seq_bytes_, total_size) << "\n";
+ os << " DBG_ADVANCE_PC: " << Percent(total_advance_pc_bytes_, total_size) << "\n";
+ os << " DBG_ADVANCE_LINE: " << Percent(total_advance_line_bytes_, total_size) << "\n";
+ os << " DBG_START_LOCAL: " << Percent(total_start_local_bytes_, total_size) << "\n";
+ os << " DBG_START_LOCAL_EXTENDED: "
+ << Percent(total_start_local_extended_bytes_, total_size) << "\n";
+ os << " DBG_END_LOCAL: " << Percent(total_end_local_bytes_, total_size) << "\n";
+ os << " DBG_RESTART_LOCAL: " << Percent(total_restart_local_bytes_, total_size) << "\n";
+ os << " DBG_SET_PROLOGUE bytes " << Percent(total_epilogue_bytes_, total_size) << "\n";
+ os << " DBG_SET_FILE bytes " << Percent(total_set_file_bytes_, total_size) << "\n";
+ os << " special: "
+ << Percent(total_other_bytes_, total_size) << "\n";
+ os << "Debug info entropy " << Percent(total_entropy_, total_size) << "\n";
+ os << "Debug info opcode bytes " << Percent(total_opcode_bytes_, total_size) << "\n";
+ os << "Debug info opcode entropy " << Percent(total_opcode_entropy_, total_size) << "\n";
+ os << "Debug info non header bytes " << Percent(total_non_header_bytes_, total_size) << "\n";
+ os << "Debug info deduped non header bytes "
+ << Percent(total_unique_non_header_bytes_, total_size) << "\n";
+}
+
void AnalyzeStrings::ProcessDexFile(const DexFile& dex_file) {
std::vector<std::string> strings;
for (size_t i = 0; i < dex_file.NumStringIds(); ++i) {
@@ -126,11 +285,13 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
num_field_ids_ += dex_file.NumFieldIds();
num_type_ids_ += dex_file.NumTypeIds();
num_class_defs_ += dex_file.NumClassDefs();
+ std::set<size_t> unique_code_items;
for (ClassAccessor accessor : dex_file.GetClasses()) {
std::set<size_t> unique_method_ids;
std::set<size_t> unique_string_ids;
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
dex_code_bytes_ += method.GetInstructions().InsnsSizeInBytes();
+ unique_code_items.insert(method.GetCodeItemOffset());
for (const DexInstructionPcPair& inst : method.GetInstructions()) {
switch (inst->Opcode()) {
case Instruction::CONST_STRING: {
@@ -148,48 +309,63 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
// Invoke cases.
case Instruction::INVOKE_VIRTUAL:
case Instruction::INVOKE_VIRTUAL_RANGE: {
- bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE);
- uint32_t method_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
+ uint32_t method_idx = DexMethodIndex(inst.Inst());
if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetClassIdx()) {
++same_class_virtual_;
- } else {
- ++other_class_virtual_;
- unique_method_ids.insert(method_idx);
}
+ ++total_virtual_;
+ unique_method_ids.insert(method_idx);
break;
}
case Instruction::INVOKE_DIRECT:
case Instruction::INVOKE_DIRECT_RANGE: {
- bool is_range = (inst->Opcode() == Instruction::INVOKE_DIRECT_RANGE);
- uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ uint32_t method_idx = DexMethodIndex(inst.Inst());
if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetClassIdx()) {
++same_class_direct_;
- } else {
- ++other_class_direct_;
- unique_method_ids.insert(method_idx);
}
+ ++total_direct_;
+ unique_method_ids.insert(method_idx);
break;
}
case Instruction::INVOKE_STATIC:
case Instruction::INVOKE_STATIC_RANGE: {
- bool is_range = (inst->Opcode() == Instruction::INVOKE_STATIC_RANGE);
- uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ uint32_t method_idx = DexMethodIndex(inst.Inst());
if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetClassIdx()) {
++same_class_static_;
- } else {
- ++other_class_static_;
- unique_method_ids.insert(method_idx);
}
+ ++total_static_;
+ unique_method_ids.insert(method_idx);
+ break;
+ }
+ case Instruction::INVOKE_INTERFACE:
+ case Instruction::INVOKE_INTERFACE_RANGE: {
+ uint32_t method_idx = DexMethodIndex(inst.Inst());
+ if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetClassIdx()) {
+ ++same_class_interface_;
+ }
+ ++total_interface_;
+ unique_method_ids.insert(method_idx);
+ break;
+ }
+ case Instruction::INVOKE_SUPER:
+ case Instruction::INVOKE_SUPER_RANGE: {
+ uint32_t method_idx = DexMethodIndex(inst.Inst());
+ if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetClassIdx()) {
+ ++same_class_super_;
+ }
+ ++total_super_;
+ unique_method_ids.insert(method_idx);
break;
}
default:
break;
}
}
- });
+ }
total_unique_method_idx_ += unique_method_ids.size();
total_unique_string_ids_ += unique_string_ids.size();
}
+ total_unique_code_items_ += unique_code_items.size();
}
void CountDexIndices::Dump(std::ostream& os, uint64_t total_size) const {
@@ -198,22 +374,75 @@ void CountDexIndices::Dump(std::ostream& os, uint64_t total_size) const {
os << "Num field ids: " << num_field_ids_ << "\n";
os << "Num type ids: " << num_type_ids_ << "\n";
os << "Num class defs: " << num_class_defs_ << "\n";
- os << "Same class direct: " << same_class_direct_ << "\n";
- os << "Other class direct: " << other_class_direct_ << "\n";
- os << "Same class virtual: " << same_class_virtual_ << "\n";
- os << "Other class virtual: " << other_class_virtual_ << "\n";
- os << "Same class static: " << same_class_static_ << "\n";
- os << "Other class static: " << other_class_static_ << "\n";
+ os << "Direct same class: " << PercentDivide(same_class_direct_, total_direct_) << "\n";
+ os << "Virtual same class: " << PercentDivide(same_class_virtual_, total_virtual_) << "\n";
+ os << "Static same class: " << PercentDivide(same_class_static_, total_static_) << "\n";
+ os << "Interface same class: " << PercentDivide(same_class_interface_, total_interface_) << "\n";
+ os << "Super same class: " << PercentDivide(same_class_super_, total_super_) << "\n";
os << "Num strings accessed from code: " << num_string_ids_from_code_ << "\n";
os << "Unique(per class) method ids accessed from code: " << total_unique_method_idx_ << "\n";
os << "Unique(per class) string ids accessed from code: " << total_unique_string_ids_ << "\n";
- size_t same_class_total = same_class_direct_ + same_class_virtual_ + same_class_static_;
- size_t other_class_total = other_class_direct_ + other_class_virtual_ + other_class_static_;
- os << "Same class invoke: " << same_class_total << "\n";
- os << "Other class invoke: " << other_class_total << "\n";
+ const size_t same_class_total =
+ same_class_direct_ +
+ same_class_virtual_ +
+ same_class_static_ +
+ same_class_interface_ +
+ same_class_super_;
+ const size_t other_class_total =
+ total_direct_ +
+ total_virtual_ +
+ total_static_ +
+ total_interface_ +
+ total_super_;
+ os << "Same class invokes: " << PercentDivide(same_class_total, other_class_total) << "\n";
os << "Invokes from code: " << (same_class_total + other_class_total) << "\n";
- os << "Total dex size: " << total_size << "\n";
+ os << "Total Dex code bytes: " << Percent(dex_code_bytes_, total_size) << "\n";
+ os << "Total unique code items: " << total_unique_code_items_ << "\n";
+ os << "Total Dex size: " << total_size << "\n";
}
-} // namespace art
+void CodeMetrics::ProcessDexFile(const DexFile& dex_file) {
+ for (ClassAccessor accessor : dex_file.GetClasses()) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ bool space_for_out_arg = false;
+ for (const DexInstructionPcPair& inst : method.GetInstructions()) {
+ switch (inst->Opcode()) {
+ case Instruction::INVOKE_VIRTUAL:
+ case Instruction::INVOKE_DIRECT:
+ case Instruction::INVOKE_SUPER:
+ case Instruction::INVOKE_INTERFACE:
+ case Instruction::INVOKE_STATIC: {
+ const uint32_t args = NumberOfArgs(inst.Inst());
+ CHECK_LT(args, kMaxArgCount);
+ ++arg_counts_[args];
+ space_for_out_arg = args < kMaxArgCount - 1;
+ break;
+ }
+ case Instruction::MOVE_RESULT:
+ case Instruction::MOVE_RESULT_OBJECT: {
+ if (space_for_out_arg) {
+ move_result_savings_ += inst->SizeInCodeUnits() * 2;
+ }
+ break;
+ }
+ default:
+ space_for_out_arg = false;
+ break;
+ }
+ }
+ }
+ }
+}
+void CodeMetrics::Dump(std::ostream& os, uint64_t total_size) const {
+ const uint64_t total = std::accumulate(arg_counts_, arg_counts_ + kMaxArgCount, 0u);
+ for (size_t i = 0; i < kMaxArgCount; ++i) {
+ os << "args=" << i << ": " << Percent(arg_counts_[i], total) << "\n";
+ }
+ os << "Move result savings: " << Percent(move_result_savings_, total_size) << "\n";
+ os << "One byte invoke savings: " << Percent(total, total_size) << "\n";
+ const uint64_t low_arg_total = std::accumulate(arg_counts_, arg_counts_ + 3, 0u);
+ os << "Low arg savings: " << Percent(low_arg_total * 2, total_size) << "\n";
+}
+
+} // namespace art
diff --git a/tools/dexanalyze/dexanalyze_experiments.h b/tools/dexanalyze/dexanalyze_experiments.h
index 0fb4d32005..2be53d6216 100644
--- a/tools/dexanalyze/dexanalyze_experiments.h
+++ b/tools/dexanalyze/dexanalyze_experiments.h
@@ -18,7 +18,9 @@
#define ART_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_
#include <iosfwd>
+#include <memory>
#include <set>
+#include <vector>
namespace art {
@@ -30,7 +32,8 @@ std::string Percent(uint64_t value, uint64_t max);
class Experiment {
public:
virtual ~Experiment() {}
- virtual void ProcessDexFile(const DexFile& dex_file) = 0;
+ virtual void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
+ virtual void ProcessDexFile(const DexFile&) {}
virtual void Dump(std::ostream& os, uint64_t total_size) const = 0;
};
@@ -51,6 +54,32 @@ class AnalyzeStrings : public Experiment {
int64_t total_num_prefixes_ = 0u;
};
+// Analyze debug info sizes.
+class AnalyzeDebugInfo : public Experiment {
+ public:
+ void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
+ void Dump(std::ostream& os, uint64_t total_size) const;
+
+ private:
+ int64_t total_bytes_ = 0u;
+ int64_t total_entropy_ = 0u;
+ int64_t total_opcode_bytes_ = 0u;
+ int64_t total_opcode_entropy_ = 0u;
+ int64_t total_non_header_bytes_ = 0u;
+ int64_t total_unique_non_header_bytes_ = 0u;
+ // Opcode and related data.
+ int64_t total_end_seq_bytes_ = 0u;
+ int64_t total_advance_pc_bytes_ = 0u;
+ int64_t total_advance_line_bytes_ = 0u;
+ int64_t total_start_local_bytes_ = 0u;
+ int64_t total_start_local_extended_bytes_ = 0u;
+ int64_t total_end_local_bytes_ = 0u;
+ int64_t total_restart_local_bytes_ = 0u;
+ int64_t total_epilogue_bytes_ = 0u;
+ int64_t total_set_file_bytes_ = 0u;
+ int64_t total_other_bytes_ = 0u;
+};
+
// Count numbers of dex indices.
class CountDexIndices : public Experiment {
public:
@@ -63,6 +92,7 @@ class CountDexIndices : public Experiment {
size_t num_string_ids_from_code_ = 0;
size_t total_unique_method_idx_ = 0;
size_t total_unique_string_ids_ = 0;
+ uint64_t total_unique_code_items_ = 0u;
// Other dex ids.
size_t dex_code_bytes_ = 0;
@@ -74,11 +104,28 @@ class CountDexIndices : public Experiment {
// Invokes
size_t same_class_direct_ = 0;
- size_t other_class_direct_ = 0;
+ size_t total_direct_ = 0;
size_t same_class_virtual_ = 0;
- size_t other_class_virtual_ = 0;
+ size_t total_virtual_ = 0;
size_t same_class_static_ = 0;
- size_t other_class_static_ = 0;
+ size_t total_static_ = 0;
+ size_t same_class_interface_ = 0;
+ size_t total_interface_ = 0;
+ size_t same_class_super_ = 0;
+ size_t total_super_ = 0;
+};
+
+// Measure various code metrics including args per invoke-virtual, fill/spill move patterns.
+class CodeMetrics : public Experiment {
+ public:
+ void ProcessDexFile(const DexFile& dex_file);
+
+ void Dump(std::ostream& os, uint64_t total_size) const;
+
+ private:
+ static constexpr size_t kMaxArgCount = 6;
+ uint64_t arg_counts_[kMaxArgCount] = {};
+ uint64_t move_result_savings_ = 0u;
};
} // namespace art
diff --git a/tools/golem/build-target.sh b/tools/golem/build-target.sh
index 4ca2722ac9..921a8cbe36 100755
--- a/tools/golem/build-target.sh
+++ b/tools/golem/build-target.sh
@@ -267,8 +267,6 @@ if [[ $mode == "golem" ]]; then
execute 'source' build/envsetup.sh
# Build generic targets (as opposed to something specific like aosp_angler-eng).
execute lunch "$lunch_target"
- setenv JACK_SERVER false
- setenv_escape JACK_REPOSITORY "$PWD/prebuilts/sdk/tools/jacks" '$PWD/prebuilts/sdk/tools/jacks'
# Golem uses master-art repository which is missing a lot of other libraries.
setenv SOONG_ALLOW_MISSING_DEPENDENCIES true
# Golem may be missing tools such as javac from its path.
diff --git a/tools/jfuzz/README.md b/tools/jfuzz/README.md
index eb0e71f53d..f32cf561d6 100644
--- a/tools/jfuzz/README.md
+++ b/tools/jfuzz/README.md
@@ -37,8 +37,10 @@ The current version of JFuzz sends all output to stdout, and uses
a fixed testing class named Test. So a typical test run looks as follows.
jfuzz > Test.java
- jack -cp ${JACK_CLASSPATH} --output-dex . Test.java
- art -classpath classes.dex Test
+ mkdir classes
+ javac -d classes Test.java
+ dx --dex --output=classes.dex classes
+ art -cp classes.dex Test
How to start JFuzz testing
==========================
@@ -67,7 +69,7 @@ where
--report_script : path to script called for each divergence
--jfuzz_arg : argument for jfuzz
--true_divergence : don't bisect timeout divergences
- --dexer=DEXER : use either dx, d8, or jack to obtain dex files
+ --dexer=DEXER : use either dx or d8 to obtain dex files
--debug_info : include debugging info
How to start JFuzz nightly testing
@@ -97,7 +99,7 @@ where
--num_tests : number of tests to run (10000 by default)
--num_inputs : number of JFuzz programs to generate
--device : target device serial number (passed to adb -s)
- --dexer=DEXER : use either dx, d8, or jack to obtain dex files
+ --dexer=DEXER : use either dx or d8 to obtain dex files
--debug_info : include debugging info
Background
diff --git a/tools/jfuzz/run_dex_fuzz_test.py b/tools/jfuzz/run_dex_fuzz_test.py
index 47fe072b6d..64bf23405b 100755
--- a/tools/jfuzz/run_dex_fuzz_test.py
+++ b/tools/jfuzz/run_dex_fuzz_test.py
@@ -28,7 +28,6 @@ sys.path.append(os.path.dirname(os.path.dirname(
from common.common import FatalError
from common.common import GetEnvVariableOrError
-from common.common import GetJackClassPath
from common.common import RetCode
from common.common import RunCommand
@@ -106,7 +105,7 @@ class DexFuzzTester(object):
self.RunDexFuzz()
def CompileOnHost(self):
- """Compiles Test.java into classes.dex using either javac/dx,d8 or jack.
+ """Compiles Test.java into classes.dex using either javac/dx or d8.
Raises:
FatalError: error when compilation fails
@@ -128,15 +127,6 @@ class DexFuzzTester(object):
os.unlink(cfile)
os.unlink('jerr.txt')
os.unlink('dxerr.txt')
-
- elif self._dexer == 'jack':
- jack_args = ['-cp', GetJackClassPath(), '--output-dex', '.', 'Test.java']
- if RunCommand(['jack'] + jack_args, out=None, err='jackerr.txt',
- timeout=30) != RetCode.SUCCESS:
- print('Unexpected error while running Jack')
- raise FatalError('Unexpected error while running Jack')
- # Cleanup on success (nothing to see).
- os.unlink('jackerr.txt')
else:
raise FatalError('Unknown dexer: ' + self._dexer)
@@ -188,7 +178,7 @@ def main():
help='number of JFuzz program to generate (default: 10)')
parser.add_argument('--device', help='target device serial number')
parser.add_argument('--dexer', default='dx', type=str,
- help='defines dexer as dx, d8, or jack (default: dx)')
+ help='defines dexer as dx or d8 (default: dx)')
parser.add_argument('--debug_info', default=False, action='store_true',
help='include debugging info')
args = parser.parse_args()
diff --git a/tools/jfuzz/run_jfuzz_test.py b/tools/jfuzz/run_jfuzz_test.py
index 3ff9f450a1..f8bfd8dda7 100755
--- a/tools/jfuzz/run_jfuzz_test.py
+++ b/tools/jfuzz/run_jfuzz_test.py
@@ -33,7 +33,6 @@ sys.path.append(os.path.dirname(os.path.dirname(
from common.common import RetCode
from common.common import CommandListToCommandString
from common.common import FatalError
-from common.common import GetJackClassPath
from common.common import GetEnvVariableOrError
from common.common import RunCommand
from common.common import RunCommandForOutput
@@ -127,8 +126,6 @@ class TestRunnerWithHostCompilation(TestRunner):
"""
self._dexer = dexer
self._debug_info = debug_info
- self._jack_args = ['-cp', GetJackClassPath(), '--output-dex', '.',
- 'Test.java']
def CompileOnHost(self):
if self._dexer == 'dx' or self._dexer == 'd8':
@@ -140,9 +137,6 @@ class TestRunnerWithHostCompilation(TestRunner):
out=None, err='dxerr.txt', timeout=30)
else:
retc = RetCode.NOTCOMPILED
- elif self._dexer == 'jack':
- retc = RunCommand(['jack'] + self._jack_args,
- out=None, err='jackerr.txt', timeout=30)
else:
raise FatalError('Unknown dexer: ' + self._dexer)
return retc
@@ -632,7 +626,7 @@ def main():
parser.add_argument('--true_divergence', default=False, action='store_true',
help='do not bisect timeout divergences')
parser.add_argument('--dexer', default='dx', type=str,
- help='defines dexer as dx, d8, or jack (default: dx)')
+ help='defines dexer as dx or d8 (default: dx)')
parser.add_argument('--debug_info', default=False, action='store_true',
help='include debugging info')
args = parser.parse_args()
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index eebc09278a..0796432f68 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -36,10 +36,9 @@ if [ -z "$ANDROID_HOST_OUT" ] ; then
ANDROID_HOST_OUT=${OUT_DIR-$ANDROID_BUILD_TOP/out}/host/linux-x86
fi
-android_root="/system"
-if [ -n "$ART_TEST_ANDROID_ROOT" ]; then
- android_root="$ART_TEST_ANDROID_ROOT"
-fi
+# "Root" (actually "system") directory on device (in the case of
+# target testing).
+android_root=${ART_TEST_ANDROID_ROOT:-/system}
java_lib_location="${ANDROID_HOST_OUT}/../common/obj/JAVA_LIBRARIES"
make_target_name="apache-harmony-jdwp-tests-hostdex"
@@ -48,6 +47,7 @@ vm_args=""
art="$android_root/bin/art"
art_debugee="sh $android_root/bin/art"
args=$@
+chroot_option=
debuggee_args="-Xcompiler-option --debuggable"
device_dir="--device-dir=/data/local/tmp"
# We use the art script on target to ensure the runner and the debuggee share the same
@@ -68,8 +68,6 @@ test="org.apache.harmony.jpda.tests.share.AllTests"
mode="target"
# Use JIT compiling by default.
use_jit=true
-# Don't use chroot by default.
-use_chroot=false
variant_cmdline_parameter="--variant=X32"
dump_command="/bin/true"
# Timeout of JDWP test in ms.
@@ -112,15 +110,6 @@ while true; do
# We don't care about jit with the RI
use_jit=false
shift
- elif [[ "$1" == "--chroot" ]]; then
- use_chroot=true
- # Adjust settings for chroot environment.
- art="/system/bin/art"
- art_debugee="sh /system/bin/art"
- vm_command="--vm-command=$art"
- device_dir="--device-dir=/tmp"
- # Shift the "--chroot" flag and its argument.
- shift 2
elif [[ $1 == --test-timeout-ms ]]; then
# Remove the --test-timeout-ms from the arguments.
args=${args/$1}
@@ -202,10 +191,17 @@ while true; do
fi
done
-if $use_chroot && [[ $mode == "host" ]]; then
- # Chroot-based testing is not supported on host.
- echo "Cannot use --chroot with --mode=host"
- exit 1
+if [[ $mode == "target" ]]; then
+ # Honor environment variable ART_TEST_CHROOT.
+ if [[ -n "$ART_TEST_CHROOT" ]]; then
+ # Set Vogar's `--chroot` option.
+ chroot_option="--chroot $ART_TEST_CHROOT"
+ # Adjust settings for chroot environment.
+ art="/system/bin/art"
+ art_debugee="sh /system/bin/art"
+ vm_command="--vm-command=$art"
+ device_dir="--device-dir=/tmp"
+ fi
fi
if [[ $has_gdb = "yes" ]]; then
@@ -341,6 +337,7 @@ vogar $vm_command \
$vm_args \
--verbose \
$args \
+ $chroot_option \
$device_dir \
$image_compiler_option \
--timeout 800 \
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 3537c1b861..aff009abb6 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -28,10 +28,9 @@ else
JAVA_LIBRARIES=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES
fi
-android_root="/system"
-if [ -n "$ART_TEST_ANDROID_ROOT" ]; then
- android_root="$ART_TEST_ANDROID_ROOT"
-fi
+# "Root" (actually "system") directory on device (in the case of
+# target testing).
+android_root=${ART_TEST_ANDROID_ROOT:-/system}
function classes_jar_path {
local var="$1"
@@ -106,8 +105,6 @@ debug=false
# Don't use device mode by default.
device_mode=false
-# Don't use chroot by default.
-use_chroot=false
while true; do
if [[ "$1" == "--mode=device" ]]; then
@@ -135,10 +132,6 @@ while true; do
elif [[ "$1" == "-Xgc:gcstress" ]]; then
gcstress=true
shift
- elif [[ "$1" == "--chroot" ]]; then
- use_chroot=true
- # Shift the "--chroot" flag and its argument.
- shift 2
elif [[ "$1" == "" ]]; then
break
else
@@ -147,20 +140,17 @@ while true; do
done
if $device_mode; then
- if $use_chroot; then
+ # Honor environment variable ART_TEST_CHROOT.
+ if [[ -n "$ART_TEST_CHROOT" ]]; then
+ # Set Vogar's `--chroot` option.
+ vogar_args="$vogar_args --chroot $ART_TEST_CHROOT"
vogar_args="$vogar_args --device-dir=/tmp"
- vogar_args="$vogar_args --vm-command=/system/bin/art"
else
+ # When not using a chroot on device, set Vogar's work directory to
+ # /data/local/tmp.
vogar_args="$vogar_args --device-dir=/data/local/tmp"
- vogar_args="$vogar_args --vm-command=$android_root/bin/art"
- fi
-else
- # Host mode.
- if $use_chroot; then
- # Chroot-based testing is not supported on host.
- echo "Cannot use --chroot with --mode=host"
- exit 1
fi
+ vogar_args="$vogar_args --vm-command=$android_root/bin/art"
fi
# Increase the timeout, as vogar cannot set individual test
diff --git a/tools/teardown-buildbot-device.sh b/tools/teardown-buildbot-device.sh
index df239a28bc..bf14ca4f9f 100755
--- a/tools/teardown-buildbot-device.sh
+++ b/tools/teardown-buildbot-device.sh
@@ -25,6 +25,27 @@ adb root
adb wait-for-device
if [[ -n "$ART_TEST_CHROOT" ]]; then
+
+ # remove_filesystem_from_chroot DIR-IN-CHROOT FSTYPE REMOVE-DIR-IN-CHROOT
+ # -----------------------------------------------------------------------
+ # Unmount filesystem with type FSTYPE mounted in directory DIR-IN-CHROOT
+ # under the chroot directory.
+ # Remove DIR-IN-CHROOT under the chroot if REMOVE-DIR-IN-CHROOT is
+ # true.
+ remove_filesystem_from_chroot() {
+ local dir_in_chroot=$1
+ local fstype=$2
+ local remove_dir=$3
+ local dir="$ART_TEST_CHROOT/$dir_in_chroot"
+ adb shell test -d "$dir" \
+ && adb shell mount | grep -q "^$fstype on $dir type $fstype " \
+ && if adb shell umount "$dir"; then
+ $remove_dir && adb shell rmdir "$dir"
+ else
+ adb shell lsof "$dir"
+ fi
+ }
+
# Tear down the chroot dir.
echo -e "${green}Tear down the chroot dir in $ART_TEST_CHROOT${nc}"
@@ -32,22 +53,17 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then
[[ "x$ART_TEST_CHROOT" = x/* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
# Remove /dev from chroot.
- adb shell mount | grep -q "^tmpfs on $ART_TEST_CHROOT/dev type tmpfs " \
- && adb shell umount "$ART_TEST_CHROOT/dev" \
- && adb shell rmdir "$ART_TEST_CHROOT/dev"
+ remove_filesystem_from_chroot dev tmpfs true
# Remove /sys/kernel/debug from chroot.
- adb shell mount | grep -q "^debugfs on $ART_TEST_CHROOT/sys/kernel/debug type debugfs " \
- && adb shell umount "$ART_TEST_CHROOT/sys/kernel/debug"
+ # The /sys/kernel/debug directory under the chroot dir cannot be
+ # deleted, as it is part of the host device's /sys filesystem.
+ remove_filesystem_from_chroot sys/kernel/debug debugfs false
# Remove /sys from chroot.
- adb shell mount | grep -q "^sysfs on $ART_TEST_CHROOT/sys type sysfs " \
- && adb shell umount "$ART_TEST_CHROOT/sys" \
- && adb shell rmdir "$ART_TEST_CHROOT/sys"
+ remove_filesystem_from_chroot sys sysfs true
# Remove /proc from chroot.
- adb shell mount | grep -q "^proc on $ART_TEST_CHROOT/proc type proc " \
- && adb shell umount "$ART_TEST_CHROOT/proc" \
- && adb shell rmdir "$ART_TEST_CHROOT/proc"
+ remove_filesystem_from_chroot proc proc true
# Remove /etc from chroot.
adb shell rm -f "$ART_TEST_CHROOT/etc"
@@ -65,6 +81,6 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then
/plat_property_contexts \
/nonplat_property_contexts"
for f in $property_context_files; do
- adb shell test -f "$f" "&&" rm -f "$ART_TEST_CHROOT$f"
+ adb shell rm -f "$ART_TEST_CHROOT$f"
done
fi
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
index 5186c43ca2..96d4a094b5 100644
--- a/tools/veridex/Android.bp
+++ b/tools/veridex/Android.bp
@@ -24,11 +24,16 @@ cc_binary {
"veridex.cc",
],
cflags: ["-Wall", "-Werror"],
- shared_libs: [
+ static_libs: [
"libdexfile",
"libartbase",
"libbase",
+ "liblog",
+ "libutils",
+ "libz",
+ "libziparchive",
],
+ stl: "libc++_static",
header_libs: [
"art_libartbase_headers",
],
diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk
index 51d924a3c1..f8463c1c33 100644
--- a/tools/veridex/Android.mk
+++ b/tools/veridex/Android.mk
@@ -16,6 +16,9 @@
LOCAL_PATH := $(call my-dir)
+# The veridex tool takes stub dex files as input, so we generate both the system and oahl
+# dex stubs.
+
system_stub_dex := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/core_dex_intermediates/classes.dex
$(system_stub_dex): PRIVATE_MIN_SDK_VERSION := 1000
$(system_stub_dex): $(call resolve-prebuilt-sdk-jar-path,system_current) | $(ZIP2ZIP) $(DX)
@@ -27,9 +30,38 @@ $(oahl_stub_dex): PRIVATE_MIN_SDK_VERSION := 1000
$(oahl_stub_dex): $(call get-prebuilt-sdk-dir,current)/org.apache.http.legacy.jar | $(ZIP2ZIP) $(DX)
$(transform-classes-d8.jar-to-dex)
+app_compat_lists := \
+ $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+
+# Phony rule to create all dependencies of the appcompat.sh script.
.PHONY: appcompat
+appcompat: $(system_stub_dex) $(oahl_stub_dex) $(HOST_OUT_EXECUTABLES)/veridex $(app_compat_lists)
+
+VERIDEX_FILES_PATH := \
+ $(call intermediates-dir-for,PACKAGING,veridex,HOST)/veridex.zip
+
+VERIDEX_FILES := $(LOCAL_PATH)/appcompat.sh
+
+$(VERIDEX_FILES_PATH): PRIVATE_VERIDEX_FILES := $(VERIDEX_FILES)
+$(VERIDEX_FILES_PATH): PRIVATE_APP_COMPAT_LISTS := $(app_compat_lists)
+$(VERIDEX_FILES_PATH): PRIVATE_SYSTEM_STUBS_ZIP := $(dir $(VERIDEX_FILES_PATH))/system-stubs.zip
+$(VERIDEX_FILES_PATH): PRIVATE_OAHL_STUBS_ZIP := $(dir $(VERIDEX_FILES_PATH))/org.apache.http.legacy-stubs.zip
+$(VERIDEX_FILES_PATH) : $(SOONG_ZIP) $(VERIDEX_FILES) $(app_compat_lists) $(HOST_OUT_EXECUTABLES)/veridex $(system_stub_dex) $(oahl_stub_dex)
+ $(hide) rm -f $(PRIVATE_SYSTEM_STUBS_ZIP) $(PRIVATE_OAHL_STUBS_ZIP)
+ $(hide) zip -j $(PRIVATE_SYSTEM_STUBS_ZIP) $(dir $(system_stub_dex))/classes*.dex
+ $(hide) zip -j $(PRIVATE_OAHL_STUBS_ZIP) $(dir $(oahl_stub_dex))/classes*.dex
+ $(hide) $(SOONG_ZIP) -o $@ -C art/tools/veridex -f $(PRIVATE_VERIDEX_FILES) \
+ -C $(dir $(lastword $(PRIVATE_APP_COMPAT_LISTS))) $(addprefix -f , $(PRIVATE_APP_COMPAT_LISTS)) \
+ -C $(HOST_OUT_EXECUTABLES) -f $(HOST_OUT_EXECUTABLES)/veridex \
+ -C $(dir $(PRIVATE_SYSTEM_STUBS_ZIP)) -f $(PRIVATE_SYSTEM_STUBS_ZIP) \
+ -C $(dir $(PRIVATE_OAHL_STUBS_ZIP)) -f $(PRIVATE_OAHL_STUBS_ZIP)
+ $(hide) rm -f $(PRIVATE_SYSTEM_STUBS_ZIP)
+ $(hide) rm -f $(PRIVATE_OAHL_STUBS_ZIP)
+
+# Make the zip file available for prebuilts.
+$(call dist-for-goals,sdk,$(VERIDEX_FILES_PATH))
-appcompat: $(system_stub_dex) $(oahl_stub_dex) $(HOST_OUT_EXECUTABLES)/veridex \
- ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-light-greylist.txt \
- ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-dark-greylist.txt \
- ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-blacklist.txt
+VERIDEX_FILES :=
+app_compat_lists :=
diff --git a/tools/veridex/appcompat.sh b/tools/veridex/appcompat.sh
index 31a8654b58..e7b735d30b 100755
--- a/tools/veridex/appcompat.sh
+++ b/tools/veridex/appcompat.sh
@@ -14,7 +14,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# We want to be at the root for simplifying the "out" detection
+echo "NOTE: appcompat.sh is still under development. It can report"
+echo "API uses that do not execute at runtime, and reflection uses"
+echo "that do not exist. It can also miss on reflection uses."
+
+# First check if the script is invoked from a prebuilts location.
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+if [[ -e ${SCRIPT_DIR}/veridex && \
+ -e ${SCRIPT_DIR}/hiddenapi-blacklist.txt && \
+ -e ${SCRIPT_DIR}/hiddenapi-light-greylist.txt && \
+ -e ${SCRIPT_DIR}/hiddenapi-dark-greylist.txt && \
+ -e ${SCRIPT_DIR}/org.apache.http.legacy-stubs.zip && \
+ -e ${SCRIPT_DIR}/system-stubs.zip ]]; then
+ exec ${SCRIPT_DIR}/veridex \
+ --core-stubs=${SCRIPT_DIR}/system-stubs.zip:${SCRIPT_DIR}/org.apache.http.legacy-stubs.zip \
+ --blacklist=${SCRIPT_DIR}/hiddenapi-blacklist.txt \
+ --light-greylist=${SCRIPT_DIR}/hiddenapi-light-greylist.txt \
+ --dark-greylist=${SCRIPT_DIR}/hiddenapi-dark-greylist.txt \
+ $@
+fi
+
+# Otherwise, we want to be at the root for simplifying the "out" detection
# logic.
if [ ! -d art ]; then
echo "Script needs to be run at the root of the android tree."
@@ -38,10 +59,6 @@ if [ -z "$ANDROID_HOST_OUT" ] ; then
ANDROID_HOST_OUT=${OUT}/host/linux-x86
fi
-echo "NOTE: appcompat.sh is still under development. It can report"
-echo "API uses that do not execute at runtime, and reflection uses"
-echo "that do not exist. It can also miss on reflection uses."
-
${ANDROID_HOST_OUT}/bin/veridex \
--core-stubs=${PACKAGING}/core_dex_intermediates/classes.dex:${PACKAGING}/oahl_dex_intermediates/classes.dex \