diff options
24 files changed, 159 insertions, 112 deletions
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index bb2a214ecd..df5bb37358 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -137,10 +137,17 @@ static std::vector<uint8_t> MakeElfFileForJITInternal( InstructionSet isa, const InstructionSetFeatures* features, bool mini_debug_info, - const MethodDebugInfo& mi) { - CHECK_EQ(mi.is_code_address_text_relative, false); + ArrayRef<const MethodDebugInfo> method_infos) { + CHECK_GT(method_infos.size(), 0u); + uint64_t min_address = std::numeric_limits<uint64_t>::max(); + uint64_t max_address = 0; + for (const MethodDebugInfo& mi : method_infos) { + CHECK_EQ(mi.is_code_address_text_relative, false); + min_address = std::min(min_address, mi.code_address); + max_address = std::max(max_address, mi.code_address + mi.code_size); + } DebugInfo debug_info{}; - debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(&mi, 1); + debug_info.compiled_methods = method_infos; std::vector<uint8_t> buffer; buffer.reserve(KB); linker::VectorOutputStream out("Debug ELF file", &buffer); @@ -151,14 +158,14 @@ static std::vector<uint8_t> MakeElfFileForJITInternal( if (mini_debug_info) { std::vector<uint8_t> mdi = MakeMiniDebugInfo(isa, features, - mi.code_address, - mi.code_size, + min_address, + max_address - min_address, /* dex_section_address */ 0, /* dex_section_size */ 0, debug_info); builder->WriteSection(".gnu_debugdata", &mdi); } else { - builder->GetText()->AllocateVirtualMemory(mi.code_address, mi.code_size); + builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address); WriteDebugInfo(builder.get(), debug_info, dwarf::DW_DEBUG_FRAME_FORMAT, @@ -173,11 +180,11 @@ std::vector<uint8_t> MakeElfFileForJIT( InstructionSet isa, const InstructionSetFeatures* features, bool mini_debug_info, - const MethodDebugInfo& method_info) { + ArrayRef<const MethodDebugInfo> method_infos) { if (Is64BitInstructionSet(isa)) { - return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_info); + return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_infos); } else { - return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_info); + return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_infos); } } diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h index 8ad0c4219a..e442e0016c 100644 --- a/compiler/debug/elf_debug_writer.h +++ b/compiler/debug/elf_debug_writer.h @@ -54,7 +54,7 @@ std::vector<uint8_t> MakeElfFileForJIT( InstructionSet isa, const InstructionSetFeatures* features, bool mini_debug_info, - const MethodDebugInfo& method_info); + ArrayRef<const MethodDebugInfo> method_infos); std::vector<uint8_t> WriteDebugElfFileForClasses( InstructionSet isa, diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h index a853714d2b..9c9e8b35b8 100644 --- a/compiler/debug/elf_symtab_writer.h +++ b/compiler/debug/elf_symtab_writer.h @@ -72,8 +72,8 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, continue; // Add symbol only for the first instance. } size_t name_offset; - if (!info.trampoline_name.empty()) { - name_offset = strtab->Write(info.trampoline_name); + if (!info.custom_name.empty()) { + name_offset = strtab->Write(info.custom_name); } else { DCHECK(info.dex_file != nullptr); std::string name = info.dex_file->PrettyMethod(info.dex_method_index, !mini_debug_info); diff --git a/compiler/debug/method_debug_info.h b/compiler/debug/method_debug_info.h index 43c8de26aa..d0b03ec441 100644 --- a/compiler/debug/method_debug_info.h +++ b/compiler/debug/method_debug_info.h @@ -27,7 +27,7 @@ namespace art { namespace debug { struct MethodDebugInfo { - std::string trampoline_name; + std::string custom_name; const DexFile* dex_file; // Native methods (trampolines) do not reference dex file. size_t class_def_index; uint32_t dex_method_index; diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 88e3e5b230..2c62095458 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -76,6 +76,7 @@ extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t cou const ArrayRef<mirror::Class*> types_array(types, count); std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForClasses( kRuntimeISA, jit_compiler->GetCompilerDriver()->GetInstructionSetFeatures(), types_array); + MutexLock mu(Thread::Current(), g_jit_debug_mutex); CreateJITCodeEntry(std::move(elf_file)); } } diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc index cedbe5d97f..6e0286afac 100644 --- a/compiler/linker/arm/relative_patcher_arm_base.cc +++ b/compiler/linker/arm/relative_patcher_arm_base.cc @@ -250,12 +250,12 @@ std::vector<debug::MethodDebugInfo> ArmBaseRelativePatcher::GenerateThunkDebugIn for (size_t i = start, num = data.NumberOfThunks(); i != num; ++i) { debug::MethodDebugInfo info = {}; if (i == 0u) { - info.trampoline_name = base_name; + info.custom_name = base_name; } else { // Add a disambiguating tag for subsequent identical thunks. Since the `thunks_` // keeps records also for thunks in previous oat files, names based on the thunk // index shall be unique across the whole multi-oat output. - info.trampoline_name = base_name + "_" + std::to_string(i); + info.custom_name = base_name + "_" + std::to_string(i); } info.isa = instruction_set_; info.is_code_address_text_relative = true; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index a3b1f0c5af..c35c490118 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -382,6 +382,8 @@ class OptimizingCompiler FINAL : public Compiler { PassObserver* pass_observer, VariableSizedHandleScope* handles) const; + void GenerateJitDebugInfo(debug::MethodDebugInfo method_debug_info); + std::unique_ptr<OptimizingCompilerStats> compilation_stats_; std::unique_ptr<std::ostream> visualizer_output_; @@ -1230,7 +1232,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code); const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode()); debug::MethodDebugInfo info = {}; - DCHECK(info.trampoline_name.empty()); + DCHECK(info.custom_name.empty()); info.dex_file = dex_file; info.class_def_index = class_def_idx; info.dex_method_index = method_idx; @@ -1246,14 +1248,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, info.frame_size_in_bytes = method_header->GetFrameSizeInBytes(); info.code_info = nullptr; info.cfi = jni_compiled_method.GetCfi(); - // If both flags are passed, generate full debug info. - const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo(); - std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT( - GetCompilerDriver()->GetInstructionSet(), - GetCompilerDriver()->GetInstructionSetFeatures(), - mini_debug_info, - info); - CreateJITCodeEntryForAddress(code_address, std::move(elf_file)); + GenerateJitDebugInfo(info); } Runtime::Current()->GetJit()->AddMemoryUsage(method, allocator.BytesUsed()); @@ -1361,7 +1356,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code); const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode()); debug::MethodDebugInfo info = {}; - DCHECK(info.trampoline_name.empty()); + DCHECK(info.custom_name.empty()); info.dex_file = dex_file; info.class_def_index = class_def_idx; info.dex_method_index = method_idx; @@ -1377,14 +1372,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, info.frame_size_in_bytes = method_header->GetFrameSizeInBytes(); info.code_info = stack_map_size == 0 ? nullptr : stack_map_data; info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()); - // If both flags are passed, generate full debug info. - const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo(); - std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT( - GetCompilerDriver()->GetInstructionSet(), - GetCompilerDriver()->GetInstructionSetFeatures(), - mini_debug_info, - info); - CreateJITCodeEntryForAddress(code_address, std::move(elf_file)); + GenerateJitDebugInfo(info); } Runtime::Current()->GetJit()->AddMemoryUsage(method, allocator.BytesUsed()); @@ -1408,4 +1396,22 @@ bool OptimizingCompiler::JitCompile(Thread* self, return true; } +void OptimizingCompiler::GenerateJitDebugInfo(debug::MethodDebugInfo info) { + const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions(); + DCHECK(compiler_options.GenerateAnyDebugInfo()); + + // If both flags are passed, generate full debug info. + const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo(); + + // Create entry for the single method that we just compiled. + std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT( + GetCompilerDriver()->GetInstructionSet(), + GetCompilerDriver()->GetInstructionSetFeatures(), + mini_debug_info, + ArrayRef<const debug::MethodDebugInfo>(&info, 1)); + MutexLock mu(Thread::Current(), g_jit_debug_mutex); + JITCodeEntry* entry = CreateJITCodeEntry(elf_file); + IncrementJITCodeEntryRefcount(entry, info.code_address); +} + } // namespace art diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 849887c8ff..66041bbfad 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -1336,7 +1336,7 @@ class OatWriter::LayoutReserveOffsetCodeMethodVisitor : public OrderedMethodVisi bool has_code_info = method_header->IsOptimized(); // Record debug information for this function if we are doing that. debug::MethodDebugInfo& info = writer_->method_info_[debug_info_idx]; - DCHECK(info.trampoline_name.empty()); + DCHECK(info.custom_name.empty()); info.dex_file = method_ref.dex_file; info.class_def_index = class_def_index; info.dex_method_index = method_ref.index; @@ -2420,7 +2420,7 @@ size_t OatWriter::InitOatCode(size_t offset) { (field) = compiler_driver_->Create ## fn_name(); \ if (generate_debug_info) { \ debug::MethodDebugInfo info = {}; \ - info.trampoline_name = #fn_name; \ + info.custom_name = #fn_name; \ info.isa = instruction_set; \ info.is_code_address_text_relative = true; \ /* Use the code offset rather than the `adjusted_offset`. */ \ diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 2b90614b93..fcbf2f1c0a 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -180,7 +180,7 @@ class OatSymbolizer FINAL { #define DO_TRAMPOLINE(fn_name) \ if (oat_header.Get ## fn_name ## Offset() != 0) { \ debug::MethodDebugInfo info = {}; \ - info.trampoline_name = #fn_name; \ + info.custom_name = #fn_name; \ info.isa = oat_header.GetInstructionSet(); \ info.is_code_address_text_relative = true; \ size_t code_offset = oat_header.Get ## fn_name ## Offset(); \ @@ -308,7 +308,7 @@ class OatSymbolizer FINAL { const void* code_address = EntryPointToCodePointer(reinterpret_cast<void*>(entry_point)); debug::MethodDebugInfo info = {}; - DCHECK(info.trampoline_name.empty()); + DCHECK(info.custom_name.empty()); info.dex_file = &dex_file; info.class_def_index = class_def_index; info.dex_method_index = dex_method_index; diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc index 4d1c85a1c2..0e295e2442 100644 --- a/runtime/jit/debugger_interface.cc +++ b/runtime/jit/debugger_interface.cc @@ -42,6 +42,7 @@ extern "C" { JITCodeEntry* prev_; const uint8_t *symfile_addr_; uint64_t symfile_size_; + uint32_t ref_count; // ART internal field. }; struct JITDescriptor { @@ -69,10 +70,11 @@ extern "C" { JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, nullptr, nullptr }; } -static Mutex g_jit_debug_mutex("JIT debug interface lock", kJitDebugInterfaceLock); +Mutex g_jit_debug_mutex("JIT debug interface lock", kJitDebugInterfaceLock); -static JITCodeEntry* CreateJITCodeEntryInternal(std::vector<uint8_t> symfile) - REQUIRES(g_jit_debug_mutex) { +static size_t g_jit_debug_mem_usage = 0; + +JITCodeEntry* CreateJITCodeEntry(const std::vector<uint8_t>& symfile) { DCHECK_NE(symfile.size(), 0u); // Make a copy of the buffer. We want to shrink it anyway. @@ -85,20 +87,20 @@ static JITCodeEntry* CreateJITCodeEntryInternal(std::vector<uint8_t> symfile) entry->symfile_addr_ = symfile_copy; entry->symfile_size_ = symfile.size(); entry->prev_ = nullptr; - + entry->ref_count = 0; entry->next_ = __jit_debug_descriptor.first_entry_; if (entry->next_ != nullptr) { entry->next_->prev_ = entry; } + g_jit_debug_mem_usage += sizeof(JITCodeEntry) + entry->symfile_size_; __jit_debug_descriptor.first_entry_ = entry; __jit_debug_descriptor.relevant_entry_ = entry; - __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; (*__jit_debug_register_code_ptr)(); return entry; } -static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) REQUIRES(g_jit_debug_mutex) { +void DeleteJITCodeEntry(JITCodeEntry* entry) { if (entry->prev_ != nullptr) { entry->prev_->next_ = entry->next_; } else { @@ -109,6 +111,7 @@ static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) REQUIRES(g_jit_debug entry->next_->prev_ = entry->prev_; } + g_jit_debug_mem_usage -= sizeof(JITCodeEntry) + entry->symfile_size_; __jit_debug_descriptor.relevant_entry_ = entry; __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; (*__jit_debug_register_code_ptr)(); @@ -116,41 +119,33 @@ static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) REQUIRES(g_jit_debug delete entry; } -JITCodeEntry* CreateJITCodeEntry(std::vector<uint8_t> symfile) { - Thread* self = Thread::Current(); - MutexLock mu(self, g_jit_debug_mutex); - return CreateJITCodeEntryInternal(std::move(symfile)); +// Mapping from code address to entry. Used to manage life-time of the entries. +static std::unordered_map<uintptr_t, JITCodeEntry*> g_jit_code_entries + GUARDED_BY(g_jit_debug_mutex); + +void IncrementJITCodeEntryRefcount(JITCodeEntry* entry, uintptr_t code_address) { + DCHECK(entry != nullptr); + DCHECK_EQ(g_jit_code_entries.count(code_address), 0u); + entry->ref_count++; + g_jit_code_entries.emplace(code_address, entry); } -void DeleteJITCodeEntry(JITCodeEntry* entry) { - Thread* self = Thread::Current(); - MutexLock mu(self, g_jit_debug_mutex); - DeleteJITCodeEntryInternal(entry); +void DecrementJITCodeEntryRefcount(JITCodeEntry* entry, uintptr_t code_address) { + DCHECK(entry != nullptr); + DCHECK(g_jit_code_entries[code_address] == entry); + if (--entry->ref_count == 0) { + DeleteJITCodeEntry(entry); + } + g_jit_code_entries.erase(code_address); } -// Mapping from address to entry. It takes ownership of the entries -// so that the user of the JIT interface does not have to store them. -static std::unordered_map<uintptr_t, JITCodeEntry*> g_jit_code_entries; - -void CreateJITCodeEntryForAddress(uintptr_t address, std::vector<uint8_t> symfile) { - Thread* self = Thread::Current(); - MutexLock mu(self, g_jit_debug_mutex); - DCHECK_NE(address, 0u); - DCHECK(g_jit_code_entries.find(address) == g_jit_code_entries.end()); - JITCodeEntry* entry = CreateJITCodeEntryInternal(std::move(symfile)); - g_jit_code_entries.emplace(address, entry); +JITCodeEntry* GetJITCodeEntry(uintptr_t code_address) { + auto it = g_jit_code_entries.find(code_address); + return it == g_jit_code_entries.end() ? nullptr : it->second; } -bool DeleteJITCodeEntryForAddress(uintptr_t address) { - Thread* self = Thread::Current(); - MutexLock mu(self, g_jit_debug_mutex); - const auto it = g_jit_code_entries.find(address); - if (it == g_jit_code_entries.end()) { - return false; - } - DeleteJITCodeEntryInternal(it->second); - g_jit_code_entries.erase(it); - return true; +size_t GetJITCodeEntryMemUsage() { + return g_jit_debug_mem_usage + g_jit_code_entries.size() * 2 * sizeof(void*); } } // namespace art diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h index d9bf331aab..9aec988f67 100644 --- a/runtime/jit/debugger_interface.h +++ b/runtime/jit/debugger_interface.h @@ -21,28 +21,45 @@ #include <memory> #include <vector> +#include "base/array_ref.h" +#include "base/mutex.h" + namespace art { extern "C" { struct JITCodeEntry; } +extern Mutex g_jit_debug_mutex; + // Notify native debugger about new JITed code by passing in-memory ELF. // It takes ownership of the in-memory ELF file. -JITCodeEntry* CreateJITCodeEntry(std::vector<uint8_t> symfile); +JITCodeEntry* CreateJITCodeEntry(const std::vector<uint8_t>& symfile) + REQUIRES(g_jit_debug_mutex); // Notify native debugger that JITed code has been removed. // It also releases the associated in-memory ELF file. -void DeleteJITCodeEntry(JITCodeEntry* entry); +void DeleteJITCodeEntry(JITCodeEntry* entry) + REQUIRES(g_jit_debug_mutex); -// Notify native debugger about new JITed code by passing in-memory ELF. -// The address is used only to uniquely identify the entry. -// It takes ownership of the in-memory ELF file. -void CreateJITCodeEntryForAddress(uintptr_t address, std::vector<uint8_t> symfile); +// Helper method to track life-time of JITCodeEntry. +// It registers given code address as being described by the given entry. +void IncrementJITCodeEntryRefcount(JITCodeEntry* entry, uintptr_t code_address) + REQUIRES(g_jit_debug_mutex); -// Notify native debugger that JITed code has been removed. -// Returns false if entry for the given address was not found. -bool DeleteJITCodeEntryForAddress(uintptr_t address); +// Helper method to track life-time of JITCodeEntry. +// It de-registers given code address as being described by the given entry. +void DecrementJITCodeEntryRefcount(JITCodeEntry* entry, uintptr_t code_address) + REQUIRES(g_jit_debug_mutex); + +// Find the registered JITCodeEntry for given code address. +// There can be only one entry per address at any given time. +JITCodeEntry* GetJITCodeEntry(uintptr_t code_address) + REQUIRES(g_jit_debug_mutex); + +// Returns approximate memory used by all JITCodeEntries. +size_t GetJITCodeEntryMemUsage() + REQUIRES(g_jit_debug_mutex); } // namespace art diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 659c55a289..e41667a5bf 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -549,7 +549,11 @@ void JitCodeCache::FreeCode(const void* code_ptr) { uintptr_t allocation = FromCodeToAllocation(code_ptr); // Notify native debugger that we are about to remove the code. // It does nothing if we are not using native debugger. - DeleteJITCodeEntryForAddress(reinterpret_cast<uintptr_t>(code_ptr)); + MutexLock mu(Thread::Current(), g_jit_debug_mutex); + JITCodeEntry* entry = GetJITCodeEntry(reinterpret_cast<uintptr_t>(code_ptr)); + if (entry != nullptr) { + DecrementJITCodeEntryRefcount(entry, reinterpret_cast<uintptr_t>(code_ptr)); + } if (OatQuickMethodHeader::FromCodePointer(code_ptr)->IsOptimized()) { FreeData(GetRootTable(code_ptr)); } // else this is a JNI stub without any data. diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index fd80aaeaf7..e22726b79b 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -173,6 +173,7 @@ enum { DEBUG_JAVA_DEBUGGABLE = 1 << 8, DISABLE_VERIFIER = 1 << 9, ONLY_USE_SYSTEM_OAT_FILES = 1 << 10, + DISABLE_HIDDEN_API_CHECKS = 1 << 11, }; static uint32_t EnableDebugFeatures(uint32_t runtime_flags) { @@ -284,6 +285,11 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env, runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES; } + if ((runtime_flags & DISABLE_HIDDEN_API_CHECKS) != 0) { + Runtime::Current()->DisableHiddenApiChecks(); + runtime_flags &= ~DISABLE_HIDDEN_API_CHECKS; + } + if (runtime_flags != 0) { LOG(ERROR) << StringPrintf("Unknown bits set in runtime_flags: %#x", runtime_flags); } @@ -331,6 +337,9 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env, } } + DCHECK(!is_system_server || !Runtime::Current()->AreHiddenApiChecksEnabled()) + << "SystemServer should be forked with DISABLE_HIDDEN_API_CHECKS"; + if (instruction_set != nullptr && !is_system_server) { ScopedUtfChars isa_string(env, instruction_set); InstructionSet isa = GetInstructionSetFromString(isa_string.c_str()); diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 2f60162c77..92eb703338 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -330,6 +330,8 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .Define("-Xtarget-sdk-version:_") .WithType<int>() .IntoKey(M::TargetSdkVersion) + .Define("-Xno-hidden-api-checks") + .IntoKey(M::NoHiddenApiChecks) .Ignore({ "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa", "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_", diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 007d361976..33bebe0887 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -265,6 +265,7 @@ Runtime::Runtime() oat_file_manager_(nullptr), is_low_memory_mode_(false), safe_mode_(false), + do_hidden_api_checks_(false), dump_native_stack_on_sig_quit_(true), pruned_dalvik_cache_(false), // Initially assume we perceive jank in case the process state is never updated. @@ -1168,6 +1169,10 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { target_sdk_version_ = runtime_options.GetOrDefault(Opt::TargetSdkVersion); + if (runtime_options.Exists(Opt::NoHiddenApiChecks)) { + do_hidden_api_checks_ = false; + } + no_sig_chain_ = runtime_options.Exists(Opt::NoSigChain); force_native_bridge_ = runtime_options.Exists(Opt::ForceNativeBridge); diff --git a/runtime/runtime.h b/runtime/runtime.h index 6d2887cc42..022a1be124 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -520,6 +520,14 @@ class Runtime { bool IsVerificationEnabled() const; bool IsVerificationSoftFail() const; + void DisableHiddenApiChecks() { + do_hidden_api_checks_ = false; + } + + bool AreHiddenApiChecksEnabled() const { + return do_hidden_api_checks_; + } + bool IsDexFileFallbackEnabled() const { return allow_dex_file_fallback_; } @@ -957,6 +965,9 @@ class Runtime { // Whether the application should run in safe mode, that is, interpreter only. bool safe_mode_; + // Whether access checks on hidden API should be performed. + bool do_hidden_api_checks_; + // Whether threads should dump their native stack on SIGQUIT. bool dump_native_stack_on_sig_quit_; diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index 3996989920..6e1a68b07d 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -119,6 +119,7 @@ RUNTIME_OPTIONS_KEY (std::vector<std::string>, \ RUNTIME_OPTIONS_KEY (verifier::VerifyMode, \ Verify, verifier::VerifyMode::kEnable) RUNTIME_OPTIONS_KEY (int, TargetSdkVersion, Runtime::kUnsetSdkVersion) +RUNTIME_OPTIONS_KEY (Unit, NoHiddenApiChecks) RUNTIME_OPTIONS_KEY (std::string, NativeBridge) RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10) RUNTIME_OPTIONS_KEY (Unit, NoDexFileFallback) diff --git a/test/004-NativeAllocations/src-art/Main.java b/test/004-NativeAllocations/src-art/Main.java index 29f907de0b..6b1c48d286 100644 --- a/test/004-NativeAllocations/src-art/Main.java +++ b/test/004-NativeAllocations/src-art/Main.java @@ -82,8 +82,8 @@ public class Main { // case of blocking registerNativeAllocation. private static void triggerBlockingRegisterNativeAllocation() throws Exception { long maxMem = Runtime.getRuntime().maxMemory(); - int size = (int)(maxMem / 32); - int allocationCount = 256; + int size = (int)(maxMem / 5); + int allocationCount = 10; long total = 0; for (int i = 0; i < allocationCount; ++i) { @@ -111,7 +111,7 @@ public class Main { synchronized (deadlockLock) { allocateDeadlockingFinalizer(); while (!aboutToDeadlock) { - checkRegisterNativeAllocation(); + Runtime.getRuntime().gc(); } // Do more allocations now that the finalizer thread is deadlocked so that we force diff --git a/test/071-dexfile-get-static-size/build b/test/071-dexfile-get-static-size/build index 0bba66d065..412ee6dd46 100755 --- a/test/071-dexfile-get-static-size/build +++ b/test/071-dexfile-get-static-size/build @@ -16,15 +16,13 @@ ./default-build "$@" -# Create and add as resources to the test jar file: +# Bundle with the test the following resources: # 1. test1.dex # 2. test2.dex # 3. test-jar.jar, containing test1.dex as classes.dex # 4. multi-jar.jar, containing test1.dex as classes.dex and test2.dex as classes2.dex mkdir test-jar -cp test1.dex test-jar/classes.dex -cp test2.dex test-jar/classes2.dex -zip -j test-jar.jar test-jar/classes.dex -zip -j multi-jar.jar test-jar/classes.dex test-jar/classes2.dex -jar uf ${TEST_NAME}.jar test1.dex test2.dex test-jar.jar multi-jar.jar - +cp res/test1.dex test-jar/classes.dex +cp res/test2.dex test-jar/classes2.dex +zip -j res/test-jar.jar test-jar/classes.dex +zip -j res/multi-jar.jar test-jar/classes.dex test-jar/classes2.dex diff --git a/test/071-dexfile-get-static-size/test1.dex b/test/071-dexfile-get-static-size/res/test1.dex Binary files differindex 84602d03c2..84602d03c2 100644 --- a/test/071-dexfile-get-static-size/test1.dex +++ b/test/071-dexfile-get-static-size/res/test1.dex diff --git a/test/071-dexfile-get-static-size/test2.dex b/test/071-dexfile-get-static-size/res/test2.dex Binary files differindex a07c46ef59..a07c46ef59 100644 --- a/test/071-dexfile-get-static-size/test2.dex +++ b/test/071-dexfile-get-static-size/res/test2.dex diff --git a/test/071-dexfile-get-static-size/src/Main.java b/test/071-dexfile-get-static-size/src/Main.java index 4bf453801e..8dbbba56c3 100644 --- a/test/071-dexfile-get-static-size/src/Main.java +++ b/test/071-dexfile-get-static-size/src/Main.java @@ -14,26 +14,9 @@ * limitations under the License. */ -import java.io.InputStream; -import java.io.OutputStream; -import java.io.FileOutputStream; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Main { - private static void extractResource(String resource, String filename) throws Exception { - ClassLoader loader = Main.class.getClassLoader(); - InputStream is = loader.getResourceAsStream(resource); - OutputStream os = new FileOutputStream(filename); - int read; - byte[] buf = new byte[4096]; - while ((read = is.read(buf)) >= 0) { - os.write(buf, 0, read); - } - is.close(); - os.close(); - } - private static long getDexFileSize(String filename) throws Exception { ClassLoader loader = Main.class.getClassLoader(); Class<?> DexFile = loader.loadClass("dalvik.system.DexFile"); @@ -47,8 +30,7 @@ public class Main { } private static void test(String resource) throws Exception { - String filename = System.getenv("DEX_LOCATION") + "/" + resource; - extractResource(resource, filename); + String filename = System.getenv("DEX_LOCATION") + "/res/" + resource; long size = getDexFileSize(filename); System.out.println("Size for " + resource + ": " + size); } diff --git a/test/README.md b/test/README.md index c68b40b135..350350e9e6 100644 --- a/test/README.md +++ b/test/README.md @@ -9,6 +9,8 @@ directory are compiled separately but to the same output directory; this can be used to exercise "API mismatch" situations by replacing class files created in the first pass. The "src-ex" directory is built separately, and is intended for exercising class loaders. +Resources can be stored in the "res" directory, which is distributed +together with the executable files. The gtests are in named directories and contain a .java source file. diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index 631b14afc8..5e40b86aa0 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -806,6 +806,10 @@ if [ "$HOST" = "n" ]; then if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then adb push profile $DEX_LOCATION fi + # Copy resource folder + if [ -d res ]; then + adb push res $DEX_LOCATION + fi else adb shell rm -r $DEX_LOCATION >/dev/null 2>&1 adb shell mkdir -p $DEX_LOCATION >/dev/null 2>&1 @@ -814,7 +818,10 @@ if [ "$HOST" = "n" ]; then if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then adb push profile $DEX_LOCATION >/dev/null 2>&1 fi - + # Copy resource folder + if [ -d res ]; then + adb push res $DEX_LOCATION >/dev/null 2>&1 + fi fi LD_LIBRARY_PATH=/data/$TEST_DIRECTORY/art/$ISA |