diff options
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 ¶meter_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 ¶meter_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 { |