summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk6
-rw-r--r--build/art.go35
-rw-r--r--build/codegen.go18
-rw-r--r--compiler/compiled_method.h2
-rw-r--r--compiler/compiler.h4
-rw-r--r--compiler/debug/dwarf/headers.h2
-rw-r--r--compiler/debug/elf_debug_writer.cc2
-rw-r--r--compiler/debug/elf_debug_writer.h2
-rw-r--r--compiler/driver/compiled_method_storage.h2
-rw-r--r--compiler/driver/compiler_driver.cc4
-rw-r--r--compiler/driver/compiler_driver.h2
-rw-r--r--compiler/elf_builder.h2
-rw-r--r--compiler/elf_writer.h2
-rw-r--r--compiler/image_writer.cc2
-rw-r--r--compiler/jni/quick/calling_convention.h2
-rw-r--r--compiler/linker/arm64/relative_patcher_arm64.h2
-rw-r--r--compiler/linker/relative_patcher.h2
-rw-r--r--compiler/linker/relative_patcher_test.h2
-rw-r--r--compiler/oat_writer.cc4
-rw-r--r--compiler/oat_writer.h2
-rw-r--r--compiler/optimizing/dead_code_elimination.cc2
-rw-r--r--compiler/optimizing/nodes.cc107
-rw-r--r--compiler/optimizing/nodes.h11
-rw-r--r--compiler/optimizing/register_allocation_resolver.h2
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.cc110
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.h6
-rw-r--r--compiler/utils/arm/assembler_thumb2.h2
-rw-r--r--compiler/utils/arm/jni_macro_assembler_arm_vixl.cc18
-rw-r--r--compiler/utils/assembler.h2
-rw-r--r--compiler/utils/dedupe_set_test.cc2
-rw-r--r--compiler/utils/jni_macro_assembler.h2
-rw-r--r--compiler/utils/x86/assembler_x86.h2
-rw-r--r--compiler/utils/x86/jni_macro_assembler_x86.h2
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h2
-rw-r--r--compiler/utils/x86_64/jni_macro_assembler_x86_64.h2
-rw-r--r--dex2oat/dex2oat.cc2
-rw-r--r--dexlist/dexlist_test.cc6
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S14
-rw-r--r--runtime/arch/arm64/quick_entrypoints_arm64.S21
-rw-r--r--runtime/art_method-inl.h3
-rw-r--r--runtime/art_method.cc7
-rw-r--r--runtime/art_method.h1
-rw-r--r--runtime/base/array_ref.h (renamed from compiler/utils/array_ref.h)6
-rw-r--r--runtime/base/transform_array_ref.h (renamed from compiler/utils/transform_array_ref.h)10
-rw-r--r--runtime/base/transform_array_ref_test.cc (renamed from compiler/utils/transform_array_ref_test.cc)2
-rw-r--r--runtime/base/transform_iterator.h (renamed from compiler/utils/transform_iterator.h)6
-rw-r--r--runtime/base/transform_iterator_test.cc (renamed from compiler/utils/transform_iterator_test.cc)2
-rw-r--r--runtime/class_linker.cc36
-rw-r--r--runtime/class_linker.h3
-rw-r--r--runtime/debugger.cc11
-rw-r--r--runtime/dex_file.cc1271
-rw-r--r--runtime/dex_file.h171
-rw-r--r--runtime/dex_file_annotations.cc1303
-rw-r--r--runtime/dex_file_annotations.h125
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h2
-rw-r--r--runtime/gc/heap.cc2
-rw-r--r--runtime/instrumentation.cc2
-rw-r--r--runtime/interpreter/interpreter_common.h5
-rw-r--r--runtime/interpreter/unstarted_runtime.cc2
-rw-r--r--runtime/jit/jit.cc7
-rw-r--r--runtime/jit/jit.h4
-rw-r--r--runtime/mirror/class.cc5
-rw-r--r--runtime/native/java_lang_Class.cc26
-rw-r--r--runtime/native/java_lang_reflect_AbstractMethod.cc14
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc3
-rw-r--r--runtime/native/java_lang_reflect_Field.cc10
-rw-r--r--runtime/native/java_lang_reflect_Method.cc5
-rw-r--r--runtime/native/java_lang_reflect_Parameter.cc3
-rw-r--r--runtime/quick/inline_method_analyser.h1
-rw-r--r--runtime/quick_exception_handler.cc4
-rw-r--r--runtime/reflection.cc18
-rw-r--r--runtime/reflection.h6
-rw-r--r--runtime/thread.cc5
-rw-r--r--runtime/thread.h24
75 files changed, 1792 insertions, 1728 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 76ee06e453..49887400f8 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -214,6 +214,8 @@ RUNTIME_GTEST_COMMON_SRC_FILES := \
runtime/base/stringprintf_test.cc \
runtime/base/time_utils_test.cc \
runtime/base/timing_logger_test.cc \
+ runtime/base/transform_array_ref_test.cc \
+ runtime/base/transform_iterator_test.cc \
runtime/base/variant_map_test.cc \
runtime/base/unix_file/fd_file_test.cc \
runtime/class_linker_test.cc \
@@ -308,9 +310,7 @@ COMPILER_GTEST_COMMON_SRC_FILES := \
compiler/utils/intrusive_forward_list_test.cc \
compiler/utils/string_reference_test.cc \
compiler/utils/swap_space_test.cc \
- compiler/utils/test_dex_file_builder_test.cc \
- compiler/utils/transform_array_ref_test.cc \
- compiler/utils/transform_iterator_test.cc \
+ compiler/utils/test_dex_file_builder_test.cc
COMPILER_GTEST_COMMON_SRC_FILES_all := \
compiler/jni/jni_cfi_test.cc \
diff --git a/build/art.go b/build/art.go
index f694505fb4..ffa9273135 100644
--- a/build/art.go
+++ b/build/art.go
@@ -122,7 +122,7 @@ func hostFlags(ctx android.BaseContext) []string {
return cflags
}
-func (a *artGlobalDefaults) CustomizeProperties(ctx android.CustomizePropertiesContext) {
+func globalDefaults(ctx android.LoadHookContext) {
type props struct {
Target struct {
Android struct {
@@ -143,9 +143,7 @@ func (a *artGlobalDefaults) CustomizeProperties(ctx android.CustomizePropertiesC
ctx.AppendProperties(p)
}
-type artGlobalDefaults struct{}
-
-func (a *artCustomLinkerCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
+func customLinker(ctx android.LoadHookContext) {
linker := envDefault(ctx, "CUSTOM_TARGET_LINKER", "")
if linker != "" {
type props struct {
@@ -158,9 +156,7 @@ func (a *artCustomLinkerCustomizer) CustomizeProperties(ctx android.CustomizePro
}
}
-type artCustomLinkerCustomizer struct{}
-
-func (a *artPrefer32BitCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
+func prefer32Bit(ctx android.LoadHookContext) {
if envTrue(ctx, "HOST_PREFER_32_BIT") {
type props struct {
Target struct {
@@ -176,8 +172,6 @@ func (a *artPrefer32BitCustomizer) CustomizeProperties(ctx android.CustomizeProp
}
}
-type artPrefer32BitCustomizer struct{}
-
func init() {
soong.RegisterModuleType("art_cc_library", artLibrary)
soong.RegisterModuleType("art_cc_binary", artBinary)
@@ -187,17 +181,16 @@ func init() {
}
func artGlobalDefaultsFactory() (blueprint.Module, []interface{}) {
- c := &artGlobalDefaults{}
module, props := artDefaultsFactory()
- android.AddCustomizer(module.(android.Module), c)
+ android.AddLoadHook(module, globalDefaults)
return module, props
}
func artDefaultsFactory() (blueprint.Module, []interface{}) {
- c := &codegenCustomizer{}
- module, props := cc.DefaultsFactory(&c.codegenProperties)
- android.AddCustomizer(module.(android.Module), c)
+ c := &codegenProperties{}
+ module, props := cc.DefaultsFactory(c)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c) })
return module, props
}
@@ -206,9 +199,9 @@ func artLibrary() (blueprint.Module, []interface{}) {
library, _ := cc.NewLibrary(android.HostAndDeviceSupported, true, true)
module, props := library.Init()
- c := &codegenCustomizer{}
- android.AddCustomizer(library, c)
- props = append(props, &c.codegenProperties)
+ c := &codegenProperties{}
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c) })
+ props = append(props, c)
return module, props
}
@@ -217,8 +210,8 @@ func artBinary() (blueprint.Module, []interface{}) {
binary, _ := cc.NewBinary(android.HostAndDeviceSupported)
module, props := binary.Init()
- android.AddCustomizer(binary, &artCustomLinkerCustomizer{})
- android.AddCustomizer(binary, &artPrefer32BitCustomizer{})
+ android.AddLoadHook(module, customLinker)
+ android.AddLoadHook(module, prefer32Bit)
return module, props
}
@@ -226,8 +219,8 @@ func artTest() (blueprint.Module, []interface{}) {
test := cc.NewTest(android.HostAndDeviceSupported)
module, props := test.Init()
- android.AddCustomizer(test, &artCustomLinkerCustomizer{})
- android.AddCustomizer(test, &artPrefer32BitCustomizer{})
+ android.AddLoadHook(module, customLinker)
+ android.AddLoadHook(module, prefer32Bit)
return module, props
}
diff --git a/build/codegen.go b/build/codegen.go
index fde9420039..d98ca4fd4f 100644
--- a/build/codegen.go
+++ b/build/codegen.go
@@ -24,9 +24,7 @@ import (
"strings"
)
-func (a *codegenCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
- c := &a.codegenProperties.Codegen
-
+func codegen(ctx android.LoadHookContext, c *codegenProperties) {
var hostArches, deviceArches []string
e := envDefault(ctx, "ART_HOST_CODEGEN_ARCHS", "")
@@ -53,17 +51,17 @@ func (a *codegenCustomizer) CustomizeProperties(ctx android.CustomizePropertiesC
addCodegenArchProperties := func(p *props, hod **codegenArchProperties, arch string) {
switch arch {
case "arm":
- *hod = &c.Arm
+ *hod = &c.Codegen.Arm
case "arm64":
- *hod = &c.Arm64
+ *hod = &c.Codegen.Arm64
case "mips":
- *hod = &c.Mips
+ *hod = &c.Codegen.Mips
case "mips64":
- *hod = &c.Mips64
+ *hod = &c.Codegen.Mips64
case "x86":
- *hod = &c.X86
+ *hod = &c.Codegen.X86
case "x86_64":
- *hod = &c.X86_64
+ *hod = &c.Codegen.X86_64
default:
ctx.ModuleErrorf("Unknown codegen architecture %q", arch)
return
@@ -109,7 +107,7 @@ type codegenCustomizer struct {
codegenProperties codegenProperties
}
-func defaultDeviceCodegenArches(ctx android.CustomizePropertiesContext) []string {
+func defaultDeviceCodegenArches(ctx android.LoadHookContext) []string {
arches := make(map[string]bool)
for _, a := range ctx.DeviceConfig().Arches() {
s := a.ArchType.String()
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 2a81804f64..1a87448e80 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -23,10 +23,10 @@
#include <vector>
#include "arch/instruction_set.h"
+#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/length_prefixed_array.h"
#include "method_reference.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/compiler.h b/compiler/compiler.h
index ed42958a76..9a69456b5a 100644
--- a/compiler/compiler.h
+++ b/compiler/compiler.h
@@ -25,10 +25,14 @@ namespace art {
namespace jit {
class JitCodeCache;
}
+namespace mirror {
+ class DexCache;
+}
class ArtMethod;
class CompilerDriver;
class CompiledMethod;
+template<class T> class Handle;
class OatWriter;
class Compiler {
diff --git a/compiler/debug/dwarf/headers.h b/compiler/debug/dwarf/headers.h
index 146d9fddf5..28f108423e 100644
--- a/compiler/debug/dwarf/headers.h
+++ b/compiler/debug/dwarf/headers.h
@@ -19,13 +19,13 @@
#include <cstdint>
+#include "base/array_ref.h"
#include "debug/dwarf/debug_frame_opcode_writer.h"
#include "debug/dwarf/debug_info_entry_writer.h"
#include "debug/dwarf/debug_line_opcode_writer.h"
#include "debug/dwarf/dwarf_constants.h"
#include "debug/dwarf/register.h"
#include "debug/dwarf/writer.h"
-#include "utils/array_ref.h"
namespace art {
namespace dwarf {
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index 5bfdd16083..d1c10a9246 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -18,6 +18,7 @@
#include <vector>
+#include "base/array_ref.h"
#include "debug/dwarf/dwarf_constants.h"
#include "debug/elf_compilation_unit.h"
#include "debug/elf_debug_frame_writer.h"
@@ -29,7 +30,6 @@
#include "debug/method_debug_info.h"
#include "elf_builder.h"
#include "linker/vector_output_stream.h"
-#include "utils/array_ref.h"
namespace art {
namespace debug {
diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h
index b0542c7ac6..07f7229827 100644
--- a/compiler/debug/elf_debug_writer.h
+++ b/compiler/debug/elf_debug_writer.h
@@ -19,11 +19,11 @@
#include <vector>
+#include "base/array_ref.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "debug/dwarf/dwarf_constants.h"
#include "elf_builder.h"
-#include "utils/array_ref.h"
namespace art {
class OatHeader;
diff --git a/compiler/driver/compiled_method_storage.h b/compiler/driver/compiled_method_storage.h
index 8674abf815..124b5a6e25 100644
--- a/compiler/driver/compiled_method_storage.h
+++ b/compiler/driver/compiled_method_storage.h
@@ -20,9 +20,9 @@
#include <iosfwd>
#include <memory>
+#include "base/array_ref.h"
#include "base/length_prefixed_array.h"
#include "base/macros.h"
-#include "utils/array_ref.h"
#include "utils/dedupe_set.h"
#include "utils/swap_space.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 53e068edf2..a149c07beb 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -26,6 +26,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "base/array_ref.h"
#include "base/bit_vector.h"
#include "base/enums.h"
#include "base/stl_util.h"
@@ -67,7 +68,6 @@
#include "thread_pool.h"
#include "trampolines/trampoline_compiler.h"
#include "transaction.h"
-#include "utils/array_ref.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "utils/swap_space.h"
#include "verifier/method_verifier.h"
@@ -2474,7 +2474,7 @@ class InitializeClassVisitor : public CompilationVisitor {
// mode which prevents the GC from visiting objects modified during the transaction.
// Ensure GC is not run so don't access freed objects when aborting transaction.
- ScopedAssertNoThreadSuspension ants(soa.Self(), "Transaction end");
+ ScopedAssertNoThreadSuspension ants("Transaction end");
runtime->ExitTransactionMode();
if (!success) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index fbc1edd0ea..ee21efa854 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -24,6 +24,7 @@
#include "arch/instruction_set.h"
#include "base/arena_allocator.h"
+#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
@@ -39,7 +40,6 @@
#include "runtime.h"
#include "safe_map.h"
#include "thread_pool.h"
-#include "utils/array_ref.h"
#include "utils/dex_cache_arrays_layout.h"
namespace art {
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 7f2e1931d0..02831c9dc7 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -21,13 +21,13 @@
#include "arch/instruction_set.h"
#include "arch/mips/instruction_set_features_mips.h"
+#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/unix_file/fd_file.h"
#include "elf_utils.h"
#include "leb128.h"
#include "linker/error_delaying_output_stream.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
index c9ea0083d5..f8f91029d4 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -22,10 +22,10 @@
#include <string>
#include <vector>
+#include "base/array_ref.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "os.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 7634510457..6d86f7d9d8 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -868,7 +868,7 @@ void ImageWriter::PruneNonImageClasses() {
// Clear references to removed classes from the DexCaches.
ArtMethod* resolution_method = runtime->GetResolutionMethod();
- ScopedAssertNoThreadSuspension sa(self, __FUNCTION__);
+ ScopedAssertNoThreadSuspension sa(__FUNCTION__);
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable
ReaderMutexLock mu2(self, *class_linker->DexLock());
for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 3d89146250..f541d8fa19 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -18,11 +18,11 @@
#define ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_
#include "base/arena_object.h"
+#include "base/array_ref.h"
#include "base/enums.h"
#include "handle_scope.h"
#include "primitive.h"
#include "thread.h"
-#include "utils/array_ref.h"
#include "utils/managed_register.h"
namespace art {
diff --git a/compiler/linker/arm64/relative_patcher_arm64.h b/compiler/linker/arm64/relative_patcher_arm64.h
index 48ad1059b0..a4a80185dc 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.h
+++ b/compiler/linker/arm64/relative_patcher_arm64.h
@@ -17,8 +17,8 @@
#ifndef ART_COMPILER_LINKER_ARM64_RELATIVE_PATCHER_ARM64_H_
#define ART_COMPILER_LINKER_ARM64_RELATIVE_PATCHER_ARM64_H_
+#include "base/array_ref.h"
#include "linker/arm/relative_patcher_arm_base.h"
-#include "utils/array_ref.h"
namespace art {
namespace linker {
diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h
index a22b9f2c2d..15e955b2c6 100644
--- a/compiler/linker/relative_patcher.h
+++ b/compiler/linker/relative_patcher.h
@@ -21,9 +21,9 @@
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
+#include "base/array_ref.h"
#include "base/macros.h"
#include "method_reference.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index d21f33e46f..304b31ca84 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -19,6 +19,7 @@
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
+#include "base/array_ref.h"
#include "base/macros.h"
#include "compiled_method.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
@@ -31,7 +32,6 @@
#include "method_reference.h"
#include "oat.h"
#include "oat_quick_method_header.h"
-#include "utils/array_ref.h"
#include "vector_output_stream.h"
namespace art {
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 43e01d54a6..5e0c64ba8b 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -994,7 +994,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
out_(out),
file_offset_(file_offset),
soa_(Thread::Current()),
- no_thread_suspension_(soa_.Self(), "OatWriter patching"),
+ no_thread_suspension_("OatWriter patching"),
class_linker_(Runtime::Current()->GetClassLinker()),
dex_cache_(nullptr) {
patched_code_.reserve(16 * KB);
@@ -1036,7 +1036,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
// No thread suspension since dex_cache_ that may get invalidated if that occurs.
- ScopedAssertNoThreadSuspension tsc(Thread::Current(), __FUNCTION__);
+ ScopedAssertNoThreadSuspension tsc(__FUNCTION__);
if (compiled_method != nullptr) { // ie. not an abstract method
size_t file_offset = file_offset_;
OutputStream* out = out_;
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 77525f1a32..dd7d699eee 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -21,6 +21,7 @@
#include <cstddef>
#include <memory>
+#include "base/array_ref.h"
#include "base/dchecked_vector.h"
#include "linker/relative_patcher.h" // For linker::RelativePatcherTargetProvider.
#include "mem_map.h"
@@ -29,7 +30,6 @@
#include "oat.h"
#include "os.h"
#include "safe_map.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index e1bde7c737..aa3f26809a 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -16,7 +16,7 @@
#include "dead_code_elimination.h"
-#include "utils/array_ref.h"
+#include "base/array_ref.h"
#include "base/bit_vector-inl.h"
#include "ssa_phi_elimination.h"
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 8f37236ede..9cfa89b7d0 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -460,6 +460,113 @@ GraphAnalysisResult HGraph::AnalyzeLoops() const {
return kAnalysisSuccess;
}
+static bool InSameLoop(HLoopInformation* first_loop, HLoopInformation* second_loop) {
+ return first_loop == second_loop;
+}
+
+static bool IsLoop(HLoopInformation* info) {
+ return info != nullptr;
+}
+
+static bool IsInnerLoop(HLoopInformation* outer, HLoopInformation* inner) {
+ return (inner != outer)
+ && (inner != nullptr)
+ && (outer != nullptr)
+ && inner->IsIn(*outer);
+}
+
+// Helper method to update work list for linear order.
+static void AddToListForLinearization(ArenaVector<HBasicBlock*>* worklist, HBasicBlock* block) {
+ HLoopInformation* block_loop = block->GetLoopInformation();
+ auto insert_pos = worklist->rbegin(); // insert_pos.base() will be the actual position.
+ for (auto end = worklist->rend(); insert_pos != end; ++insert_pos) {
+ HBasicBlock* current = *insert_pos;
+ HLoopInformation* current_loop = current->GetLoopInformation();
+ if (InSameLoop(block_loop, current_loop)
+ || !IsLoop(current_loop)
+ || IsInnerLoop(current_loop, block_loop)) {
+ // The block can be processed immediately.
+ break;
+ }
+ }
+ worklist->insert(insert_pos.base(), block);
+}
+
+// Helper method to validate linear order.
+static bool IsLinearOrderWellFormed(const HGraph& graph) {
+ for (HBasicBlock* header : graph.GetBlocks()) {
+ if (header == nullptr || !header->IsLoopHeader()) {
+ continue;
+ }
+ HLoopInformation* loop = header->GetLoopInformation();
+ size_t num_blocks = loop->GetBlocks().NumSetBits();
+ size_t found_blocks = 0u;
+ for (HLinearOrderIterator it(graph); !it.Done(); it.Advance()) {
+ HBasicBlock* current = it.Current();
+ if (loop->Contains(*current)) {
+ found_blocks++;
+ if (found_blocks == 1u && current != header) {
+ // First block is not the header.
+ return false;
+ } else if (found_blocks == num_blocks && !loop->IsBackEdge(*current)) {
+ // Last block is not a back edge.
+ return false;
+ }
+ } else if (found_blocks != 0u && found_blocks != num_blocks) {
+ // Blocks are not adjacent.
+ return false;
+ }
+ }
+ DCHECK_EQ(found_blocks, num_blocks);
+ }
+ return true;
+}
+
+void HGraph::Linearize() {
+ // Create a reverse post ordering with the following properties:
+ // - Blocks in a loop are consecutive,
+ // - Back-edge is the last block before loop exits.
+
+ // (1): Record the number of forward predecessors for each block. This is to
+ // ensure the resulting order is reverse post order. We could use the
+ // current reverse post order in the graph, but it would require making
+ // order queries to a GrowableArray, which is not the best data structure
+ // for it.
+ ArenaVector<uint32_t> forward_predecessors(blocks_.size(),
+ arena_->Adapter(kArenaAllocSsaLiveness));
+ for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
+ HBasicBlock* block = it.Current();
+ size_t number_of_forward_predecessors = block->GetPredecessors().size();
+ if (block->IsLoopHeader()) {
+ number_of_forward_predecessors -= block->GetLoopInformation()->NumberOfBackEdges();
+ }
+ forward_predecessors[block->GetBlockId()] = number_of_forward_predecessors;
+ }
+
+ // (2): Following a worklist approach, first start with the entry block, and
+ // iterate over the successors. When all non-back edge predecessors of a
+ // successor block are visited, the successor block is added in the worklist
+ // following an order that satisfies the requirements to build our linear graph.
+ linear_order_.reserve(GetReversePostOrder().size());
+ ArenaVector<HBasicBlock*> worklist(arena_->Adapter(kArenaAllocSsaLiveness));
+ worklist.push_back(GetEntryBlock());
+ do {
+ HBasicBlock* current = worklist.back();
+ worklist.pop_back();
+ linear_order_.push_back(current);
+ for (HBasicBlock* successor : current->GetSuccessors()) {
+ int block_id = successor->GetBlockId();
+ size_t number_of_remaining_predecessors = forward_predecessors[block_id];
+ if (number_of_remaining_predecessors == 1) {
+ AddToListForLinearization(&worklist, successor);
+ }
+ forward_predecessors[block_id] = number_of_remaining_predecessors - 1;
+ }
+ } while (!worklist.empty());
+
+ DCHECK(HasIrreducibleLoops() || IsLinearOrderWellFormed(*this));
+}
+
void HLoopInformation::Dump(std::ostream& os) {
os << "header: " << header_->GetBlockId() << std::endl;
os << "pre header: " << GetPreHeader()->GetBlockId() << std::endl;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 119b62a16b..7c3ca5cefa 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -24,7 +24,9 @@
#include "base/arena_bit_vector.h"
#include "base/arena_containers.h"
#include "base/arena_object.h"
+#include "base/array_ref.h"
#include "base/stl_util.h"
+#include "base/transform_array_ref.h"
#include "dex_file.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "handle.h"
@@ -35,9 +37,7 @@
#include "mirror/class.h"
#include "offsets.h"
#include "primitive.h"
-#include "utils/array_ref.h"
#include "utils/intrusive_forward_list.h"
-#include "utils/transform_array_ref.h"
namespace art {
@@ -365,6 +365,13 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
// is a throw-catch loop, i.e. the header is a catch block.
GraphAnalysisResult AnalyzeLoops() const;
+ // Computes the linear order (should be called before using HLinearOrderIterator).
+ // Linearizes the graph such that:
+ // (1): a block is always after its dominator,
+ // (2): blocks of loops are contiguous.
+ // This creates a natural and efficient ordering when visualizing live ranges.
+ void Linearize();
+
// Iterate over blocks to compute try block membership. Needs reverse post
// order and loop information.
void ComputeTryBlockInformation();
diff --git a/compiler/optimizing/register_allocation_resolver.h b/compiler/optimizing/register_allocation_resolver.h
index a70ceae076..d48b1a0bb9 100644
--- a/compiler/optimizing/register_allocation_resolver.h
+++ b/compiler/optimizing/register_allocation_resolver.h
@@ -18,9 +18,9 @@
#define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATION_RESOLVER_H_
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/value_object.h"
#include "primitive.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index a4d52d7761..9ce34aa80b 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -23,119 +23,11 @@
namespace art {
void SsaLivenessAnalysis::Analyze() {
- LinearizeGraph();
+ graph_->Linearize();
NumberInstructions();
ComputeLiveness();
}
-static bool IsLoop(HLoopInformation* info) {
- return info != nullptr;
-}
-
-static bool InSameLoop(HLoopInformation* first_loop, HLoopInformation* second_loop) {
- return first_loop == second_loop;
-}
-
-static bool IsInnerLoop(HLoopInformation* outer, HLoopInformation* inner) {
- return (inner != outer)
- && (inner != nullptr)
- && (outer != nullptr)
- && inner->IsIn(*outer);
-}
-
-static void AddToListForLinearization(ArenaVector<HBasicBlock*>* worklist, HBasicBlock* block) {
- HLoopInformation* block_loop = block->GetLoopInformation();
- auto insert_pos = worklist->rbegin(); // insert_pos.base() will be the actual position.
- for (auto end = worklist->rend(); insert_pos != end; ++insert_pos) {
- HBasicBlock* current = *insert_pos;
- HLoopInformation* current_loop = current->GetLoopInformation();
- if (InSameLoop(block_loop, current_loop)
- || !IsLoop(current_loop)
- || IsInnerLoop(current_loop, block_loop)) {
- // The block can be processed immediately.
- break;
- }
- }
- worklist->insert(insert_pos.base(), block);
-}
-
-static bool IsLinearOrderWellFormed(const HGraph& graph) {
- for (HBasicBlock* header : graph.GetBlocks()) {
- if (header == nullptr || !header->IsLoopHeader()) {
- continue;
- }
-
- HLoopInformation* loop = header->GetLoopInformation();
- size_t num_blocks = loop->GetBlocks().NumSetBits();
- size_t found_blocks = 0u;
-
- for (HLinearOrderIterator it(graph); !it.Done(); it.Advance()) {
- HBasicBlock* current = it.Current();
- if (loop->Contains(*current)) {
- found_blocks++;
- if (found_blocks == 1u && current != header) {
- // First block is not the header.
- return false;
- } else if (found_blocks == num_blocks && !loop->IsBackEdge(*current)) {
- // Last block is not a back edge.
- return false;
- }
- } else if (found_blocks != 0u && found_blocks != num_blocks) {
- // Blocks are not adjacent.
- return false;
- }
- }
- DCHECK_EQ(found_blocks, num_blocks);
- }
-
- return true;
-}
-
-void SsaLivenessAnalysis::LinearizeGraph() {
- // Create a reverse post ordering with the following properties:
- // - Blocks in a loop are consecutive,
- // - Back-edge is the last block before loop exits.
-
- // (1): Record the number of forward predecessors for each block. This is to
- // ensure the resulting order is reverse post order. We could use the
- // current reverse post order in the graph, but it would require making
- // order queries to a GrowableArray, which is not the best data structure
- // for it.
- ArenaVector<uint32_t> forward_predecessors(graph_->GetBlocks().size(),
- graph_->GetArena()->Adapter(kArenaAllocSsaLiveness));
- for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
- HBasicBlock* block = it.Current();
- size_t number_of_forward_predecessors = block->GetPredecessors().size();
- if (block->IsLoopHeader()) {
- number_of_forward_predecessors -= block->GetLoopInformation()->NumberOfBackEdges();
- }
- forward_predecessors[block->GetBlockId()] = number_of_forward_predecessors;
- }
-
- // (2): Following a worklist approach, first start with the entry block, and
- // iterate over the successors. When all non-back edge predecessors of a
- // successor block are visited, the successor block is added in the worklist
- // following an order that satisfies the requirements to build our linear graph.
- graph_->linear_order_.reserve(graph_->GetReversePostOrder().size());
- ArenaVector<HBasicBlock*> worklist(graph_->GetArena()->Adapter(kArenaAllocSsaLiveness));
- worklist.push_back(graph_->GetEntryBlock());
- do {
- HBasicBlock* current = worklist.back();
- worklist.pop_back();
- graph_->linear_order_.push_back(current);
- for (HBasicBlock* successor : current->GetSuccessors()) {
- int block_id = successor->GetBlockId();
- size_t number_of_remaining_predecessors = forward_predecessors[block_id];
- if (number_of_remaining_predecessors == 1) {
- AddToListForLinearization(&worklist, successor);
- }
- forward_predecessors[block_id] = number_of_remaining_predecessors - 1;
- }
- } while (!worklist.empty());
-
- DCHECK(graph_->HasIrreducibleLoops() || IsLinearOrderWellFormed(*graph_));
-}
-
void SsaLivenessAnalysis::NumberInstructions() {
int ssa_index = 0;
size_t lifetime_position = 0;
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 0be16118b1..b62bf4e5f9 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -1186,12 +1186,6 @@ class SsaLivenessAnalysis : public ValueObject {
static constexpr const char* kLivenessPassName = "liveness";
private:
- // Linearize the graph so that:
- // (1): a block is always after its dominator,
- // (2): blocks of loops are contiguous.
- // This creates a natural and efficient ordering when visualizing live ranges.
- void LinearizeGraph();
-
// Give an SSA number to each instruction that defines a value used by another instruction,
// and setup the lifetime information of each instruction and block.
void NumberInstructions();
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 13f3becb6d..353555d0e8 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -22,11 +22,11 @@
#include <vector>
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/logging.h"
#include "constants_arm.h"
#include "utils/arm/managed_register_arm.h"
#include "utils/arm/assembler_arm.h"
-#include "utils/array_ref.h"
#include "offsets.h"
namespace art {
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
index a03dd74657..14d29c4f1a 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
@@ -314,11 +314,21 @@ void ArmVIXLJNIMacroAssembler::Move(ManagedRegister m_dst,
CHECK(src.IsCoreRegister()) << src;
___ Mov(dst.AsVIXLRegister(), src.AsVIXLRegister());
} else if (dst.IsDRegister()) {
- CHECK(src.IsDRegister()) << src;
- ___ Vmov(F64, dst.AsVIXLDRegister(), src.AsVIXLDRegister());
+ if (src.IsDRegister()) {
+ ___ Vmov(F64, dst.AsVIXLDRegister(), src.AsVIXLDRegister());
+ } else {
+ // VMOV Dn, Rlo, Rhi (Dn = {Rlo, Rhi})
+ CHECK(src.IsRegisterPair()) << src;
+ ___ Vmov(dst.AsVIXLDRegister(), src.AsVIXLRegisterPairLow(), src.AsVIXLRegisterPairHigh());
+ }
} else if (dst.IsSRegister()) {
- CHECK(src.IsSRegister()) << src;
- ___ Vmov(F32, dst.AsVIXLSRegister(), src.AsVIXLSRegister());
+ if (src.IsSRegister()) {
+ ___ Vmov(F32, dst.AsVIXLSRegister(), src.AsVIXLSRegister());
+ } else {
+ // VMOV Sn, Rn (Sn = Rn)
+ CHECK(src.IsCoreRegister()) << src;
+ ___ Vmov(dst.AsVIXLSRegister(), src.AsVIXLRegister());
+ }
} else {
CHECK(dst.IsRegisterPair()) << dst;
CHECK(src.IsRegisterPair()) << src;
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index b616057e79..314ff8cf7a 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -24,6 +24,7 @@
#include "arm/constants_arm.h"
#include "base/arena_allocator.h"
#include "base/arena_object.h"
+#include "base/array_ref.h"
#include "base/enums.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -33,7 +34,6 @@
#include "memory_region.h"
#include "mips/constants_mips.h"
#include "offsets.h"
-#include "utils/array_ref.h"
#include "x86/constants_x86.h"
#include "x86_64/constants_x86_64.h"
diff --git a/compiler/utils/dedupe_set_test.cc b/compiler/utils/dedupe_set_test.cc
index 60a891d6a2..4c0979e0b7 100644
--- a/compiler/utils/dedupe_set_test.cc
+++ b/compiler/utils/dedupe_set_test.cc
@@ -20,10 +20,10 @@
#include <cstdio>
#include <vector>
+#include "base/array_ref.h"
#include "dedupe_set-inl.h"
#include "gtest/gtest.h"
#include "thread-inl.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/utils/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h
index 6f45bd62db..0119ae9bfb 100644
--- a/compiler/utils/jni_macro_assembler.h
+++ b/compiler/utils/jni_macro_assembler.h
@@ -22,12 +22,12 @@
#include "arch/instruction_set.h"
#include "base/arena_allocator.h"
#include "base/arena_object.h"
+#include "base/array_ref.h"
#include "base/enums.h"
#include "base/logging.h"
#include "base/macros.h"
#include "managed_register.h"
#include "offsets.h"
-#include "utils/array_ref.h"
namespace art {
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 9738784d45..114986b3e7 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -20,6 +20,7 @@
#include <vector>
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/enums.h"
#include "base/macros.h"
@@ -27,7 +28,6 @@
#include "globals.h"
#include "managed_register_x86.h"
#include "offsets.h"
-#include "utils/array_ref.h"
#include "utils/assembler.h"
namespace art {
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.h b/compiler/utils/x86/jni_macro_assembler_x86.h
index 3f07ede865..015584cbc1 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.h
+++ b/compiler/utils/x86/jni_macro_assembler_x86.h
@@ -21,10 +21,10 @@
#include "assembler_x86.h"
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/enums.h"
#include "base/macros.h"
#include "offsets.h"
-#include "utils/array_ref.h"
#include "utils/jni_macro_assembler.h"
namespace art {
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index fdd3aa9317..acad86d161 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -20,13 +20,13 @@
#include <vector>
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/macros.h"
#include "constants_x86_64.h"
#include "globals.h"
#include "managed_register_x86_64.h"
#include "offsets.h"
-#include "utils/array_ref.h"
#include "utils/assembler.h"
#include "utils/jni_macro_assembler.h"
diff --git a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
index cc4e57c999..9107f3c422 100644
--- a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
+++ b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
@@ -21,10 +21,10 @@
#include "assembler_x86_64.h"
#include "base/arena_containers.h"
+#include "base/array_ref.h"
#include "base/enums.h"
#include "base/macros.h"
#include "offsets.h"
-#include "utils/array_ref.h"
#include "utils/assembler.h"
#include "utils/jni_macro_assembler.h"
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 1dd91321c5..1296bcf525 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2782,6 +2782,8 @@ static int dex2oat(int argc, char** argv) {
return EXIT_FAILURE;
}
+ VLOG(compiler) << "Running dex2oat (parent PID = " << getppid() << ")";
+
bool result;
if (dex2oat->IsImage()) {
result = CompileImage(*dex2oat);
diff --git a/dexlist/dexlist_test.cc b/dexlist/dexlist_test.cc
index 9a65ba647c..da1dd7fd89 100644
--- a/dexlist/dexlist_test.cc
+++ b/dexlist/dexlist_test.cc
@@ -43,11 +43,7 @@ class DexListTest : public CommonRuntimeTest {
// Runs test with given arguments.
bool Exec(const std::vector<std::string>& args, std::string* error_msg) {
std::string file_path = GetTestAndroidRoot();
- if (IsHost()) {
- file_path += "/bin/dexlist";
- } else {
- file_path += "/xbin/dexlist";
- }
+ file_path += "/bin/dexlist";
EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
std::vector<std::string> exec_argv = { file_path };
exec_argv.insert(exec_argv.end(), args.begin(), args.end());
diff --git a/runtime/Android.bp b/runtime/Android.bp
index b61976c47b..eb7b0c82f3 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -53,6 +53,7 @@ cc_defaults {
"compiler_filter.cc",
"debugger.cc",
"dex_file.cc",
+ "dex_file_annotations.cc",
"dex_file_verifier.cc",
"dex_instruction.cc",
"elf_file.cc",
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 0416988e06..0b044802b4 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -260,7 +260,7 @@
.fnstart
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r0 @ save callee saves for throw
mov r0, r9 @ pass Thread::Current
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*)
+ bl artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*)
.endm
.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
@@ -268,7 +268,7 @@
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r0 @ save all registers as basis for long jump context
mov r0, r9 @ pass Thread::Current
- b \cxx_name @ \cxx_name(Thread*)
+ bl \cxx_name @ \cxx_name(Thread*)
END \c_name
.endm
@@ -277,7 +277,7 @@ END \c_name
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r1 @ save all registers as basis for long jump context
mov r1, r9 @ pass Thread::Current
- b \cxx_name @ \cxx_name(Thread*)
+ bl \cxx_name @ \cxx_name(Thread*)
END \c_name
.endm
@@ -286,7 +286,7 @@ END \c_name
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r2 @ save all registers as basis for long jump context
mov r2, r9 @ pass Thread::Current
- b \cxx_name @ \cxx_name(Thread*)
+ bl \cxx_name @ \cxx_name(Thread*)
END \c_name
.endm
@@ -392,7 +392,7 @@ ENTRY art_quick_throw_null_pointer_exception_from_signal
SETUP_SAVE_EVERYTHING_FRAME_CORE_REGS_SAVED r1
mov r0, lr @ pass the fault address stored in LR by the fault handler.
mov r1, r9 @ pass Thread::Current
- b artThrowNullPointerExceptionFromSignal @ (Thread*)
+ bl artThrowNullPointerExceptionFromSignal @ (Thread*)
END art_quick_throw_null_pointer_exception_from_signal
/*
@@ -753,7 +753,7 @@ ENTRY art_quick_check_cast
.cfi_restore lr
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r2 @ save all registers as basis for long jump context
mov r2, r9 @ pass Thread::Current
- b artThrowClassCastException @ (Class*, Class*, Thread*)
+ bl artThrowClassCastException @ (Class*, Class*, Thread*)
bkpt
END art_quick_check_cast
@@ -896,7 +896,7 @@ ENTRY art_quick_aput_obj
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r3
mov r1, r2
mov r2, r9 @ pass Thread::Current
- b artThrowArrayStoreException @ (Class*, Class*, Thread*)
+ bl artThrowArrayStoreException @ (Class*, Class*, Thread*)
bkpt @ unreached
END art_quick_aput_obj
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 1a8a2b27fa..e9d03d7ceb 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -400,7 +400,7 @@
mov x0, xSELF
// Point of no return.
- b artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*)
+ bl artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*)
brk 0 // Unreached
.endm
@@ -433,7 +433,7 @@
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
mov x0, xSELF // pass Thread::Current
- b \cxx_name // \cxx_name(Thread*)
+ bl \cxx_name // \cxx_name(Thread*)
END \c_name
.endm
@@ -442,7 +442,7 @@ END \c_name
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context.
mov x1, xSELF // pass Thread::Current.
- b \cxx_name // \cxx_name(arg, Thread*).
+ bl \cxx_name // \cxx_name(arg, Thread*).
brk 0
END \c_name
.endm
@@ -452,7 +452,7 @@ END \c_name
ENTRY \c_name
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
mov x2, xSELF // pass Thread::Current
- b \cxx_name // \cxx_name(arg1, arg2, Thread*)
+ bl \cxx_name // \cxx_name(arg1, arg2, Thread*)
brk 0
END \c_name
.endm
@@ -483,8 +483,7 @@ ENTRY art_quick_throw_null_pointer_exception_from_signal
SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_X29_LR
mov x0, lr // pass the fault address stored in LR by the fault handler.
mov x1, xSELF // pass Thread::Current.
- // TODO: Change other throwing entrypoints to use BL instead of B. http://b/31468464
- bl artThrowNullPointerExceptionFromSignal // (arg, Thread*).
+ bl artThrowNullPointerExceptionFromSignal // (arg, Thread*).
brk 0
END art_quick_throw_null_pointer_exception_from_signal
@@ -1302,7 +1301,7 @@ ENTRY art_quick_check_cast
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
mov x2, xSELF // pass Thread::Current
- b artThrowClassCastException // (Class*, Class*, Thread*)
+ bl artThrowClassCastException // (Class*, Class*, Thread*)
brk 0 // We should not return here...
END art_quick_check_cast
@@ -1466,10 +1465,10 @@ ENTRY art_quick_aput_obj
RESTORE_TWO_REGS_DECREASE_FRAME x0, x1, 32
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
- mov x1, x2 // Pass value.
- mov x2, xSELF // Pass Thread::Current.
- b artThrowArrayStoreException // (Object*, Object*, Thread*).
- brk 0 // Unreached.
+ mov x1, x2 // Pass value.
+ mov x2, xSELF // Pass Thread::Current.
+ bl artThrowArrayStoreException // (Object*, Object*, Thread*).
+ brk 0 // Unreached.
END art_quick_aput_obj
// Macro to facilitate adding new allocation entrypoints.
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 1659f3333b..9b4b38aa0f 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -24,6 +24,7 @@
#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file.h"
+#include "dex_file_annotations.h"
#include "dex_file-inl.h"
#include "gc_root-inl.h"
#include "jit/profiling_info.h"
@@ -347,7 +348,7 @@ inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
if (dex_pc == DexFile::kDexNoIndex) {
return IsNative() ? -2 : -1;
}
- return GetDexFile()->GetLineNumFromPC(this, dex_pc);
+ return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
}
inline const DexFile::ProtoId& ArtMethod::GetPrototype() {
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 1392399bde..fd6c37a4e5 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -25,6 +25,7 @@
#include "class_linker-inl.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "dex_instruction.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
@@ -107,7 +108,7 @@ size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
}
bool ArtMethod::HasSameNameAndSignature(ArtMethod* other) {
- ScopedAssertNoThreadSuspension ants(Thread::Current(), "HasSameNameAndSignature");
+ ScopedAssertNoThreadSuspension ants("HasSameNameAndSignature");
const DexFile* dex_file = GetDexFile();
const DexFile::MethodId& mid = dex_file->GetMethodId(GetDexMethodIndex());
if (GetDexCache() == other->GetDexCache()) {
@@ -349,8 +350,6 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {
ScopedObjectAccess soa(self);
StackHandleScope<1> shs(self);
- const DexFile& dex_file = GetDeclaringClass()->GetDexFile();
-
mirror::Class* annotation = soa.Decode<mirror::Class*>(klass);
DCHECK(annotation->IsAnnotation());
Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation));
@@ -358,7 +357,7 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {
// Note: Resolves any method annotations' classes as a side-effect.
// -- This seems allowed by the spec since it says we can preload any classes
// referenced by another classes's constant pool table.
- return dex_file.IsMethodAnnotationPresent(this, annotation_handle, visibility);
+ return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility);
}
bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 8051a1fc7e..b1baccded9 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -33,6 +33,7 @@
namespace art {
+template<class T> class Handle;
union JValue;
class OatQuickMethodHeader;
class ProfilingInfo;
diff --git a/compiler/utils/array_ref.h b/runtime/base/array_ref.h
index 8dc9ab4a5e..00b9bad6bf 100644
--- a/compiler/utils/array_ref.h
+++ b/runtime/base/array_ref.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_UTILS_ARRAY_REF_H_
-#define ART_COMPILER_UTILS_ARRAY_REF_H_
+#ifndef ART_RUNTIME_BASE_ARRAY_REF_H_
+#define ART_RUNTIME_BASE_ARRAY_REF_H_
#include <type_traits>
#include <vector>
@@ -197,4 +197,4 @@ bool operator!=(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
} // namespace art
-#endif // ART_COMPILER_UTILS_ARRAY_REF_H_
+#endif // ART_RUNTIME_BASE_ARRAY_REF_H_
diff --git a/compiler/utils/transform_array_ref.h b/runtime/base/transform_array_ref.h
index a6da34fb40..a4e0bc27ed 100644
--- a/compiler/utils/transform_array_ref.h
+++ b/runtime/base/transform_array_ref.h
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_UTILS_TRANSFORM_ARRAY_REF_H_
-#define ART_COMPILER_UTILS_TRANSFORM_ARRAY_REF_H_
+#ifndef ART_RUNTIME_BASE_TRANSFORM_ARRAY_REF_H_
+#define ART_RUNTIME_BASE_TRANSFORM_ARRAY_REF_H_
#include <type_traits>
-#include "utils/array_ref.h"
-#include "utils/transform_iterator.h"
+#include "base/array_ref.h"
+#include "base/transform_iterator.h"
namespace art {
@@ -193,4 +193,4 @@ TransformArrayRef<const typename Container::value_type, Function> MakeTransformA
} // namespace art
-#endif // ART_COMPILER_UTILS_TRANSFORM_ARRAY_REF_H_
+#endif // ART_RUNTIME_BASE_TRANSFORM_ARRAY_REF_H_
diff --git a/compiler/utils/transform_array_ref_test.cc b/runtime/base/transform_array_ref_test.cc
index 8d71fd7179..494dbb29aa 100644
--- a/compiler/utils/transform_array_ref_test.cc
+++ b/runtime/base/transform_array_ref_test.cc
@@ -19,7 +19,7 @@
#include "gtest/gtest.h"
-#include "utils/transform_array_ref.h"
+#include "base/transform_array_ref.h"
namespace art {
diff --git a/compiler/utils/transform_iterator.h b/runtime/base/transform_iterator.h
index 3bc9046408..9c8f822b71 100644
--- a/compiler/utils/transform_iterator.h
+++ b/runtime/base/transform_iterator.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_UTILS_TRANSFORM_ITERATOR_H_
-#define ART_COMPILER_UTILS_TRANSFORM_ITERATOR_H_
+#ifndef ART_RUNTIME_BASE_TRANSFORM_ITERATOR_H_
+#define ART_RUNTIME_BASE_TRANSFORM_ITERATOR_H_
#include <iterator>
#include <type_traits>
@@ -175,4 +175,4 @@ auto MakeTransformRange(BaseRange& range, Function f) {
} // namespace art
-#endif // ART_COMPILER_UTILS_TRANSFORM_ITERATOR_H_
+#endif // ART_RUNTIME_BASE_TRANSFORM_ITERATOR_H_
diff --git a/compiler/utils/transform_iterator_test.cc b/runtime/base/transform_iterator_test.cc
index 57ff0a62ac..a85dda8958 100644
--- a/compiler/utils/transform_iterator_test.cc
+++ b/runtime/base/transform_iterator_test.cc
@@ -22,7 +22,7 @@
#include "gtest/gtest.h"
-#include "utils/transform_iterator.h"
+#include "base/transform_iterator.h"
namespace art {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4d252e1be9..6d9373639e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1533,7 +1533,7 @@ static std::unique_ptr<const DexFile> OpenOatDexFile(const OatFile* oat_file,
bool ClassLinker::OpenImageDexFiles(gc::space::ImageSpace* space,
std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
std::string* error_msg) {
- ScopedAssertNoThreadSuspension nts(Thread::Current(), __FUNCTION__);
+ ScopedAssertNoThreadSuspension nts(__FUNCTION__);
const ImageHeader& header = space->GetImageHeader();
mirror::Object* dex_caches_object = header.GetImageRoot(ImageHeader::kDexCaches);
DCHECK(dex_caches_object != nullptr);
@@ -1923,7 +1923,7 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor) {
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
// Not safe to have thread suspension when we are holding a lock.
if (self != nullptr) {
- ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
+ ScopedAssertNoThreadSuspension nts(__FUNCTION__);
VisitClassesInternal(visitor);
} else {
VisitClassesInternal(visitor);
@@ -1965,9 +1965,8 @@ class GetClassInToObjectArray : public ClassVisitor {
void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
// TODO: it may be possible to avoid secondary storage if we iterate over dex caches. The problem
// is avoiding duplicates.
- Thread* const self = Thread::Current();
if (!kMovingClasses) {
- ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
+ ScopedAssertNoThreadSuspension nts(__FUNCTION__);
GetClassesInToVector accumulator;
VisitClasses(&accumulator);
for (mirror::Class* klass : accumulator.classes_) {
@@ -1976,6 +1975,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
}
}
} else {
+ Thread* const self = Thread::Current();
StackHandleScope<1> hs(self);
auto classes = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr);
// We size the array assuming classes won't be added to the class table during the visit.
@@ -3047,7 +3047,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
- ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
+ ScopedAssertNoThreadSuspension nts(__FUNCTION__);
// Load static fields.
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
@@ -3113,7 +3113,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
// 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(self, dex_file, it, klass, method);
+ LoadMethod(dex_file, it, klass, method);
LinkCode(method, oat_class, class_def_method_index);
uint32_t it_method_index = it.GetMemberIndex();
if (last_dex_method_index == it_method_index) {
@@ -3128,7 +3128,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
}
for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
- LoadMethod(self, dex_file, it, klass, method);
+ LoadMethod(dex_file, it, klass, method);
DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
LinkCode(method, oat_class, class_def_method_index);
class_def_method_index++;
@@ -3149,8 +3149,7 @@ void ClassLinker::LoadField(const ClassDataItemIterator& it,
dst->SetAccessFlags(it.GetFieldAccessFlags());
}
-void ClassLinker::LoadMethod(Thread* self,
- const DexFile& dex_file,
+void ClassLinker::LoadMethod(const DexFile& dex_file,
const ClassDataItemIterator& it,
Handle<mirror::Class> klass,
ArtMethod* dst) {
@@ -3158,7 +3157,7 @@ void ClassLinker::LoadMethod(Thread* self,
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
- ScopedAssertNoThreadSuspension ants(self, "LoadMethod");
+ ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
@@ -3692,7 +3691,7 @@ void ClassLinker::AddImageClassesToClassTable(std::vector<gc::space::ImageSpace*
mirror::ClassLoader* class_loader) {
Thread* self = Thread::Current();
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ScopedAssertNoThreadSuspension ants(self, "Moving image classes to class table");
+ ScopedAssertNoThreadSuspension ants("Moving image classes to class table");
ClassTable* const class_table = InsertClassTableForClassLoader(class_loader);
@@ -3747,7 +3746,7 @@ void ClassLinker::MoveClassTableToPreZygote() {
}
mirror::Class* ClassLinker::LookupClassFromBootImage(const char* descriptor) {
- ScopedAssertNoThreadSuspension ants(Thread::Current(), "Image class lookup");
+ ScopedAssertNoThreadSuspension ants("Image class lookup");
std::vector<mirror::ObjectArray<mirror::DexCache>*> dex_caches_vector =
GetImageDexCaches(Runtime::Current()->GetHeap()->GetBootImageSpaces());
for (mirror::ObjectArray<mirror::DexCache>* dex_caches : dex_caches_vector) {
@@ -4639,8 +4638,11 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
}
}
- EncodedStaticFieldValueIterator value_it(dex_file, &dex_cache, &class_loader,
- this, *dex_class_def);
+ annotations::RuntimeEncodedStaticFieldValueIterator value_it(dex_file,
+ &dex_cache,
+ &class_loader,
+ this,
+ *dex_class_def);
const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
ClassDataItemIterator field_it(dex_file, class_data);
if (value_it.HasNext()) {
@@ -6505,7 +6507,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
size_t new_ifcount;
{
- ScopedAssertNoThreadSuspension nts(self, "Copying mirror::Class*'s for FillIfTable");
+ ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
std::vector<mirror::Class*> to_add;
for (size_t i = 0; i < num_interfaces; i++) {
mirror::Class* interface = have_interfaces ? interfaces->Get(i) :
@@ -8268,7 +8270,7 @@ void ClassLinker::CleanupClassLoaders() {
std::set<DexCacheResolvedClasses> ClassLinker::GetResolvedClasses(bool ignore_boot_classes) {
ScopedTrace trace(__PRETTY_FUNCTION__);
ScopedObjectAccess soa(Thread::Current());
- ScopedAssertNoThreadSuspension ants(soa.Self(), __FUNCTION__);
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
std::set<DexCacheResolvedClasses> ret;
VLOG(class_linker) << "Collecting resolved classes";
const uint64_t start_time = NanoTime();
@@ -8342,7 +8344,7 @@ std::unordered_set<std::string> ClassLinker::GetClassDescriptorsForProfileKeys(
Thread* const self = Thread::Current();
std::unordered_map<std::string, const DexFile*> location_to_dex_file;
ScopedObjectAccess soa(self);
- ScopedAssertNoThreadSuspension ants(soa.Self(), __FUNCTION__);
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
ReaderMutexLock mu(self, *DexLock());
for (const ClassLinker::DexCacheData& data : GetDexCachesData()) {
if (!self->IsJWeakCleared(data.weak_root)) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 5e4ae03782..0a46e2ebed 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -769,8 +769,7 @@ class ClassLinker {
void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadMethod(Thread* self,
- const DexFile& dex_file,
+ void LoadMethod(const DexFile& dex_file,
const ClassDataItemIterator& it,
Handle<mirror::Class> klass, ArtMethod* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 9f3c2aa89b..b49c01cfb1 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -28,6 +28,7 @@
#include "class_linker.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "dex_instruction.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
@@ -1986,7 +1987,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p
if (error != JDWP::ERR_NONE) {
return JDWP::ERR_INVALID_OBJECT;
}
- ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroup");
+ ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroup");
// Okay, so it's an object, but is it actually a thread?
DecodeThread(soa, thread_id, &error);
if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
@@ -2036,7 +2037,7 @@ JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::Ex
if (error != JDWP::ERR_NONE) {
return error;
}
- ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupName");
+ ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupName");
ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name);
CHECK(f != nullptr);
mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group));
@@ -2055,7 +2056,7 @@ JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP::
}
mirror::Object* parent;
{
- ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupParent");
+ ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupParent");
ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent);
CHECK(f != nullptr);
parent = f->GetObject(thread_group);
@@ -3694,8 +3695,8 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize
mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
method = m;
if (dex_cache != nullptr) {
- const DexFile& dex_file = *dex_cache->GetDexFile();
- line_number = dex_file.GetLineNumFromPC(m, GetDexPc());
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc());
}
}
}
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 76cd348d8e..ccc4c168e5 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -27,28 +27,20 @@
#include <memory>
#include <sstream>
-#include "art_field-inl.h"
-#include "art_method-inl.h"
#include "base/enums.h"
#include "base/file_magic.h"
#include "base/hash_map.h"
#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/stringprintf.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "dex_file_verifier.h"
#include "globals.h"
-#include "handle_scope-inl.h"
#include "jvalue.h"
#include "leb128.h"
-#include "mirror/field.h"
-#include "mirror/method.h"
-#include "mirror/string.h"
#include "os.h"
-#include "reflection.h"
#include "safe_map.h"
#include "thread.h"
#include "type_lookup_table.h"
@@ -864,22 +856,6 @@ const Signature DexFile::CreateSignature(const StringPiece& signature) const {
return Signature(this, *proto_id);
}
-int32_t DexFile::GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const {
- // For native method, lineno should be -2 to indicate it is native. Note that
- // "line number == -2" is how libcore tells from StackTraceElement.
- if (method->GetCodeItemOffset() == 0) {
- return -2;
- }
-
- const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
- DCHECK(code_item != nullptr) << PrettyMethod(method) << " " << GetLocation();
-
- // A method with no line number info should return -1
- LineNumFromPcContext context(rel_pc, -1);
- DecodeDebugPositionInfo(code_item, LineNumForPcCb, &context);
- return context.line_num_;
-}
-
int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) {
// Note: Signed type is important for max and min.
int32_t min = 0;
@@ -1186,7 +1162,7 @@ std::string DexFile::GetDexCanonicalLocation(const char* dex_location) {
}
// Read a signed integer. "zwidth" is the zero-based byte count.
-static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) {
+int32_t DexFile::ReadSignedInt(const uint8_t* ptr, int zwidth) {
int32_t val = 0;
for (int i = zwidth; i >= 0; --i) {
val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
@@ -1197,7 +1173,7 @@ static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) {
// Read an unsigned integer. "zwidth" is the zero-based byte count,
// "fill_on_right" indicates which side we want to zero-fill from.
-static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) {
+uint32_t DexFile::ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) {
uint32_t val = 0;
for (int i = zwidth; i >= 0; --i) {
val = (val >> 8) | (((uint32_t)*ptr++) << 24);
@@ -1209,7 +1185,7 @@ static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_rig
}
// Read a signed long. "zwidth" is the zero-based byte count.
-static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) {
+int64_t DexFile::ReadSignedLong(const uint8_t* ptr, int zwidth) {
int64_t val = 0;
for (int i = zwidth; i >= 0; --i) {
val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
@@ -1220,7 +1196,7 @@ static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) {
// Read an unsigned long. "zwidth" is the zero-based byte count,
// "fill_on_right" indicates which side we want to zero-fill from.
-static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) {
+uint64_t DexFile::ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) {
uint64_t val = 0;
for (int i = zwidth; i >= 0; --i) {
val = (val >> 8) | (((uint64_t)*ptr++) << 56);
@@ -1233,1150 +1209,6 @@ static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_ri
// Checks that visibility is as expected. Includes special behavior for M and
// before to allow runtime and build visibility when expecting runtime.
-static bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) {
- if (expected == DexFile::kDexVisibilityRuntime) {
- int32_t sdk_version = Runtime::Current()->GetTargetSdkVersion();
- if (sdk_version > 0 && sdk_version <= 23) {
- return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild;
- }
- }
- return actual == expected;
-}
-
-const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForField(ArtField* field) const {
- mirror::Class* klass = field->GetDeclaringClass();
- const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef());
- if (annotations_dir == nullptr) {
- return nullptr;
- }
- const FieldAnnotationsItem* field_annotations = GetFieldAnnotations(annotations_dir);
- if (field_annotations == nullptr) {
- return nullptr;
- }
- uint32_t field_index = field->GetDexFieldIndex();
- uint32_t field_count = annotations_dir->fields_size_;
- for (uint32_t i = 0; i < field_count; ++i) {
- if (field_annotations[i].field_idx_ == field_index) {
- return GetFieldAnnotationSetItem(field_annotations[i]);
- }
- }
- return nullptr;
-}
-
-mirror::Object* DexFile::GetAnnotationForField(ArtField* field,
- Handle<mirror::Class> annotation_class) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
- return GetAnnotationObjectFromAnnotationSet(
- field_class, annotation_set, kDexVisibilityRuntime, annotation_class);
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForField(ArtField* field) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
- return ProcessAnnotationSet(field_class, annotation_set, kDexVisibilityRuntime);
-}
-
-mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForField(ArtField* field)
- const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
- return GetSignatureValue(field_class, annotation_set);
-}
-
-bool DexFile::IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class)
- const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
- if (annotation_set == nullptr) {
- return false;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
- const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
- field_class, annotation_set, kDexVisibilityRuntime, annotation_class);
- return annotation_item != nullptr;
-}
-
-const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForMethod(ArtMethod* method) const {
- mirror::Class* klass = method->GetDeclaringClass();
- const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef());
- if (annotations_dir == nullptr) {
- return nullptr;
- }
- const MethodAnnotationsItem* method_annotations = GetMethodAnnotations(annotations_dir);
- if (method_annotations == nullptr) {
- return nullptr;
- }
- uint32_t method_index = method->GetDexMethodIndex();
- uint32_t method_count = annotations_dir->methods_size_;
- for (uint32_t i = 0; i < method_count; ++i) {
- if (method_annotations[i].method_idx_ == method_index) {
- return GetMethodAnnotationSetItem(method_annotations[i]);
- }
- }
- return nullptr;
-}
-
-const DexFile::ParameterAnnotationsItem* DexFile::FindAnnotationsItemForMethod(ArtMethod* method)
- const {
- mirror::Class* klass = method->GetDeclaringClass();
- const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef());
- if (annotations_dir == nullptr) {
- return nullptr;
- }
- const ParameterAnnotationsItem* parameter_annotations = GetParameterAnnotations(annotations_dir);
- if (parameter_annotations == nullptr) {
- return nullptr;
- }
- uint32_t method_index = method->GetDexMethodIndex();
- uint32_t parameter_count = annotations_dir->parameters_size_;
- for (uint32_t i = 0; i < parameter_count; ++i) {
- if (parameter_annotations[i].method_idx_ == method_index) {
- return &parameter_annotations[i];
- }
- }
- return nullptr;
-}
-
-mirror::Object* DexFile::GetAnnotationDefaultValue(ArtMethod* method) const {
- mirror::Class* klass = method->GetDeclaringClass();
- const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef());
- if (annotations_dir == nullptr) {
- return nullptr;
- }
- const AnnotationSetItem* annotation_set = GetClassAnnotationSet(annotations_dir);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(annotation_set,
- "Ldalvik/annotation/AnnotationDefault;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value");
- if (annotation == nullptr) {
- return nullptr;
- }
- uint8_t header_byte = *(annotation++);
- if ((header_byte & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) {
- return nullptr;
- }
- annotation = SearchEncodedAnnotation(annotation, method->GetName());
- if (annotation == nullptr) {
- return nullptr;
- }
- AnnotationValue annotation_value;
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::Class> h_klass(hs.NewHandle(klass));
- PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- Handle<mirror::Class> return_type(hs.NewHandle(
- method->GetReturnType(true /* resolve */, pointer_size)));
- if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type, kAllObjects)) {
- return nullptr;
- }
- return annotation_value.value_.GetL();
-}
-
-mirror::Object* DexFile::GetAnnotationForMethod(ArtMethod* method,
- Handle<mirror::Class> annotation_class) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set,
- kDexVisibilityRuntime, annotation_class);
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForMethod(ArtMethod* method) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return ProcessAnnotationSet(method_class, annotation_set, kDexVisibilityRuntime);
-}
-
-mirror::ObjectArray<mirror::Class>* DexFile::GetExceptionTypesForMethod(ArtMethod* method) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return GetThrowsValue(method_class, annotation_set);
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::GetParameterAnnotations(ArtMethod* method) const {
- const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
- if (parameter_annotations == nullptr) {
- return nullptr;
- }
- const AnnotationSetRefList* set_ref_list =
- GetParameterAnnotationSetRefList(parameter_annotations);
- if (set_ref_list == nullptr) {
- return nullptr;
- }
- uint32_t size = set_ref_list->size_;
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return ProcessAnnotationSetRefList(method_class, set_ref_list, size);
-}
-
-mirror::Object* DexFile::GetAnnotationForMethodParameter(ArtMethod* method,
- uint32_t parameter_idx,
- Handle<mirror::Class> annotation_class)
- const {
- const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
- if (parameter_annotations == nullptr) {
- return nullptr;
- }
- const AnnotationSetRefList* set_ref_list =
- GetParameterAnnotationSetRefList(parameter_annotations);
- if (set_ref_list == nullptr) {
- return nullptr;
- }
-
- if (parameter_idx >= set_ref_list->size_) {
- return nullptr;
- }
- const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
- const AnnotationSetItem* annotation_set = GetSetRefItemItem(annotation_set_ref);
-
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return GetAnnotationObjectFromAnnotationSet(method_class,
- annotation_set,
- kDexVisibilityRuntime,
- annotation_class);
-}
-
-mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForMethod(ArtMethod* method)
- const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- return GetSignatureValue(method_class, annotation_set);
-}
-
-bool DexFile::IsMethodAnnotationPresent(ArtMethod* method,
- Handle<mirror::Class> annotation_class,
- uint32_t visibility /* = kDexVisibilityRuntime */)
- const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
- if (annotation_set == nullptr) {
- return false;
- }
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
- const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(method_class,
- annotation_set,
- visibility,
- annotation_class);
- return annotation_item != nullptr;
-}
-
-const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForClass(Handle<mirror::Class> klass)
- const {
- const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef());
- if (annotations_dir == nullptr) {
- return nullptr;
- }
- return GetClassAnnotationSet(annotations_dir);
-}
-
-mirror::Object* DexFile::GetAnnotationForClass(Handle<mirror::Class> klass,
- Handle<mirror::Class> annotation_class) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, kDexVisibilityRuntime,
- annotation_class);
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForClass(Handle<mirror::Class> klass)
- const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- return ProcessAnnotationSet(klass, annotation_set, kDexVisibilityRuntime);
-}
-
-mirror::ObjectArray<mirror::Class>* DexFile::GetDeclaredClasses(Handle<mirror::Class> klass) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/MemberClasses;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- StackHandleScope<1> hs(Thread::Current());
- 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.Get() == nullptr) {
- return nullptr;
- }
- mirror::Object* obj = GetAnnotationValue(
- klass, annotation_item, "value", class_array_class, kDexAnnotationArray);
- if (obj == nullptr) {
- return nullptr;
- }
- return obj->AsObjectArray<mirror::Class>();
-}
-
-mirror::Class* DexFile::GetDeclaringClass(Handle<mirror::Class> klass) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/EnclosingClass;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- mirror::Object* obj = GetAnnotationValue(klass,
- annotation_item,
- "value",
- ScopedNullHandle<mirror::Class>(),
- kDexAnnotationType);
- if (obj == nullptr) {
- return nullptr;
- }
- return obj->AsClass();
-}
-
-mirror::Class* DexFile::GetEnclosingClass(Handle<mirror::Class> klass) const {
- mirror::Class* declaring_class = GetDeclaringClass(klass);
- if (declaring_class != nullptr) {
- return declaring_class;
- }
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value");
- if (annotation == nullptr) {
- return nullptr;
- }
- AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass,
- &annotation,
- &annotation_value,
- ScopedNullHandle<mirror::Class>(),
- kAllRaw)) {
- return nullptr;
- }
- if (annotation_value.type_ != kDexAnnotationMethod) {
- return nullptr;
- }
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
- klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader);
- if (method == nullptr) {
- return nullptr;
- }
- return method->GetDeclaringClass();
-}
-
-mirror::Object* DexFile::GetEnclosingMethod(Handle<mirror::Class> klass) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- return GetAnnotationValue(
- klass, annotation_item, "value", ScopedNullHandle<mirror::Class>(), kDexAnnotationMethod);
-}
-
-bool DexFile::GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return false;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return false;
- }
- const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "name");
- if (annotation == nullptr) {
- return false;
- }
- AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass,
- &annotation,
- &annotation_value,
- ScopedNullHandle<mirror::Class>(),
- kAllObjects)) {
- return false;
- }
- if (annotation_value.type_ != kDexAnnotationNull &&
- annotation_value.type_ != kDexAnnotationString) {
- return false;
- }
- *name = down_cast<mirror::String*>(annotation_value.value_.GetL());
- return true;
-}
-
-bool DexFile::GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return false;
- }
- const AnnotationItem* annotation_item = SearchAnnotationSet(
- annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return false;
- }
- const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "accessFlags");
- if (annotation == nullptr) {
- return false;
- }
- AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass,
- &annotation,
- &annotation_value,
- ScopedNullHandle<mirror::Class>(),
- kAllRaw)) {
- return false;
- }
- if (annotation_value.type_ != kDexAnnotationInt) {
- return false;
- }
- *flags = annotation_value.value_.GetI();
- return true;
-}
-
-mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForClass(
- Handle<mirror::Class> klass) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- return GetSignatureValue(klass, annotation_set);
-}
-
-bool DexFile::IsClassAnnotationPresent(Handle<mirror::Class> klass,
- Handle<mirror::Class> annotation_class) const {
- const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
- if (annotation_set == nullptr) {
- return false;
- }
- const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
- klass, annotation_set, kDexVisibilityRuntime, annotation_class);
- return annotation_item != nullptr;
-}
-
-mirror::Object* DexFile::CreateAnnotationMember(Handle<mirror::Class> klass,
- Handle<mirror::Class> annotation_class, const uint8_t** annotation) const {
- Thread* self = Thread::Current();
- ScopedObjectAccessUnchecked soa(self);
- StackHandleScope<5> hs(self);
- uint32_t element_name_index = DecodeUnsignedLeb128(annotation);
- const char* name = StringDataByIdx(element_name_index);
- Handle<mirror::String> string_name(
- hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name)));
-
- PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- ArtMethod* annotation_method =
- annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size);
- if (annotation_method == nullptr) {
- return nullptr;
- }
- Handle<mirror::Class> method_return(hs.NewHandle(
- annotation_method->GetReturnType(true /* resolve */, pointer_size)));
-
- AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return, kAllObjects)) {
- return nullptr;
- }
- Handle<mirror::Object> value_object(hs.NewHandle(annotation_value.value_.GetL()));
-
- mirror::Class* annotation_member_class =
- WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember);
- Handle<mirror::Object> new_member(hs.NewHandle(annotation_member_class->AllocObject(self)));
- mirror::Method* method_obj_ptr;
- DCHECK(!Runtime::Current()->IsActiveTransaction());
- if (pointer_size == PointerSize::k64) {
- method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k64, false>(
- self, annotation_method);
- } else {
- method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k32, false>(
- self, annotation_method);
- }
- Handle<mirror::Method> method_object(hs.NewHandle(method_obj_ptr));
-
- if (new_member.Get() == nullptr || string_name.Get() == nullptr ||
- method_object.Get() == nullptr || method_return.Get() == nullptr) {
- LOG(ERROR) << StringPrintf("Failed creating annotation element (m=%p n=%p a=%p r=%p",
- new_member.Get(), string_name.Get(), method_object.Get(), method_return.Get());
- return nullptr;
- }
-
- JValue result;
- ArtMethod* annotation_member_init =
- soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationMember_init);
- uint32_t args[5] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(new_member.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(string_name.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(value_object.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_return.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_object.Get()))
- };
- annotation_member_init->Invoke(self, args, sizeof(args), &result, "VLLLL");
- if (self->IsExceptionPending()) {
- LOG(INFO) << "Exception in AnnotationMember.<init>";
- return nullptr;
- }
-
- return new_member.Get();
-}
-
-const DexFile::AnnotationItem* DexFile::GetAnnotationItemFromAnnotationSet(
- Handle<mirror::Class> klass, const AnnotationSetItem* annotation_set, uint32_t visibility,
- Handle<mirror::Class> annotation_class) const {
- for (uint32_t i = 0; i < annotation_set->size_; ++i) {
- const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i);
- if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
- continue;
- }
- const uint8_t* annotation = annotation_item->annotation_;
- uint32_t type_index = DecodeUnsignedLeb128(&annotation);
- mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType(
- klass->GetDexFile(), type_index, klass.Get());
- if (resolved_class == nullptr) {
- std::string temp;
- LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
- klass->GetDescriptor(&temp), type_index);
- CHECK(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
- continue;
- }
- if (resolved_class == annotation_class.Get()) {
- return annotation_item;
- }
- }
-
- return nullptr;
-}
-
-mirror::Object* DexFile::GetAnnotationObjectFromAnnotationSet(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set, uint32_t visibility,
- Handle<mirror::Class> annotation_class) const {
- const AnnotationItem* annotation_item =
- GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- const uint8_t* annotation = annotation_item->annotation_;
- return ProcessEncodedAnnotation(klass, &annotation);
-}
-
-mirror::Object* DexFile::GetAnnotationValue(Handle<mirror::Class> klass,
- const AnnotationItem* annotation_item, const char* annotation_name,
- Handle<mirror::Class> array_class, uint32_t expected_type) const {
- const uint8_t* annotation =
- SearchEncodedAnnotation(annotation_item->annotation_, annotation_name);
- if (annotation == nullptr) {
- return nullptr;
- }
- AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class, kAllObjects)) {
- return nullptr;
- }
- if (annotation_value.type_ != expected_type) {
- return nullptr;
- }
- return annotation_value.value_.GetL();
-}
-
-mirror::ObjectArray<mirror::String>* DexFile::GetSignatureValue(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set) const {
- StackHandleScope<1> hs(Thread::Current());
- const AnnotationItem* annotation_item =
- SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Signature;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- 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.Get() == nullptr) {
- return nullptr;
- }
- mirror::Object* obj =
- GetAnnotationValue(klass, annotation_item, "value", string_array_class, kDexAnnotationArray);
- if (obj == nullptr) {
- return nullptr;
- }
- return obj->AsObjectArray<mirror::String>();
-}
-
-mirror::ObjectArray<mirror::Class>* DexFile::GetThrowsValue(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set) const {
- StackHandleScope<1> hs(Thread::Current());
- const AnnotationItem* annotation_item =
- SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Throws;", kDexVisibilitySystem);
- if (annotation_item == nullptr) {
- return nullptr;
- }
- 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.Get() == nullptr) {
- return nullptr;
- }
- mirror::Object* obj =
- GetAnnotationValue(klass, annotation_item, "value", class_array_class, kDexAnnotationArray);
- if (obj == nullptr) {
- return nullptr;
- }
- return obj->AsObjectArray<mirror::Class>();
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::ProcessAnnotationSet(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set, uint32_t visibility) const {
- Thread* self = Thread::Current();
- ScopedObjectAccessUnchecked soa(self);
- StackHandleScope<2> hs(self);
- Handle<mirror::Class> annotation_array_class(hs.NewHandle(
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array)));
- if (annotation_set == nullptr) {
- return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), 0);
- }
-
- uint32_t size = annotation_set->size_;
- Handle<mirror::ObjectArray<mirror::Object>> result(hs.NewHandle(
- mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), size)));
- if (result.Get() == nullptr) {
- return nullptr;
- }
-
- uint32_t dest_index = 0;
- for (uint32_t i = 0; i < size; ++i) {
- const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i);
- // Note that we do not use IsVisibilityCompatible here because older code
- // was correct for this case.
- if (annotation_item->visibility_ != visibility) {
- continue;
- }
- const uint8_t* annotation = annotation_item->annotation_;
- mirror::Object* annotation_obj = ProcessEncodedAnnotation(klass, &annotation);
- if (annotation_obj != nullptr) {
- result->SetWithoutChecks<false>(dest_index, annotation_obj);
- ++dest_index;
- } else if (self->IsExceptionPending()) {
- return nullptr;
- }
- }
-
- if (dest_index == size) {
- return result.Get();
- }
-
- mirror::ObjectArray<mirror::Object>* trimmed_result =
- mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index);
- if (trimmed_result == nullptr) {
- return nullptr;
- }
-
- for (uint32_t i = 0; i < dest_index; ++i) {
- mirror::Object* obj = result->GetWithoutChecks(i);
- trimmed_result->SetWithoutChecks<false>(i, obj);
- }
-
- return trimmed_result;
-}
-
-mirror::ObjectArray<mirror::Object>* DexFile::ProcessAnnotationSetRefList(
- Handle<mirror::Class> klass, const AnnotationSetRefList* set_ref_list, uint32_t size) const {
- Thread* self = Thread::Current();
- ScopedObjectAccessUnchecked soa(self);
- StackHandleScope<1> hs(self);
- mirror::Class* annotation_array_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
- mirror::Class* annotation_array_array_class =
- Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
- if (annotation_array_array_class == nullptr) {
- return nullptr;
- }
- Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle(
- mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size)));
- if (annotation_array_array.Get() == nullptr) {
- LOG(ERROR) << "Annotation set ref array allocation failed";
- return nullptr;
- }
- for (uint32_t index = 0; index < size; ++index) {
- const AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index];
- const AnnotationSetItem* set_item = GetSetRefItemItem(set_ref_item);
- mirror::Object* annotation_set = ProcessAnnotationSet(klass, set_item, kDexVisibilityRuntime);
- if (annotation_set == nullptr) {
- return nullptr;
- }
- annotation_array_array->SetWithoutChecks<false>(index, annotation_set);
- }
- return annotation_array_array.Get();
-}
-
-bool DexFile::ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr,
- AnnotationValue* annotation_value, Handle<mirror::Class> array_class,
- DexFile::AnnotationResultStyle result_style) const {
- Thread* self = Thread::Current();
- mirror::Object* element_object = nullptr;
- bool set_object = false;
- Primitive::Type primitive_type = Primitive::kPrimVoid;
- const uint8_t* annotation = *annotation_ptr;
- uint8_t header_byte = *(annotation++);
- uint8_t value_type = header_byte & kDexAnnotationValueTypeMask;
- uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift;
- int32_t width = value_arg + 1;
- annotation_value->type_ = value_type;
-
- switch (value_type) {
- case kDexAnnotationByte:
- annotation_value->value_.SetB(static_cast<int8_t>(ReadSignedInt(annotation, value_arg)));
- primitive_type = Primitive::kPrimByte;
- break;
- case kDexAnnotationShort:
- annotation_value->value_.SetS(static_cast<int16_t>(ReadSignedInt(annotation, value_arg)));
- primitive_type = Primitive::kPrimShort;
- break;
- case kDexAnnotationChar:
- annotation_value->value_.SetC(static_cast<uint16_t>(ReadUnsignedInt(annotation, value_arg,
- false)));
- primitive_type = Primitive::kPrimChar;
- break;
- case kDexAnnotationInt:
- annotation_value->value_.SetI(ReadSignedInt(annotation, value_arg));
- primitive_type = Primitive::kPrimInt;
- break;
- case kDexAnnotationLong:
- annotation_value->value_.SetJ(ReadSignedLong(annotation, value_arg));
- primitive_type = Primitive::kPrimLong;
- break;
- case kDexAnnotationFloat:
- annotation_value->value_.SetI(ReadUnsignedInt(annotation, value_arg, true));
- primitive_type = Primitive::kPrimFloat;
- break;
- case kDexAnnotationDouble:
- annotation_value->value_.SetJ(ReadUnsignedLong(annotation, value_arg, true));
- primitive_type = Primitive::kPrimDouble;
- break;
- case kDexAnnotationBoolean:
- annotation_value->value_.SetZ(value_arg != 0);
- primitive_type = Primitive::kPrimBoolean;
- width = 0;
- break;
- case kDexAnnotationString: {
- uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(index);
- } else {
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- element_object = Runtime::Current()->GetClassLinker()->ResolveString(
- klass->GetDexFile(), index, dex_cache);
- set_object = true;
- if (element_object == nullptr) {
- return false;
- }
- }
- break;
- }
- case kDexAnnotationType: {
- uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(index);
- } else {
- element_object = Runtime::Current()->GetClassLinker()->ResolveType(
- klass->GetDexFile(), index, klass.Get());
- set_object = true;
- if (element_object == nullptr) {
- CHECK(self->IsExceptionPending());
- if (result_style == kAllObjects) {
- const char* msg = StringByTypeIdx(index);
- self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
- element_object = self->GetException();
- self->ClearException();
- } else {
- return false;
- }
- }
- }
- break;
- }
- case kDexAnnotationMethod: {
- uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(index);
- } else {
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType(
- klass->GetDexFile(), index, dex_cache, class_loader);
- if (method == nullptr) {
- return false;
- }
- PointerSize pointer_size = class_linker->GetImagePointerSize();
- set_object = true;
- DCHECK(!Runtime::Current()->IsActiveTransaction());
- if (method->IsConstructor()) {
- if (pointer_size == PointerSize::k64) {
- element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k64,
- false>(self, method);
- } else {
- element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k32,
- false>(self, method);
- }
- } else {
- if (pointer_size == PointerSize::k64) {
- element_object = mirror::Method::CreateFromArtMethod<PointerSize::k64,
- false>(self, method);
- } else {
- element_object = mirror::Method::CreateFromArtMethod<PointerSize::k32,
- false>(self, method);
- }
- }
- if (element_object == nullptr) {
- return false;
- }
- }
- break;
- }
- case kDexAnnotationField: {
- uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(index);
- } else {
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(
- klass->GetDexFile(), index, dex_cache, class_loader);
- if (field == nullptr) {
- return false;
- }
- set_object = true;
- PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- if (pointer_size == PointerSize::k64) {
- element_object = mirror::Field::CreateFromArtField<PointerSize::k64>(self, field, true);
- } else {
- element_object = mirror::Field::CreateFromArtField<PointerSize::k32>(self, field, true);
- }
- if (element_object == nullptr) {
- return false;
- }
- }
- break;
- }
- case kDexAnnotationEnum: {
- uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(index);
- } else {
- StackHandleScope<3> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField(
- klass->GetDexFile(), index, dex_cache, class_loader, true);
- if (enum_field == nullptr) {
- return false;
- } else {
- Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass()));
- Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true);
- element_object = enum_field->GetObject(field_class.Get());
- set_object = true;
- }
- }
- break;
- }
- case kDexAnnotationArray:
- if (result_style == kAllRaw || array_class.Get() == nullptr) {
- return false;
- } else {
- ScopedObjectAccessUnchecked soa(self);
- StackHandleScope<2> hs(self);
- uint32_t size = DecodeUnsignedLeb128(&annotation);
- Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType()));
- Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc<true>(
- self, array_class.Get(), size, array_class->GetComponentSizeShift(),
- Runtime::Current()->GetHeap()->GetCurrentAllocator())));
- if (new_array.Get() == nullptr) {
- LOG(ERROR) << "Annotation element array allocation failed with size " << size;
- return false;
- }
- AnnotationValue new_annotation_value;
- for (uint32_t i = 0; i < size; ++i) {
- if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, component_type,
- kPrimitivesOrObjects)) {
- return false;
- }
- if (!component_type->IsPrimitive()) {
- mirror::Object* obj = new_annotation_value.value_.GetL();
- new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
- } else {
- switch (new_annotation_value.type_) {
- case kDexAnnotationByte:
- new_array->AsByteArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetB());
- break;
- case kDexAnnotationShort:
- new_array->AsShortArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetS());
- break;
- case kDexAnnotationChar:
- new_array->AsCharArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetC());
- break;
- case kDexAnnotationInt:
- new_array->AsIntArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetI());
- break;
- case kDexAnnotationLong:
- new_array->AsLongArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetJ());
- break;
- case kDexAnnotationFloat:
- new_array->AsFloatArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetF());
- break;
- case kDexAnnotationDouble:
- new_array->AsDoubleArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetD());
- break;
- case kDexAnnotationBoolean:
- new_array->AsBooleanArray()->SetWithoutChecks<false>(
- i, new_annotation_value.value_.GetZ());
- break;
- default:
- LOG(FATAL) << "Found invalid annotation value type while building annotation array";
- return false;
- }
- }
- }
- element_object = new_array.Get();
- set_object = true;
- width = 0;
- }
- break;
- case kDexAnnotationAnnotation:
- if (result_style == kAllRaw) {
- return false;
- }
- element_object = ProcessEncodedAnnotation(klass, &annotation);
- if (element_object == nullptr) {
- return false;
- }
- set_object = true;
- width = 0;
- break;
- case kDexAnnotationNull:
- if (result_style == kAllRaw) {
- annotation_value->value_.SetI(0);
- } else {
- CHECK(element_object == nullptr);
- set_object = true;
- }
- width = 0;
- break;
- default:
- LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type);
- return false;
- }
-
- annotation += width;
- *annotation_ptr = annotation;
-
- if (result_style == kAllObjects && primitive_type != Primitive::kPrimVoid) {
- element_object = BoxPrimitive(primitive_type, annotation_value->value_);
- set_object = true;
- }
-
- if (set_object) {
- annotation_value->value_.SetL(element_object);
- }
-
- return true;
-}
-
-mirror::Object* DexFile::ProcessEncodedAnnotation(Handle<mirror::Class> klass,
- const uint8_t** annotation) const {
- uint32_t type_index = DecodeUnsignedLeb128(annotation);
- uint32_t size = DecodeUnsignedLeb128(annotation);
-
- Thread* self = Thread::Current();
- ScopedObjectAccessUnchecked soa(self);
- StackHandleScope<2> hs(self);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Handle<mirror::Class> annotation_class(hs.NewHandle(
- class_linker->ResolveType(klass->GetDexFile(), type_index, klass.Get())));
- if (annotation_class.Get() == nullptr) {
- LOG(INFO) << "Unable to resolve " << PrettyClass(klass.Get()) << " annotation class "
- << type_index;
- DCHECK(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
- return nullptr;
- }
-
- mirror::Class* annotation_member_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::libcore_reflect_AnnotationMember);
- mirror::Class* annotation_member_array_class =
- class_linker->FindArrayClass(self, &annotation_member_class);
- if (annotation_member_array_class == nullptr) {
- return nullptr;
- }
- mirror::ObjectArray<mirror::Object>* element_array = nullptr;
- if (size > 0) {
- element_array =
- mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size);
- if (element_array == nullptr) {
- LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)";
- return nullptr;
- }
- }
-
- Handle<mirror::ObjectArray<mirror::Object>> h_element_array(hs.NewHandle(element_array));
- for (uint32_t i = 0; i < size; ++i) {
- mirror::Object* new_member = CreateAnnotationMember(klass, annotation_class, annotation);
- if (new_member == nullptr) {
- return nullptr;
- }
- h_element_array->SetWithoutChecks<false>(i, new_member);
- }
-
- JValue result;
- ArtMethod* create_annotation_method =
- soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation);
- uint32_t args[2] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(annotation_class.Get())),
- static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_element_array.Get())) };
- create_annotation_method->Invoke(self, args, sizeof(args), &result, "LLL");
- if (self->IsExceptionPending()) {
- LOG(INFO) << "Exception in AnnotationFactory.createAnnotation";
- return nullptr;
- }
-
- return result.GetL();
-}
-
-const DexFile::AnnotationItem* DexFile::SearchAnnotationSet(const AnnotationSetItem* annotation_set,
- const char* descriptor, uint32_t visibility) const {
- const AnnotationItem* result = nullptr;
- for (uint32_t i = 0; i < annotation_set->size_; ++i) {
- const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i);
- if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
- continue;
- }
- const uint8_t* annotation = annotation_item->annotation_;
- uint32_t type_index = DecodeUnsignedLeb128(&annotation);
-
- if (strcmp(descriptor, StringByTypeIdx(type_index)) == 0) {
- result = annotation_item;
- break;
- }
- }
- return result;
-}
-
-const uint8_t* DexFile::SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const {
- DecodeUnsignedLeb128(&annotation); // unused type_index
- uint32_t size = DecodeUnsignedLeb128(&annotation);
-
- while (size != 0) {
- uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
- const char* element_name = GetStringData(GetStringId(element_name_index));
- if (strcmp(name, element_name) == 0) {
- return annotation;
- }
- SkipAnnotationValue(&annotation);
- size--;
- }
- return nullptr;
-}
-
-bool DexFile::SkipAnnotationValue(const uint8_t** annotation_ptr) const {
- const uint8_t* annotation = *annotation_ptr;
- uint8_t header_byte = *(annotation++);
- uint8_t value_type = header_byte & kDexAnnotationValueTypeMask;
- uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift;
- int32_t width = value_arg + 1;
-
- switch (value_type) {
- case kDexAnnotationByte:
- case kDexAnnotationShort:
- case kDexAnnotationChar:
- case kDexAnnotationInt:
- case kDexAnnotationLong:
- case kDexAnnotationFloat:
- case kDexAnnotationDouble:
- case kDexAnnotationString:
- case kDexAnnotationType:
- case kDexAnnotationMethod:
- case kDexAnnotationField:
- case kDexAnnotationEnum:
- break;
- case kDexAnnotationArray:
- {
- uint32_t size = DecodeUnsignedLeb128(&annotation);
- while (size--) {
- if (!SkipAnnotationValue(&annotation)) {
- return false;
- }
- }
- width = 0;
- break;
- }
- case kDexAnnotationAnnotation:
- {
- DecodeUnsignedLeb128(&annotation); // unused type_index
- uint32_t size = DecodeUnsignedLeb128(&annotation);
- while (size--) {
- DecodeUnsignedLeb128(&annotation); // unused element_name_index
- if (!SkipAnnotationValue(&annotation)) {
- return false;
- }
- }
- width = 0;
- break;
- }
- case kDexAnnotationBoolean:
- case kDexAnnotationNull:
- width = 0;
- break;
- default:
- LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type);
- return false;
- }
-
- annotation += width;
- *annotation_ptr = annotation;
- return true;
-}
-
std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) {
os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]",
dex_file.GetLocation().c_str(),
@@ -2460,50 +1292,13 @@ void ClassDataItemIterator::ReadClassDataMethod() {
}
}
-EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(
- const DexFile& dex_file,
- const DexFile::ClassDef& class_def)
- : EncodedStaticFieldValueIterator(dex_file,
- nullptr,
- nullptr,
- nullptr,
- class_def,
- -1,
- kByte) {
-}
-
-EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(
- const DexFile& dex_file,
- Handle<mirror::DexCache>* dex_cache,
- Handle<mirror::ClassLoader>* class_loader,
- ClassLinker* linker,
- const DexFile::ClassDef& class_def)
- : EncodedStaticFieldValueIterator(dex_file,
- dex_cache, class_loader,
- linker,
- class_def,
- -1,
- kByte) {
- DCHECK(dex_cache_ != nullptr);
- DCHECK(class_loader_ != nullptr);
-}
-
-EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(
- const DexFile& dex_file,
- Handle<mirror::DexCache>* dex_cache,
- Handle<mirror::ClassLoader>* class_loader,
- ClassLinker* linker,
- const DexFile::ClassDef& class_def,
- size_t pos,
- ValueType type)
+EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def)
: dex_file_(dex_file),
- dex_cache_(dex_cache),
- class_loader_(class_loader),
- linker_(linker),
array_size_(),
- pos_(pos),
- type_(type) {
- ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
+ pos_(-1),
+ type_(kByte) {
+ ptr_ = dex_file_.GetEncodedStaticFieldValuesArray(class_def);
if (ptr_ == nullptr) {
array_size_ = 0;
} else {
@@ -2529,32 +1324,32 @@ void EncodedStaticFieldValueIterator::Next() {
width = 0;
break;
case kByte:
- jval_.i = ReadSignedInt(ptr_, value_arg);
+ jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
CHECK(IsInt<8>(jval_.i));
break;
case kShort:
- jval_.i = ReadSignedInt(ptr_, value_arg);
+ jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
CHECK(IsInt<16>(jval_.i));
break;
case kChar:
- jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+ jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
CHECK(IsUint<16>(jval_.i));
break;
case kInt:
- jval_.i = ReadSignedInt(ptr_, value_arg);
+ jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
break;
case kLong:
- jval_.j = ReadSignedLong(ptr_, value_arg);
+ jval_.j = DexFile::ReadSignedLong(ptr_, value_arg);
break;
case kFloat:
- jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
+ jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true);
break;
case kDouble:
- jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
+ jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true);
break;
case kString:
case kType:
- jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+ jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
break;
case kField:
case kMethod:
@@ -2574,38 +1369,6 @@ void EncodedStaticFieldValueIterator::Next() {
ptr_ += width;
}
-template<bool kTransactionActive>
-void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const {
- DCHECK(dex_cache_ != nullptr);
- DCHECK(class_loader_ != nullptr);
- switch (type_) {
- case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z);
- break;
- case kByte: field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
- case kShort: field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break;
- case kChar: field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break;
- case kInt: field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break;
- case kLong: field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break;
- case kFloat: field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break;
- case kDouble: field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
- case kNull: field->SetObject<kTransactionActive>(field->GetDeclaringClass(), nullptr); break;
- case kString: {
- mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_);
- field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
- break;
- }
- case kType: {
- mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_,
- *class_loader_);
- field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
- break;
- }
- default: UNIMPLEMENTED(FATAL) << ": type " << type_;
- }
-}
-template void EncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const;
-template void EncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* field) const;
-
CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
handler_.address_ = -1;
int32_t offset = -1;
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 23676bdbf7..0ae36f78b5 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -27,27 +27,14 @@
#include "globals.h"
#include "invoke_type.h"
#include "jni.h"
-#include "mirror/object_array.h"
#include "modifiers.h"
#include "utf.h"
namespace art {
-// TODO: remove dependencies on mirror classes, primarily by moving
-// EncodedStaticFieldValueIterator to its own file.
-namespace mirror {
- class ClassLoader;
- class DexCache;
-} // namespace mirror
-class ArtField;
-class ArtMethod;
-class ClassLinker;
-template <class Key, class Value, class EmptyFn, class HashFn, class Pred, class Alloc>
-class HashMap;
class MemMap;
class OatDexFile;
class Signature;
-template<class T> class Handle;
class StringPiece;
class TypeLookupTable;
class ZipArchive;
@@ -402,6 +389,8 @@ class DexFile {
kAllRaw
};
+ struct AnnotationValue;
+
// Returns the checksum of a file for comparison with GetLocationChecksum().
// For .dex files, this is the header checksum.
// For zip files, this is the classes.dex zip entry CRC32 checksum.
@@ -934,110 +923,6 @@ class DexFile {
return reinterpret_cast<const AnnotationSetItem*>(begin_ + offset);
}
- const AnnotationSetItem* FindAnnotationSetForField(ArtField* field) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> annotation_class)
- const REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class)
- const REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method,
- uint32_t parameter_idx,
- Handle<mirror::Class> annotation_class) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsMethodAnnotationPresent(ArtMethod* method,
- Handle<mirror::Class> annotation_class,
- uint32_t visibility = kDexVisibilityRuntime) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- const AnnotationSetItem* FindAnnotationSetForClass(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass,
- Handle<mirror::Class> annotation_class) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass)
- const REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class)
- const REQUIRES_SHARED(Locks::mutator_lock_);
-
- mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass,
- Handle<mirror::Class> annotation_class,
- const uint8_t** annotation) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- const AnnotationItem* GetAnnotationItemFromAnnotationSet(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set,
- uint32_t visibility,
- Handle<mirror::Class> annotation_class)
- const REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationObjectFromAnnotationSet(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set,
- uint32_t visibility,
- Handle<mirror::Class> annotation_class) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* GetAnnotationValue(Handle<mirror::Class> klass,
- const AnnotationItem* annotation_item,
- const char* annotation_name,
- Handle<mirror::Class> array_class,
- uint32_t expected_type) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::String>* GetSignatureValue(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set)
- const REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Class>* GetThrowsValue(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet(Handle<mirror::Class> klass,
- const AnnotationSetItem* annotation_set,
- uint32_t visibility) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Object>* ProcessAnnotationSetRefList(Handle<mirror::Class> klass,
- const AnnotationSetRefList* set_ref_list, uint32_t size) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Object* ProcessEncodedAnnotation(Handle<mirror::Class> klass,
- const uint8_t** annotation) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- const AnnotationItem* SearchAnnotationSet(const AnnotationSetItem* annotation_set,
- const char* descriptor, uint32_t visibility) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- const uint8_t* SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool SkipAnnotationValue(const uint8_t** annotation_ptr) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Debug info opcodes and constants
enum {
DBG_END_SEQUENCE = 0x00,
@@ -1064,17 +949,6 @@ class DexFile {
DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
};
- // Determine the source file line number based on the program counter.
- // "pc" is an offset, in 16-bit units, from the start of the method's code.
- //
- // Returns -1 if no match was found (possibly because the source files were
- // compiled without "-g", so no line number information is present).
- // Returns -2 for native methods (as expected in exception traces).
- //
- // This is used by runtime; therefore use art::Method not art::DexFile::Method.
- int32_t GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Returns false if there is no debugging information or if it cannot be decoded.
bool DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
DexDebugNewLocalCb local_cb, void* context) const;
@@ -1140,6 +1014,12 @@ class DexFile {
void CreateTypeLookupTable(uint8_t* storage = nullptr) const;
+ // Utility methods for reading integral values from a buffer.
+ static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth);
+ static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right);
+ static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth);
+ static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right);
+
private:
// Opens a .dex file
static std::unique_ptr<const DexFile> OpenFile(int fd,
@@ -1204,13 +1084,6 @@ class DexFile {
// whether the string contains the separator character.
static bool IsMultiDexLocation(const char* location);
- struct AnnotationValue;
-
- bool ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr,
- AnnotationValue* annotation_value, Handle<mirror::Class> return_class,
- DexFile::AnnotationResultStyle result_style) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// The base address of the memory mapping.
const uint8_t* const begin_;
@@ -1514,22 +1387,9 @@ class ClassDataItemIterator {
class EncodedStaticFieldValueIterator {
public:
- // A constructor for static tools. You cannot call
- // ReadValueToField() for an object created by this.
EncodedStaticFieldValueIterator(const DexFile& dex_file,
const DexFile::ClassDef& class_def);
- // A constructor meant to be called from runtime code.
- EncodedStaticFieldValueIterator(const DexFile& dex_file,
- Handle<mirror::DexCache>* dex_cache,
- Handle<mirror::ClassLoader>* class_loader,
- ClassLinker* linker,
- const DexFile::ClassDef& class_def)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- template<bool kTransactionActive>
- void ReadValueToField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_);
-
bool HasNext() const { return pos_ < array_size_; }
void Next();
@@ -1556,27 +1416,18 @@ class EncodedStaticFieldValueIterator {
ValueType GetValueType() const { return type_; }
const jvalue& GetJavaValue() const { return jval_; }
- private:
- EncodedStaticFieldValueIterator(const DexFile& dex_file,
- Handle<mirror::DexCache>* dex_cache,
- Handle<mirror::ClassLoader>* class_loader,
- ClassLinker* linker,
- const DexFile::ClassDef& class_def,
- size_t pos,
- ValueType type);
-
+ protected:
static constexpr uint8_t kEncodedValueTypeMask = 0x1f; // 0b11111
static constexpr uint8_t kEncodedValueArgShift = 5;
const DexFile& dex_file_;
- Handle<mirror::DexCache>* const dex_cache_; // Dex cache to resolve literal objects.
- Handle<mirror::ClassLoader>* const class_loader_; // ClassLoader to resolve types.
- ClassLinker* linker_; // Linker to resolve literal objects.
size_t array_size_; // Size of array.
size_t pos_; // Current position.
const uint8_t* ptr_; // Pointer into encoded data array.
ValueType type_; // Type of current encoded value.
jvalue jval_; // Value of current encoded value.
+
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
};
std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code);
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
new file mode 100644
index 0000000000..c6c87fdf36
--- /dev/null
+++ b/runtime/dex_file_annotations.cc
@@ -0,0 +1,1303 @@
+/*
+ * 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 "dex_file_annotations.h"
+
+#include <stdlib.h>
+
+#include "art_field-inl.h"
+#include "art_method-inl.h"
+#include "class_linker-inl.h"
+#include "dex_file-inl.h"
+#include "jvalue.h"
+#include "mirror/field.h"
+#include "mirror/method.h"
+#include "reflection.h"
+#include "thread.h"
+
+namespace art {
+
+struct DexFile::AnnotationValue {
+ JValue value_;
+ uint8_t type_;
+};
+
+namespace {
+mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass,
+ Handle<mirror::Class> annotation_class,
+ const uint8_t** annotation)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) {
+ if (expected == DexFile::kDexVisibilityRuntime) {
+ int32_t sdk_version = Runtime::Current()->GetTargetSdkVersion();
+ if (sdk_version > 0 && sdk_version <= 23) {
+ return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild;
+ }
+ }
+ return actual == expected;
+}
+
+const DexFile::AnnotationSetItem* FindAnnotationSetForField(ArtField* field)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile* dex_file = field->GetDexFile();
+ mirror::Class* klass = field->GetDeclaringClass();
+ const DexFile::AnnotationsDirectoryItem* annotations_dir =
+ dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+ if (annotations_dir == nullptr) {
+ return nullptr;
+ }
+ const DexFile::FieldAnnotationsItem* field_annotations =
+ dex_file->GetFieldAnnotations(annotations_dir);
+ if (field_annotations == nullptr) {
+ return nullptr;
+ }
+ uint32_t field_index = field->GetDexFieldIndex();
+ uint32_t field_count = annotations_dir->fields_size_;
+ for (uint32_t i = 0; i < field_count; ++i) {
+ if (field_annotations[i].field_idx_ == field_index) {
+ return dex_file->GetFieldAnnotationSetItem(field_annotations[i]);
+ }
+ }
+ return nullptr;
+}
+
+const DexFile::AnnotationItem* SearchAnnotationSet(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem* annotation_set,
+ const char* descriptor,
+ uint32_t visibility)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile::AnnotationItem* result = nullptr;
+ for (uint32_t i = 0; i < annotation_set->size_; ++i) {
+ const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
+ if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
+ continue;
+ }
+ const uint8_t* annotation = annotation_item->annotation_;
+ uint32_t type_index = DecodeUnsignedLeb128(&annotation);
+
+ if (strcmp(descriptor, dex_file.StringByTypeIdx(type_index)) == 0) {
+ result = annotation_item;
+ break;
+ }
+ }
+ return result;
+}
+
+bool SkipAnnotationValue(const DexFile& dex_file, const uint8_t** annotation_ptr)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const uint8_t* annotation = *annotation_ptr;
+ uint8_t header_byte = *(annotation++);
+ uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
+ uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
+ int32_t width = value_arg + 1;
+
+ switch (value_type) {
+ case DexFile::kDexAnnotationByte:
+ case DexFile::kDexAnnotationShort:
+ case DexFile::kDexAnnotationChar:
+ case DexFile::kDexAnnotationInt:
+ case DexFile::kDexAnnotationLong:
+ case DexFile::kDexAnnotationFloat:
+ case DexFile::kDexAnnotationDouble:
+ case DexFile::kDexAnnotationString:
+ case DexFile::kDexAnnotationType:
+ case DexFile::kDexAnnotationMethod:
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum:
+ break;
+ case DexFile::kDexAnnotationArray:
+ {
+ uint32_t size = DecodeUnsignedLeb128(&annotation);
+ while (size--) {
+ if (!SkipAnnotationValue(dex_file, &annotation)) {
+ return false;
+ }
+ }
+ width = 0;
+ break;
+ }
+ case DexFile::kDexAnnotationAnnotation:
+ {
+ DecodeUnsignedLeb128(&annotation); // unused type_index
+ uint32_t size = DecodeUnsignedLeb128(&annotation);
+ while (size--) {
+ DecodeUnsignedLeb128(&annotation); // unused element_name_index
+ if (!SkipAnnotationValue(dex_file, &annotation)) {
+ return false;
+ }
+ }
+ width = 0;
+ break;
+ }
+ case DexFile::kDexAnnotationBoolean:
+ case DexFile::kDexAnnotationNull:
+ width = 0;
+ break;
+ default:
+ LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type);
+ return false;
+ }
+
+ annotation += width;
+ *annotation_ptr = annotation;
+ return true;
+}
+
+const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file,
+ const uint8_t* annotation,
+ const char* name)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DecodeUnsignedLeb128(&annotation); // unused type_index
+ uint32_t size = DecodeUnsignedLeb128(&annotation);
+
+ while (size != 0) {
+ uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
+ const char* element_name = dex_file.GetStringData(dex_file.GetStringId(element_name_index));
+ if (strcmp(name, element_name) == 0) {
+ return annotation;
+ }
+ SkipAnnotationValue(dex_file, &annotation);
+ size--;
+ }
+ return nullptr;
+}
+
+const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile* dex_file = method->GetDexFile();
+ mirror::Class* klass = method->GetDeclaringClass();
+ const DexFile::AnnotationsDirectoryItem* annotations_dir =
+ dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+ if (annotations_dir == nullptr) {
+ return nullptr;
+ }
+ const DexFile::MethodAnnotationsItem* method_annotations =
+ dex_file->GetMethodAnnotations(annotations_dir);
+ if (method_annotations == nullptr) {
+ return nullptr;
+ }
+ uint32_t method_index = method->GetDexMethodIndex();
+ uint32_t method_count = annotations_dir->methods_size_;
+ for (uint32_t i = 0; i < method_count; ++i) {
+ if (method_annotations[i].method_idx_ == method_index) {
+ return dex_file->GetMethodAnnotationSetItem(method_annotations[i]);
+ }
+ }
+ return nullptr;
+}
+
+const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile* dex_file = method->GetDexFile();
+ mirror::Class* klass = method->GetDeclaringClass();
+ const DexFile::AnnotationsDirectoryItem* annotations_dir =
+ dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+ if (annotations_dir == nullptr) {
+ return nullptr;
+ }
+ const DexFile::ParameterAnnotationsItem* parameter_annotations =
+ dex_file->GetParameterAnnotations(annotations_dir);
+ if (parameter_annotations == nullptr) {
+ return nullptr;
+ }
+ uint32_t method_index = method->GetDexMethodIndex();
+ uint32_t parameter_count = annotations_dir->parameters_size_;
+ for (uint32_t i = 0; i < parameter_count; ++i) {
+ if (parameter_annotations[i].method_idx_ == method_index) {
+ return &parameter_annotations[i];
+ }
+ }
+ return nullptr;
+}
+
+const DexFile::AnnotationSetItem* FindAnnotationSetForClass(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationsDirectoryItem* annotations_dir =
+ dex_file.GetAnnotationsDirectory(*klass->GetClassDef());
+ if (annotations_dir == nullptr) {
+ return nullptr;
+ }
+ return dex_file.GetClassAnnotationSet(annotations_dir);
+}
+
+mirror::Object* ProcessEncodedAnnotation(Handle<mirror::Class> klass, const uint8_t** annotation)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t type_index = DecodeUnsignedLeb128(annotation);
+ uint32_t size = DecodeUnsignedLeb128(annotation);
+
+ Thread* self = Thread::Current();
+ ScopedObjectAccessUnchecked soa(self);
+ StackHandleScope<2> hs(self);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::Class> annotation_class(hs.NewHandle(
+ class_linker->ResolveType(klass->GetDexFile(), type_index, klass.Get())));
+ if (annotation_class.Get() == nullptr) {
+ LOG(INFO) << "Unable to resolve " << PrettyClass(klass.Get()) << " annotation class "
+ << type_index;
+ DCHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ return nullptr;
+ }
+
+ mirror::Class* annotation_member_class =
+ soa.Decode<mirror::Class*>(WellKnownClasses::libcore_reflect_AnnotationMember);
+ mirror::Class* annotation_member_array_class =
+ class_linker->FindArrayClass(self, &annotation_member_class);
+ if (annotation_member_array_class == nullptr) {
+ return nullptr;
+ }
+ mirror::ObjectArray<mirror::Object>* element_array = nullptr;
+ if (size > 0) {
+ element_array =
+ mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size);
+ if (element_array == nullptr) {
+ LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)";
+ return nullptr;
+ }
+ }
+
+ Handle<mirror::ObjectArray<mirror::Object>> h_element_array(hs.NewHandle(element_array));
+ for (uint32_t i = 0; i < size; ++i) {
+ mirror::Object* new_member = CreateAnnotationMember(klass, annotation_class, annotation);
+ if (new_member == nullptr) {
+ return nullptr;
+ }
+ h_element_array->SetWithoutChecks<false>(i, new_member);
+ }
+
+ JValue result;
+ ArtMethod* create_annotation_method =
+ soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation);
+ uint32_t args[2] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(annotation_class.Get())),
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_element_array.Get())) };
+ create_annotation_method->Invoke(self, args, sizeof(args), &result, "LLL");
+ if (self->IsExceptionPending()) {
+ LOG(INFO) << "Exception in AnnotationFactory.createAnnotation";
+ return nullptr;
+ }
+
+ return result.GetL();
+}
+
+bool ProcessAnnotationValue(Handle<mirror::Class> klass,
+ const uint8_t** annotation_ptr,
+ DexFile::AnnotationValue* annotation_value,
+ Handle<mirror::Class> array_class,
+ DexFile::AnnotationResultStyle result_style)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ Thread* self = Thread::Current();
+ mirror::Object* element_object = nullptr;
+ bool set_object = false;
+ Primitive::Type primitive_type = Primitive::kPrimVoid;
+ const uint8_t* annotation = *annotation_ptr;
+ uint8_t header_byte = *(annotation++);
+ uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
+ uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
+ int32_t width = value_arg + 1;
+ annotation_value->type_ = value_type;
+
+ switch (value_type) {
+ case DexFile::kDexAnnotationByte:
+ annotation_value->value_.SetB(
+ static_cast<int8_t>(DexFile::ReadSignedInt(annotation, value_arg)));
+ primitive_type = Primitive::kPrimByte;
+ break;
+ case DexFile::kDexAnnotationShort:
+ annotation_value->value_.SetS(
+ static_cast<int16_t>(DexFile::ReadSignedInt(annotation, value_arg)));
+ primitive_type = Primitive::kPrimShort;
+ break;
+ case DexFile::kDexAnnotationChar:
+ annotation_value->value_.SetC(
+ static_cast<uint16_t>(DexFile::ReadUnsignedInt(annotation, value_arg, false)));
+ primitive_type = Primitive::kPrimChar;
+ break;
+ case DexFile::kDexAnnotationInt:
+ annotation_value->value_.SetI(DexFile::ReadSignedInt(annotation, value_arg));
+ primitive_type = Primitive::kPrimInt;
+ break;
+ case DexFile::kDexAnnotationLong:
+ annotation_value->value_.SetJ(DexFile::ReadSignedLong(annotation, value_arg));
+ primitive_type = Primitive::kPrimLong;
+ break;
+ case DexFile::kDexAnnotationFloat:
+ annotation_value->value_.SetI(DexFile::ReadUnsignedInt(annotation, value_arg, true));
+ primitive_type = Primitive::kPrimFloat;
+ break;
+ case DexFile::kDexAnnotationDouble:
+ annotation_value->value_.SetJ(DexFile::ReadUnsignedLong(annotation, value_arg, true));
+ primitive_type = Primitive::kPrimDouble;
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ annotation_value->value_.SetZ(value_arg != 0);
+ primitive_type = Primitive::kPrimBoolean;
+ width = 0;
+ break;
+ case DexFile::kDexAnnotationString: {
+ uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(index);
+ } else {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ element_object = Runtime::Current()->GetClassLinker()->ResolveString(
+ klass->GetDexFile(), index, dex_cache);
+ set_object = true;
+ if (element_object == nullptr) {
+ return false;
+ }
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationType: {
+ uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(index);
+ } else {
+ element_object = Runtime::Current()->GetClassLinker()->ResolveType(
+ klass->GetDexFile(), index, klass.Get());
+ set_object = true;
+ if (element_object == nullptr) {
+ CHECK(self->IsExceptionPending());
+ if (result_style == DexFile::kAllObjects) {
+ const char* msg = dex_file.StringByTypeIdx(index);
+ self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
+ element_object = self->GetException();
+ self->ClearException();
+ } else {
+ return false;
+ }
+ }
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationMethod: {
+ uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(index);
+ } else {
+ StackHandleScope<2> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType(
+ klass->GetDexFile(), index, dex_cache, class_loader);
+ if (method == nullptr) {
+ return false;
+ }
+ PointerSize pointer_size = class_linker->GetImagePointerSize();
+ set_object = true;
+ DCHECK(!Runtime::Current()->IsActiveTransaction());
+ if (method->IsConstructor()) {
+ if (pointer_size == PointerSize::k64) {
+ element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k64,
+ false>(self, method);
+ } else {
+ element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k32,
+ false>(self, method);
+ }
+ } else {
+ if (pointer_size == PointerSize::k64) {
+ element_object = mirror::Method::CreateFromArtMethod<PointerSize::k64,
+ false>(self, method);
+ } else {
+ element_object = mirror::Method::CreateFromArtMethod<PointerSize::k32,
+ false>(self, method);
+ }
+ }
+ if (element_object == nullptr) {
+ return false;
+ }
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationField: {
+ uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(index);
+ } else {
+ StackHandleScope<2> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+ ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(
+ klass->GetDexFile(), index, dex_cache, class_loader);
+ if (field == nullptr) {
+ return false;
+ }
+ set_object = true;
+ PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ if (pointer_size == PointerSize::k64) {
+ element_object = mirror::Field::CreateFromArtField<PointerSize::k64>(self, field, true);
+ } else {
+ element_object = mirror::Field::CreateFromArtField<PointerSize::k32>(self, field, true);
+ }
+ if (element_object == nullptr) {
+ return false;
+ }
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationEnum: {
+ uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(index);
+ } else {
+ StackHandleScope<3> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+ ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField(
+ klass->GetDexFile(), index, dex_cache, class_loader, true);
+ if (enum_field == nullptr) {
+ return false;
+ } else {
+ Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass()));
+ Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true);
+ element_object = enum_field->GetObject(field_class.Get());
+ set_object = true;
+ }
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationArray:
+ if (result_style == DexFile::kAllRaw || array_class.Get() == nullptr) {
+ return false;
+ } else {
+ ScopedObjectAccessUnchecked soa(self);
+ StackHandleScope<2> hs(self);
+ uint32_t size = DecodeUnsignedLeb128(&annotation);
+ Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType()));
+ Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc<true>(
+ self, array_class.Get(), size, array_class->GetComponentSizeShift(),
+ Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+ if (new_array.Get() == nullptr) {
+ LOG(ERROR) << "Annotation element array allocation failed with size " << size;
+ return false;
+ }
+ DexFile::AnnotationValue new_annotation_value;
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value,
+ component_type, DexFile::kPrimitivesOrObjects)) {
+ return false;
+ }
+ if (!component_type->IsPrimitive()) {
+ mirror::Object* obj = new_annotation_value.value_.GetL();
+ new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
+ } else {
+ switch (new_annotation_value.type_) {
+ case DexFile::kDexAnnotationByte:
+ new_array->AsByteArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetB());
+ break;
+ case DexFile::kDexAnnotationShort:
+ new_array->AsShortArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetS());
+ break;
+ case DexFile::kDexAnnotationChar:
+ new_array->AsCharArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetC());
+ break;
+ case DexFile::kDexAnnotationInt:
+ new_array->AsIntArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetI());
+ break;
+ case DexFile::kDexAnnotationLong:
+ new_array->AsLongArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetJ());
+ break;
+ case DexFile::kDexAnnotationFloat:
+ new_array->AsFloatArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetF());
+ break;
+ case DexFile::kDexAnnotationDouble:
+ new_array->AsDoubleArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetD());
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ new_array->AsBooleanArray()->SetWithoutChecks<false>(
+ i, new_annotation_value.value_.GetZ());
+ break;
+ default:
+ LOG(FATAL) << "Found invalid annotation value type while building annotation array";
+ return false;
+ }
+ }
+ }
+ element_object = new_array.Get();
+ set_object = true;
+ width = 0;
+ }
+ break;
+ case DexFile::kDexAnnotationAnnotation:
+ if (result_style == DexFile::kAllRaw) {
+ return false;
+ }
+ element_object = ProcessEncodedAnnotation(klass, &annotation);
+ if (element_object == nullptr) {
+ return false;
+ }
+ set_object = true;
+ width = 0;
+ break;
+ case DexFile::kDexAnnotationNull:
+ if (result_style == DexFile::kAllRaw) {
+ annotation_value->value_.SetI(0);
+ } else {
+ CHECK(element_object == nullptr);
+ set_object = true;
+ }
+ width = 0;
+ break;
+ default:
+ LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type);
+ return false;
+ }
+
+ annotation += width;
+ *annotation_ptr = annotation;
+
+ if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) {
+ element_object = BoxPrimitive(primitive_type, annotation_value->value_);
+ set_object = true;
+ }
+
+ if (set_object) {
+ annotation_value->value_.SetL(element_object);
+ }
+
+ return true;
+}
+
+mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass,
+ Handle<mirror::Class> annotation_class,
+ const uint8_t** annotation) {
+ const DexFile& dex_file = klass->GetDexFile();
+ Thread* self = Thread::Current();
+ ScopedObjectAccessUnchecked soa(self);
+ StackHandleScope<5> hs(self);
+ uint32_t element_name_index = DecodeUnsignedLeb128(annotation);
+ const char* name = dex_file.StringDataByIdx(element_name_index);
+ Handle<mirror::String> string_name(
+ hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name)));
+
+ PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ ArtMethod* annotation_method =
+ annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size);
+ if (annotation_method == nullptr) {
+ return nullptr;
+ }
+ Handle<mirror::Class> method_return(hs.NewHandle(
+ annotation_method->GetReturnType(true /* resolve */, pointer_size)));
+
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return,
+ DexFile::kAllObjects)) {
+ return nullptr;
+ }
+ Handle<mirror::Object> value_object(hs.NewHandle(annotation_value.value_.GetL()));
+
+ mirror::Class* annotation_member_class =
+ WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember);
+ Handle<mirror::Object> new_member(hs.NewHandle(annotation_member_class->AllocObject(self)));
+ mirror::Method* method_obj_ptr;
+ DCHECK(!Runtime::Current()->IsActiveTransaction());
+ if (pointer_size == PointerSize::k64) {
+ method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k64, false>(
+ self, annotation_method);
+ } else {
+ method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k32, false>(
+ self, annotation_method);
+ }
+ Handle<mirror::Method> method_object(hs.NewHandle(method_obj_ptr));
+
+ if (new_member.Get() == nullptr || string_name.Get() == nullptr ||
+ method_object.Get() == nullptr || method_return.Get() == nullptr) {
+ LOG(ERROR) << StringPrintf("Failed creating annotation element (m=%p n=%p a=%p r=%p",
+ new_member.Get(), string_name.Get(), method_object.Get(), method_return.Get());
+ return nullptr;
+ }
+
+ JValue result;
+ ArtMethod* annotation_member_init =
+ soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationMember_init);
+ uint32_t args[5] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(new_member.Get())),
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(string_name.Get())),
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(value_object.Get())),
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_return.Get())),
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_object.Get()))
+ };
+ annotation_member_init->Invoke(self, args, sizeof(args), &result, "VLLLL");
+ if (self->IsExceptionPending()) {
+ LOG(INFO) << "Exception in AnnotationMember.<init>";
+ return nullptr;
+ }
+
+ return new_member.Get();
+}
+
+const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet(
+ Handle<mirror::Class> klass,
+ const DexFile::AnnotationSetItem* annotation_set,
+ uint32_t visibility,
+ Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ for (uint32_t i = 0; i < annotation_set->size_; ++i) {
+ const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
+ if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
+ continue;
+ }
+ const uint8_t* annotation = annotation_item->annotation_;
+ uint32_t type_index = DecodeUnsignedLeb128(&annotation);
+ mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType(
+ klass->GetDexFile(), type_index, klass.Get());
+ if (resolved_class == nullptr) {
+ std::string temp;
+ LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
+ klass->GetDescriptor(&temp), type_index);
+ CHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ continue;
+ }
+ if (resolved_class == annotation_class.Get()) {
+ return annotation_item;
+ }
+ }
+
+ return nullptr;
+}
+
+mirror::Object* GetAnnotationObjectFromAnnotationSet(
+ Handle<mirror::Class> klass,
+ const DexFile::AnnotationSetItem* annotation_set,
+ uint32_t visibility,
+ Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile::AnnotationItem* annotation_item =
+ GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ const uint8_t* annotation = annotation_item->annotation_;
+ return ProcessEncodedAnnotation(klass, &annotation);
+}
+
+mirror::Object* GetAnnotationValue(Handle<mirror::Class> klass,
+ const DexFile::AnnotationItem* annotation_item,
+ const char* annotation_name,
+ Handle<mirror::Class> array_class,
+ uint32_t expected_type)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(dex_file, annotation_item->annotation_, annotation_name);
+ if (annotation == nullptr) {
+ return nullptr;
+ }
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class,
+ DexFile::kAllObjects)) {
+ return nullptr;
+ }
+ if (annotation_value.type_ != expected_type) {
+ return nullptr;
+ }
+ return annotation_value.value_.GetL();
+}
+
+mirror::ObjectArray<mirror::String>* GetSignatureValue(Handle<mirror::Class> klass,
+ 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/Signature;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ 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.Get() == nullptr) {
+ return nullptr;
+ }
+ mirror::Object* obj =
+ GetAnnotationValue(klass, annotation_item, "value", string_array_class,
+ DexFile::kDexAnnotationArray);
+ if (obj == nullptr) {
+ return nullptr;
+ }
+ return obj->AsObjectArray<mirror::String>();
+}
+
+mirror::ObjectArray<mirror::Class>* GetThrowsValue(Handle<mirror::Class> klass,
+ 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;
+ }
+ 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.Get() == nullptr) {
+ return nullptr;
+ }
+ mirror::Object* obj =
+ GetAnnotationValue(klass, annotation_item, "value", class_array_class,
+ DexFile::kDexAnnotationArray);
+ if (obj == nullptr) {
+ return nullptr;
+ }
+ return obj->AsObjectArray<mirror::Class>();
+}
+
+mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet(
+ Handle<mirror::Class> klass,
+ const DexFile::AnnotationSetItem* annotation_set,
+ uint32_t visibility)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ Thread* self = Thread::Current();
+ ScopedObjectAccessUnchecked soa(self);
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Class> annotation_array_class(hs.NewHandle(
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array)));
+ if (annotation_set == nullptr) {
+ return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), 0);
+ }
+
+ uint32_t size = annotation_set->size_;
+ Handle<mirror::ObjectArray<mirror::Object>> result(hs.NewHandle(
+ mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), size)));
+ if (result.Get() == nullptr) {
+ return nullptr;
+ }
+
+ uint32_t dest_index = 0;
+ for (uint32_t i = 0; i < size; ++i) {
+ const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
+ // Note that we do not use IsVisibilityCompatible here because older code
+ // was correct for this case.
+ if (annotation_item->visibility_ != visibility) {
+ continue;
+ }
+ const uint8_t* annotation = annotation_item->annotation_;
+ mirror::Object* annotation_obj = ProcessEncodedAnnotation(klass, &annotation);
+ if (annotation_obj != nullptr) {
+ result->SetWithoutChecks<false>(dest_index, annotation_obj);
+ ++dest_index;
+ } else if (self->IsExceptionPending()) {
+ return nullptr;
+ }
+ }
+
+ if (dest_index == size) {
+ return result.Get();
+ }
+
+ mirror::ObjectArray<mirror::Object>* trimmed_result =
+ mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index);
+ if (trimmed_result == nullptr) {
+ return nullptr;
+ }
+
+ for (uint32_t i = 0; i < dest_index; ++i) {
+ mirror::Object* obj = result->GetWithoutChecks(i);
+ trimmed_result->SetWithoutChecks<false>(i, obj);
+ }
+
+ return trimmed_result;
+}
+
+mirror::ObjectArray<mirror::Object>* ProcessAnnotationSetRefList(
+ Handle<mirror::Class> klass,
+ const DexFile::AnnotationSetRefList* set_ref_list,
+ uint32_t size)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile& dex_file = klass->GetDexFile();
+ Thread* self = Thread::Current();
+ ScopedObjectAccessUnchecked soa(self);
+ StackHandleScope<1> hs(self);
+ mirror::Class* annotation_array_class =
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+ mirror::Class* annotation_array_array_class =
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
+ if (annotation_array_array_class == nullptr) {
+ return nullptr;
+ }
+ Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle(
+ mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size)));
+ if (annotation_array_array.Get() == nullptr) {
+ LOG(ERROR) << "Annotation set ref array allocation failed";
+ return nullptr;
+ }
+ for (uint32_t index = 0; index < size; ++index) {
+ const DexFile::AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index];
+ const DexFile::AnnotationSetItem* set_item = dex_file.GetSetRefItemItem(set_ref_item);
+ mirror::Object* annotation_set = ProcessAnnotationSet(klass, set_item,
+ DexFile::kDexVisibilityRuntime);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ annotation_array_array->SetWithoutChecks<false>(index, annotation_set);
+ }
+ return annotation_array_array.Get();
+}
+} // namespace
+
+namespace annotations {
+
+mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> annotation_class) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
+ return GetAnnotationObjectFromAnnotationSet(field_class, annotation_set,
+ DexFile::kDexVisibilityRuntime, annotation_class);
+}
+
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
+ return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime);
+}
+
+mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
+ return GetSignatureValue(field_class, annotation_set);
+}
+
+bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
+ if (annotation_set == nullptr) {
+ return false;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass()));
+ const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
+ field_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class);
+ return annotation_item != nullptr;
+}
+
+mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) {
+ const DexFile* dex_file = method->GetDexFile();
+ mirror::Class* klass = method->GetDeclaringClass();
+ const DexFile::AnnotationsDirectoryItem* annotations_dir =
+ dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+ if (annotations_dir == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationSetItem* annotation_set =
+ dex_file->GetClassAnnotationSet(annotations_dir);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(*dex_file, annotation_set,
+ "Ldalvik/annotation/AnnotationDefault;", DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(*dex_file, annotation_item->annotation_, "value");
+ if (annotation == nullptr) {
+ return nullptr;
+ }
+ uint8_t header_byte = *(annotation++);
+ if ((header_byte & DexFile::kDexAnnotationValueTypeMask) != DexFile::kDexAnnotationAnnotation) {
+ return nullptr;
+ }
+ annotation = SearchEncodedAnnotation(*dex_file, annotation, method->GetName());
+ if (annotation == nullptr) {
+ return nullptr;
+ }
+ DexFile::AnnotationValue annotation_value;
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::Class> h_klass(hs.NewHandle(klass));
+ PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ Handle<mirror::Class> return_type(hs.NewHandle(
+ method->GetReturnType(true /* resolve */, pointer_size)));
+ if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type,
+ DexFile::kAllObjects)) {
+ return nullptr;
+ }
+ return annotation_value.value_.GetL();
+}
+
+mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set,
+ DexFile::kDexVisibilityRuntime, annotation_class);
+}
+
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return ProcessAnnotationSet(method_class, annotation_set, DexFile::kDexVisibilityRuntime);
+}
+
+mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return GetThrowsValue(method_class, annotation_set);
+}
+
+mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) {
+ const DexFile* dex_file = method->GetDexFile();
+ const DexFile::ParameterAnnotationsItem* parameter_annotations =
+ FindAnnotationsItemForMethod(method);
+ if (parameter_annotations == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationSetRefList* set_ref_list =
+ dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
+ if (set_ref_list == nullptr) {
+ return nullptr;
+ }
+ uint32_t size = set_ref_list->size_;
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return ProcessAnnotationSetRefList(method_class, set_ref_list, size);
+}
+
+mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method,
+ uint32_t parameter_idx,
+ Handle<mirror::Class> annotation_class) {
+ const DexFile* dex_file = method->GetDexFile();
+ const DexFile::ParameterAnnotationsItem* parameter_annotations =
+ FindAnnotationsItemForMethod(method);
+ if (parameter_annotations == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationSetRefList* set_ref_list =
+ dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
+ if (set_ref_list == nullptr) {
+ return nullptr;
+ }
+ if (parameter_idx >= set_ref_list->size_) {
+ return nullptr;
+ }
+ const DexFile::AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
+ const DexFile::AnnotationSetItem* annotation_set =
+ dex_file->GetSetRefItemItem(annotation_set_ref);
+
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return GetAnnotationObjectFromAnnotationSet(method_class,
+ annotation_set,
+ DexFile::kDexVisibilityRuntime,
+ annotation_class);
+}
+
+mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ return GetSignatureValue(method_class, annotation_set);
+}
+
+bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class,
+ uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
+ if (annotation_set == nullptr) {
+ return false;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
+ const DexFile::AnnotationItem* annotation_item =
+ GetAnnotationItemFromAnnotationSet(method_class, annotation_set, visibility,
+ annotation_class);
+ return annotation_item != nullptr;
+}
+
+mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass,
+ Handle<mirror::Class> annotation_class) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime,
+ annotation_class);
+}
+
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ return ProcessAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime);
+}
+
+mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item =
+ SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/MemberClasses;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ StackHandleScope<1> hs(Thread::Current());
+ 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.Get() == nullptr) {
+ return nullptr;
+ }
+ mirror::Object* obj =
+ GetAnnotationValue(klass, annotation_item, "value", class_array_class,
+ DexFile::kDexAnnotationArray);
+ if (obj == nullptr) {
+ return nullptr;
+ }
+ return obj->AsObjectArray<mirror::Class>();
+}
+
+mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item =
+ SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingClass;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ mirror::Object* obj = GetAnnotationValue(klass, annotation_item, "value",
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kDexAnnotationType);
+ if (obj == nullptr) {
+ return nullptr;
+ }
+ return obj->AsClass();
+}
+
+mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) {
+ const DexFile& dex_file = klass->GetDexFile();
+ mirror::Class* declaring_class = GetDeclaringClass(klass);
+ if (declaring_class != nullptr) {
+ return declaring_class;
+ }
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item =
+ SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "value");
+ if (annotation == nullptr) {
+ return nullptr;
+ }
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
+ ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+ return nullptr;
+ }
+ if (annotation_value.type_ != DexFile::kDexAnnotationMethod) {
+ return nullptr;
+ }
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+ ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
+ klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader);
+ if (method == nullptr) {
+ return nullptr;
+ }
+ return method->GetDeclaringClass();
+}
+
+mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ const DexFile::AnnotationItem* annotation_item =
+ SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return nullptr;
+ }
+ return GetAnnotationValue(klass, annotation_item, "value", ScopedNullHandle<mirror::Class>(),
+ DexFile::kDexAnnotationMethod);
+}
+
+bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return false;
+ }
+ const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(
+ dex_file, annotation_set, "Ldalvik/annotation/InnerClass;", DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return false;
+ }
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "name");
+ if (annotation == nullptr) {
+ return false;
+ }
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kAllObjects)) {
+ return false;
+ }
+ if (annotation_value.type_ != DexFile::kDexAnnotationNull &&
+ annotation_value.type_ != DexFile::kDexAnnotationString) {
+ return false;
+ }
+ *name = down_cast<mirror::String*>(annotation_value.value_.GetL());
+ return true;
+}
+
+bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) {
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return false;
+ }
+ const DexFile::AnnotationItem* annotation_item =
+ SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/InnerClass;",
+ DexFile::kDexVisibilitySystem);
+ if (annotation_item == nullptr) {
+ return false;
+ }
+ const uint8_t* annotation =
+ SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "accessFlags");
+ if (annotation == nullptr) {
+ return false;
+ }
+ DexFile::AnnotationValue annotation_value;
+ if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
+ ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+ return false;
+ }
+ if (annotation_value.type_ != DexFile::kDexAnnotationInt) {
+ return false;
+ }
+ *flags = annotation_value.value_.GetI();
+ return true;
+}
+
+mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return nullptr;
+ }
+ return GetSignatureValue(klass, annotation_set);
+}
+
+bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) {
+ const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+ if (annotation_set == nullptr) {
+ return false;
+ }
+ const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
+ klass, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class);
+ return annotation_item != nullptr;
+}
+
+int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) {
+ // For native method, lineno should be -2 to indicate it is native. Note that
+ // "line number == -2" is how libcore tells from StackTraceElement.
+ if (method->GetCodeItemOffset() == 0) {
+ return -2;
+ }
+
+ const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
+ DCHECK(code_item != nullptr) << PrettyMethod(method) << " " << dex_file->GetLocation();
+
+ // A method with no line number info should return -1
+ DexFile::LineNumFromPcContext context(rel_pc, -1);
+ dex_file->DecodeDebugPositionInfo(code_item, DexFile::LineNumForPcCb, &context);
+ return context.line_num_;
+}
+
+template<bool kTransactionActive>
+void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const {
+ DCHECK(dex_cache_ != nullptr);
+ DCHECK(class_loader_ != nullptr);
+ switch (type_) {
+ case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z);
+ break;
+ case kByte: field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
+ case kShort: field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break;
+ case kChar: field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break;
+ case kInt: field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break;
+ case kLong: field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break;
+ case kFloat: field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break;
+ case kDouble: field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
+ case kNull: field->SetObject<kTransactionActive>(field->GetDeclaringClass(), nullptr); break;
+ case kString: {
+ mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_);
+ field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
+ break;
+ }
+ case kType: {
+ mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_,
+ *class_loader_);
+ field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
+ break;
+ }
+ default: UNIMPLEMENTED(FATAL) << ": type " << type_;
+ }
+}
+template
+void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const;
+template
+void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* field) const;
+
+} // namespace annotations
+
+} // namespace art
diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h
new file mode 100644
index 0000000000..7b4e8564b0
--- /dev/null
+++ b/runtime/dex_file_annotations.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_
+#define ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_
+
+#include "dex_file.h"
+
+#include "mirror/object_array.h"
+
+namespace art {
+
+namespace mirror {
+ class ClassLoader;
+ class DexCache;
+} // namespace mirror
+class ArtField;
+class ArtMethod;
+class ClassLinker;
+
+namespace annotations {
+
+// Field annotations.
+mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+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_);
+
+// Method annotations.
+mirror::Object* GetAnnotationDefaultValue(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method,
+ uint32_t parameter_idx,
+ Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class,
+ uint32_t visibility = DexFile::kDexVisibilityRuntime)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+// Class annotations.
+mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass,
+ Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+bool GetInnerClass(Handle<mirror::Class> klass, 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_);
+bool IsClassAnnotationPresent(Handle<mirror::Class> klass,
+ Handle<mirror::Class> annotation_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+// Map back from a PC to the line number in a method.
+int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+// Annotations iterator.
+class RuntimeEncodedStaticFieldValueIterator : public EncodedStaticFieldValueIterator {
+ public:
+ // A constructor meant to be called from runtime code.
+ RuntimeEncodedStaticFieldValueIterator(const DexFile& dex_file,
+ Handle<mirror::DexCache>* dex_cache,
+ Handle<mirror::ClassLoader>* class_loader,
+ ClassLinker* linker,
+ const DexFile::ClassDef& class_def)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ : EncodedStaticFieldValueIterator(dex_file, class_def),
+ dex_cache_(dex_cache),
+ class_loader_(class_loader),
+ linker_(linker) {
+ }
+
+ template<bool kTransactionActive>
+ void ReadValueToField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+ Handle<mirror::DexCache>* const dex_cache_; // Dex cache to resolve literal objects.
+ Handle<mirror::ClassLoader>* const class_loader_; // ClassLoader to resolve types.
+ ClassLinker* linker_; // Linker to resolve literal objects.
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RuntimeEncodedStaticFieldValueIterator);
+};
+
+} // namespace annotations
+
+} // namespace art
+
+#endif // ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index d03a9d80eb..1bf5c5388a 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -48,7 +48,7 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
// This method is being used by artQuickResolutionTrampoline, before it sets up
// the passed parameters in a GC friendly way. Therefore we must never be
// suspended while executing it.
- ScopedAssertNoThreadSuspension sants(Thread::Current(), __FUNCTION__);
+ ScopedAssertNoThreadSuspension sants(__FUNCTION__);
uint32_t method_index = inline_info.GetMethodIndexAtDepth(encoding, inlining_depth);
InvokeType invoke_type = static_cast<InvokeType>(
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 600aff19dd..cb5226b7b6 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1011,7 +1011,7 @@ void Heap::VisitObjects(ObjectCallback callback, void* arg) {
DecrementDisableMovingGC(self);
} else {
// GCs can move objects, so don't allow this.
- ScopedAssertNoThreadSuspension ants(self, "Visiting objects");
+ ScopedAssertNoThreadSuspension ants("Visiting objects");
DCHECK(region_space_ == nullptr);
VisitObjectsInternal(callback, arg);
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 388561b012..ff433890a9 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -966,7 +966,7 @@ void Instrumentation::InvokeVirtualOrInterfaceImpl(Thread* thread,
ArtMethod* callee) const {
// We cannot have thread suspension since that would cause the this_object parameter to
// potentially become a dangling pointer. An alternative could be to put it in a handle instead.
- ScopedAssertNoThreadSuspension ants(thread, __FUNCTION__);
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
for (InstrumentationListener* listener : invoke_virtual_or_interface_listeners_) {
if (listener != nullptr) {
listener->InvokeVirtualOrInterface(thread, this_object, caller, dex_pc, callee);
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 9d76685fb5..814adf7132 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -147,8 +147,7 @@ static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instr
jit::Jit* jit = Runtime::Current()->GetJit();
if (jit != nullptr) {
if (type == kVirtual || type == kInterface) {
- jit->InvokeVirtualOrInterface(
- self, receiver, sf_method, shadow_frame.GetDexPC(), called_method);
+ jit->InvokeVirtualOrInterface(receiver, sf_method, shadow_frame.GetDexPC(), called_method);
}
jit->AddSamples(self, sf_method, 1, /*with_backedges*/false);
}
@@ -195,7 +194,7 @@ static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
jit::Jit* jit = Runtime::Current()->GetJit();
if (jit != nullptr) {
jit->InvokeVirtualOrInterface(
- self, receiver, shadow_frame.GetMethod(), shadow_frame.GetDexPC(), called_method);
+ receiver, shadow_frame.GetMethod(), shadow_frame.GetDexPC(), called_method);
jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges*/false);
}
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index c6144086a8..d505aea10a 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -402,7 +402,7 @@ void UnstartedRuntime::UnstartedClassGetEnclosingClass(
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
result->SetL(nullptr);
}
- result->SetL(klass->GetDexFile().GetEnclosingClass(klass));
+ result->SetL(annotations::GetEnclosingClass(klass));
}
void UnstartedRuntime::UnstartedClassGetInnerClassFlags(
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index cff23541b3..d984f45253 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -431,7 +431,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
const uint8_t* native_pc = nullptr;
{
- ScopedAssertNoThreadSuspension sts(thread, "Holding OSR method");
+ ScopedAssertNoThreadSuspension sts("Holding OSR method");
const OatQuickMethodHeader* osr_method = jit->GetCodeCache()->LookupOsrMethodHeader(method);
if (osr_method == nullptr) {
// No osr method yet, just return to the interpreter.
@@ -683,12 +683,11 @@ void Jit::MethodEntered(Thread* thread, ArtMethod* method) {
}
}
-void Jit::InvokeVirtualOrInterface(Thread* thread,
- mirror::Object* this_object,
+void Jit::InvokeVirtualOrInterface(mirror::Object* this_object,
ArtMethod* caller,
uint32_t dex_pc,
ArtMethod* callee ATTRIBUTE_UNUSED) {
- ScopedAssertNoThreadSuspension ants(thread, __FUNCTION__);
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
DCHECK(this_object != nullptr);
ProfilingInfo* info = caller->GetProfilingInfo(kRuntimePointerSize);
if (info != nullptr) {
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 417a185853..35656cd6f6 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -30,6 +30,7 @@
namespace art {
class ArtMethod;
+class ClassLinker;
struct RuntimeArgumentMap;
union JValue;
@@ -108,8 +109,7 @@ class Jit {
void AddSamples(Thread* self, ArtMethod* method, uint16_t samples, bool with_backedges)
REQUIRES_SHARED(Locks::mutator_lock_);
- void InvokeVirtualOrInterface(Thread* thread,
- mirror::Object* this_object,
+ void InvokeVirtualOrInterface(mirror::Object* this_object,
ArtMethod* caller,
uint32_t dex_pc,
ArtMethod* callee)
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index c979c28138..f21baed70f 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -23,6 +23,7 @@
#include "class-inl.h"
#include "dex_cache.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "gc/accounting/card_table-inl.h"
#include "handle_scope-inl.h"
#include "method.h"
@@ -784,7 +785,7 @@ ArtField* Class::FindStaticField(Thread* self,
}
// Though GetDirectInterface() should not cause thread suspension when called
// from here, it takes a Handle as an argument, so we need to wrap `k`.
- ScopedAssertNoThreadSuspension ants(self, __FUNCTION__);
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_k(hs.NewHandle(k));
// Is this field in any of this class' interfaces?
@@ -1214,7 +1215,7 @@ int32_t Class::GetInnerClassFlags(Handle<Class> h_this, int32_t default_value) {
return default_value;
}
uint32_t flags;
- if (!h_this->GetDexFile().GetInnerClassFlags(h_this, &flags)) {
+ if (!annotations::GetInnerClassFlags(h_this, &flags)) {
return default_value;
}
return flags;
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index d89a334f32..af9b68f9a7 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -23,6 +23,7 @@
#include "class_linker.h"
#include "common_throws.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
#include "mirror/class-inl.h"
@@ -454,7 +455,7 @@ static jobject Class_getDeclaredAnnotation(JNIEnv* env, jobject javaThis, jclass
}
Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationClass)));
return soa.AddLocalReference<jobject>(
- klass->GetDexFile().GetAnnotationForClass(klass, annotation_class));
+ annotations::GetAnnotationForClass(klass, annotation_class));
}
static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis) {
@@ -469,7 +470,7 @@ static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis)
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
- return soa.AddLocalReference<jobjectArray>(klass->GetDexFile().GetAnnotationsForClass(klass));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
}
static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) {
@@ -478,7 +479,7 @@ static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) {
Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
mirror::ObjectArray<mirror::Class>* classes = nullptr;
if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
- classes = klass->GetDexFile().GetDeclaredClasses(klass);
+ classes = annotations::GetDeclaredClasses(klass);
}
if (classes == nullptr) {
// Return an empty array instead of a null pointer.
@@ -506,7 +507,7 @@ static jclass Class_getEnclosingClass(JNIEnv* env, jobject javaThis) {
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
return nullptr;
}
- return soa.AddLocalReference<jclass>(klass->GetDexFile().GetEnclosingClass(klass));
+ return soa.AddLocalReference<jclass>(annotations::GetEnclosingClass(klass));
}
static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis) {
@@ -516,7 +517,7 @@ static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
return nullptr;
}
- mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass);
+ mirror::Object* method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
if (method->GetClass() ==
soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor)) {
@@ -533,7 +534,7 @@ static jobject Class_getEnclosingMethodNative(JNIEnv* env, jobject javaThis) {
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
return nullptr;
}
- mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass);
+ mirror::Object* method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
if (method->GetClass() ==
soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method)) {
@@ -558,7 +559,7 @@ static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) {
return nullptr;
}
mirror::String* class_name = nullptr;
- if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) {
+ if (!annotations::GetInnerClass(klass, &class_name)) {
return nullptr;
}
return soa.AddLocalReference<jstring>(class_name);
@@ -572,7 +573,7 @@ static jobjectArray Class_getSignatureAnnotation(JNIEnv* env, jobject javaThis)
return nullptr;
}
return soa.AddLocalReference<jobjectArray>(
- klass->GetDexFile().GetSignatureAnnotationForClass(klass));
+ annotations::GetSignatureAnnotationForClass(klass));
}
static jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
@@ -583,7 +584,7 @@ static jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
return false;
}
mirror::String* class_name = nullptr;
- if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) {
+ if (!annotations::GetInnerClass(klass, &class_name)) {
return false;
}
return class_name == nullptr;
@@ -598,7 +599,7 @@ static jboolean Class_isDeclaredAnnotationPresent(JNIEnv* env, jobject javaThis,
return false;
}
Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
- return klass->GetDexFile().IsClassAnnotationPresent(klass, annotation_class);
+ return annotations::IsClassAnnotationPresent(klass, annotation_class);
}
static jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
@@ -612,7 +613,7 @@ static jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
if (Class_isAnonymousClass(env, javaThis)) {
return nullptr;
}
- return soa.AddLocalReference<jclass>(klass->GetDexFile().GetDeclaringClass(klass));
+ return soa.AddLocalReference<jclass>(annotations::GetDeclaringClass(klass));
}
static jobject Class_newInstance(JNIEnv* env, jobject javaThis) {
@@ -668,8 +669,7 @@ static jobject Class_newInstance(JNIEnv* env, jobject javaThis) {
caller.Assign(GetCallingClass(soa.Self(), 1));
}
if (UNLIKELY(caller.Get() != nullptr && !VerifyAccess(
- soa.Self(), receiver.Get(), declaring_class, constructor->GetAccessFlags(),
- caller.Get()))) {
+ receiver.Get(), declaring_class, constructor->GetAccessFlags(), caller.Get()))) {
soa.Self()->ThrowNewExceptionF(
"Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
PrettyMethod(constructor).c_str(), PrettyClass(caller.Get()).c_str());
diff --git a/runtime/native/java_lang_reflect_AbstractMethod.cc b/runtime/native/java_lang_reflect_AbstractMethod.cc
index 33e0daef1f..254f8dbb4c 100644
--- a/runtime/native/java_lang_reflect_AbstractMethod.cc
+++ b/runtime/native/java_lang_reflect_AbstractMethod.cc
@@ -17,6 +17,7 @@
#include "java_lang_reflect_AbstractMethod.h"
#include "art_method-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
@@ -38,7 +39,7 @@ static jobjectArray AbstractMethod_getDeclaredAnnotations(JNIEnv* env, jobject j
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
- return soa.AddLocalReference<jobjectArray>(method->GetDexFile()->GetAnnotationsForMethod(method));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
}
static jobject AbstractMethod_getAnnotationNative(JNIEnv* env,
@@ -51,8 +52,7 @@ static jobject AbstractMethod_getAnnotationNative(JNIEnv* env,
return nullptr;
} else {
Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
- return soa.AddLocalReference<jobject>(
- method->GetDexFile()->GetAnnotationForMethod(method, klass));
+ return soa.AddLocalReference<jobject>(annotations::GetAnnotationForMethod(method, klass));
}
}
@@ -63,8 +63,7 @@ static jobjectArray AbstractMethod_getSignatureAnnotation(JNIEnv* env, jobject j
return nullptr;
}
StackHandleScope<1> hs(soa.Self());
- return soa.AddLocalReference<jobjectArray>(
- method->GetDexFile()->GetSignatureAnnotationForMethod(method));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetSignatureAnnotationForMethod(method));
}
@@ -74,8 +73,7 @@ static jobjectArray AbstractMethod_getParameterAnnotationsNative(JNIEnv* env, jo
if (method->IsProxyMethod()) {
return nullptr;
} else {
- return soa.AddLocalReference<jobjectArray>(
- method->GetDexFile()->GetParameterAnnotations(method));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetParameterAnnotations(method));
}
}
@@ -89,7 +87,7 @@ static jboolean AbstractMethod_isAnnotationPresentNative(JNIEnv* env,
}
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
- return method->GetDexFile()->IsMethodAnnotationPresent(method, klass);
+ return annotations::IsMethodAnnotationPresent(method, klass);
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index f699d6bd75..d001d0c0da 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -20,6 +20,7 @@
#include "base/enums.h"
#include "class_linker.h"
#include "class_linker-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/method.h"
@@ -35,7 +36,7 @@ static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMetho
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod)
->GetInterfaceMethodIfProxy(kRuntimePointerSize);
mirror::ObjectArray<mirror::Class>* result_array =
- method->GetDexFile()->GetExceptionTypesForMethod(method);
+ annotations::GetExceptionTypesForMethod(method);
if (result_array == nullptr) {
// Return an empty array instead of a null pointer.
mirror::Class* class_class = mirror::Class::GetJavaLangClass();
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 5a4ced2fed..412445f0d0 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -20,6 +20,7 @@
#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/field.h"
@@ -423,7 +424,7 @@ static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass
return nullptr;
}
Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
- return soa.AddLocalReference<jobject>(field->GetDexFile()->GetAnnotationForField(field, klass));
+ return soa.AddLocalReference<jobject>(annotations::GetAnnotationForField(field, klass));
}
static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
@@ -437,7 +438,7 @@ static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField)
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
- return soa.AddLocalReference<jobjectArray>(field->GetDexFile()->GetAnnotationsForField(field));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForField(field));
}
static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) {
@@ -446,8 +447,7 @@ static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField)
if (field->GetDeclaringClass()->IsProxyClass()) {
return nullptr;
}
- return soa.AddLocalReference<jobjectArray>(
- field->GetDexFile()->GetSignatureAnnotationForField(field));
+ return soa.AddLocalReference<jobjectArray>(annotations::GetSignatureAnnotationForField(field));
}
static jboolean Field_isAnnotationPresentNative(JNIEnv* env, jobject javaField,
@@ -459,7 +459,7 @@ static jboolean Field_isAnnotationPresentNative(JNIEnv* env, jobject javaField,
return false;
}
Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
- return field->GetDexFile()->IsFieldAnnotationPresent(field, klass);
+ return annotations::IsFieldAnnotationPresent(field, klass);
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 3360f4170e..b8efb14903 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -20,6 +20,7 @@
#include "base/enums.h"
#include "class_linker.h"
#include "class_linker-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
@@ -36,7 +37,7 @@ static jobject Method_getDefaultValue(JNIEnv* env, jobject javaMethod) {
if (!method->GetDeclaringClass()->IsAnnotation()) {
return nullptr;
}
- return soa.AddLocalReference<jobject>(method->GetDexFile()->GetAnnotationDefaultValue(method));
+ return soa.AddLocalReference<jobject>(annotations::GetAnnotationDefaultValue(method));
}
static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) {
@@ -58,7 +59,7 @@ static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) {
return soa.AddLocalReference<jobjectArray>(declared_exceptions->Clone(soa.Self()));
} else {
mirror::ObjectArray<mirror::Class>* result_array =
- method->GetDexFile()->GetExceptionTypesForMethod(method);
+ annotations::GetExceptionTypesForMethod(method);
if (result_array == nullptr) {
// Return an empty array instead of a null pointer
mirror::Class* class_class = mirror::Class::GetJavaLangClass();
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
index 8fe3bb590e..c2a803c3cd 100644
--- a/runtime/native/java_lang_reflect_Parameter.cc
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -19,6 +19,7 @@
#include "art_method-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "jni_internal.h"
#include "scoped_fast_native_object_access.h"
#include "utils.h"
@@ -54,7 +55,7 @@ static jobject Parameter_getAnnotationNative(JNIEnv* env,
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
return soa.AddLocalReference<jobject>(
- method->GetDexFile()->GetAnnotationForMethodParameter(method, parameterIndex, klass));
+ annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass));
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h
index 356e290843..2df2ced7f4 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/runtime/quick/inline_method_analyser.h
@@ -33,6 +33,7 @@ namespace art {
namespace verifier {
class MethodVerifier;
} // namespace verifier
+class ArtMethod;
enum InlineMethodOpcode : uint16_t {
kIntrinsicDoubleCvt,
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 55aba2befa..b3f29c28e4 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -160,8 +160,8 @@ void QuickExceptionHandler::FindCatch(mirror::Throwable* exception) {
LOG(INFO) << "Handler is upcall";
}
if (handler_method_ != nullptr) {
- const DexFile& dex_file = *handler_method_->GetDeclaringClass()->GetDexCache()->GetDexFile();
- int line_number = dex_file.GetLineNumFromPC(handler_method_, handler_dex_pc_);
+ const DexFile* dex_file = handler_method_->GetDeclaringClass()->GetDexCache()->GetDexFile();
+ int line_number = annotations::GetLineNumFromPC(dex_file, handler_method_, handler_dex_pc_);
LOG(INFO) << "Handler: " << PrettyMethod(handler_method_) << " (line: " << line_number << ")";
}
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index f2af3da6e4..67e3fe8864 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -625,8 +625,12 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
// If method is not set to be accessible, verify it can be accessed by the caller.
mirror::Class* calling_class = nullptr;
- if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(),
- &calling_class, num_frames)) {
+ if (!accessible && !VerifyAccess(soa.Self(),
+ receiver,
+ declaring_class,
+ m->GetAccessFlags(),
+ &calling_class,
+ num_frames)) {
ThrowIllegalAccessException(
StringPrintf("Class %s cannot access %s method %s of class %s",
calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
@@ -857,15 +861,17 @@ bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_cl
return false;
}
*calling_class = klass;
- return VerifyAccess(self, obj, declaring_class, access_flags, klass);
+ return VerifyAccess(obj, declaring_class, access_flags, klass);
}
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
- uint32_t access_flags, mirror::Class* calling_class) {
+bool VerifyAccess(mirror::Object* obj,
+ mirror::Class* declaring_class,
+ uint32_t access_flags,
+ mirror::Class* calling_class) {
if (calling_class == declaring_class) {
return true;
}
- ScopedAssertNoThreadSuspension sants(self, "verify-access");
+ ScopedAssertNoThreadSuspension sants("verify-access");
if ((access_flags & kAccPrivate) != 0) {
return false;
}
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 579c6b1c7d..208b533917 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -74,8 +74,10 @@ bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_cl
REQUIRES_SHARED(Locks::mutator_lock_);
// This version takes a known calling class.
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
- uint32_t access_flags, mirror::Class* calling_class)
+bool VerifyAccess(mirror::Object* obj,
+ mirror::Class* declaring_class,
+ uint32_t access_flags,
+ mirror::Class* calling_class)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get the calling class by using a stack visitor, may return null for unattached native threads.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index a860c7ae97..89403545fd 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -40,6 +40,7 @@
#include "class_linker-inl.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "dex_file_annotations.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
@@ -1388,8 +1389,8 @@ struct StackDumpVisitor : public StackVisitor {
mirror::DexCache* dex_cache = c->GetDexCache();
int line_number = -1;
if (dex_cache != nullptr) { // be tolerant of bad input
- const DexFile& dex_file = *dex_cache->GetDexFile();
- line_number = dex_file.GetLineNumFromPC(m, GetDexPc(false));
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc(false));
}
if (line_number == last_line_number && last_method == m) {
++repetition_count;
diff --git a/runtime/thread.h b/runtime/thread.h
index b53cc2ef3e..016c2bc7ea 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -1546,19 +1546,25 @@ class Thread {
class SCOPED_CAPABILITY ScopedAssertNoThreadSuspension {
public:
- ScopedAssertNoThreadSuspension(Thread* self, const char* cause) ACQUIRE(Roles::uninterruptible_)
- : self_(self), old_cause_(self->StartAssertNoThreadSuspension(cause)) {
- }
- ~ScopedAssertNoThreadSuspension() RELEASE(Roles::uninterruptible_) {
- self_->EndAssertNoThreadSuspension(old_cause_);
+ ALWAYS_INLINE ScopedAssertNoThreadSuspension(const char* cause) ACQUIRE(Roles::uninterruptible_) {
+ if (kIsDebugBuild) {
+ self_ = Thread::Current();
+ old_cause_ = self_->StartAssertNoThreadSuspension(cause);
+ } else {
+ Roles::uninterruptible_.Acquire(); // No-op.
+ }
}
- Thread* Self() {
- return self_;
+ ALWAYS_INLINE ~ScopedAssertNoThreadSuspension() RELEASE(Roles::uninterruptible_) {
+ if (kIsDebugBuild) {
+ self_->EndAssertNoThreadSuspension(old_cause_);
+ } else {
+ Roles::uninterruptible_.Release(); // No-op.
+ }
}
private:
- Thread* const self_;
- const char* const old_cause_;
+ Thread* self_;
+ const char* old_cause_;
};
class ScopedStackedShadowFramePusher {