diff options
137 files changed, 1981 insertions, 643 deletions
diff --git a/Android.bp b/Android.bp index 4bcceffcd1..bb92e5f2f8 100644 --- a/Android.bp +++ b/Android.bp @@ -1,7 +1,6 @@ // TODO: These should be handled with transitive static library dependencies art_static_dependencies = [ // Note: the order is important because of static linking resolution. - "libdexfile", "libziparchive", "libnativehelper", "libnativebridge", @@ -36,6 +35,7 @@ subdirs = [ "dt_fd_forward", "dt_fd_forward/export", "imgdiag", + "libdexfile", "oatdump", "openjdkjvm", "openjdkjvmti", diff --git a/Android.mk b/Android.mk index 361ceecc2f..2489308c02 100644 --- a/Android.mk +++ b/Android.mk @@ -79,6 +79,7 @@ include $(art_path)/build/Android.cpplint.mk include $(art_path)/oatdump/Android.mk include $(art_path)/tools/Android.mk include $(art_path)/tools/ahat/Android.mk +include $(art_path)/tools/amm/Android.mk include $(art_path)/tools/dexfuzz/Android.mk include $(art_path)/libart_fake/Android.mk @@ -486,8 +487,10 @@ build-art-target-golem: dex2oat dalvikvm patchoat linker libstdc++ \ $(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \ $(TARGET_CORE_IMG_OUT_BASE).art \ $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art + # remove libartd.so and libdexfiled.so from public.libraries.txt because golem builds + # won't have it. sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt - # remove libartd.so from public.libraries.txt because golem builds won't have it. + sed -i '/libdexfiled.so/d' $(TARGET_OUT)/etc/public.libraries.txt ######################################################################## # Phony target for building what go/lem requires on host. diff --git a/benchmark/type-check/info.txt b/benchmark/type-check/info.txt new file mode 100644 index 0000000000..d14fb9685b --- /dev/null +++ b/benchmark/type-check/info.txt @@ -0,0 +1 @@ +Benchmarks for repeating check-cast and instance-of instructions in a loop. diff --git a/benchmark/type-check/src/TypeCheckBenchmark.java b/benchmark/type-check/src/TypeCheckBenchmark.java new file mode 100644 index 0000000000..96904d99b6 --- /dev/null +++ b/benchmark/type-check/src/TypeCheckBenchmark.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class TypeCheckBenchmark { + public void timeCheckCastLevel1ToLevel1(int count) { + Object[] arr = arr1; + for (int i = 0; i < count; ++i) { + Level1 l1 = (Level1) arr[i & 1023]; + } + } + + public void timeCheckCastLevel2ToLevel1(int count) { + Object[] arr = arr2; + for (int i = 0; i < count; ++i) { + Level1 l1 = (Level1) arr[i & 1023]; + } + } + + public void timeCheckCastLevel3ToLevel1(int count) { + Object[] arr = arr3; + for (int i = 0; i < count; ++i) { + Level1 l1 = (Level1) arr[i & 1023]; + } + } + + public void timeCheckCastLevel9ToLevel1(int count) { + Object[] arr = arr9; + for (int i = 0; i < count; ++i) { + Level1 l1 = (Level1) arr[i & 1023]; + } + } + + public void timeCheckCastLevel9ToLevel2(int count) { + Object[] arr = arr9; + for (int i = 0; i < count; ++i) { + Level2 l2 = (Level2) arr[i & 1023]; + } + } + + public void timeInstanceOfLevel1ToLevel1(int count) { + int sum = 0; + Object[] arr = arr1; + for (int i = 0; i < count; ++i) { + if (arr[i & 1023] instanceof Level1) { + ++sum; + } + } + result = sum; + } + + public void timeInstanceOfLevel2ToLevel1(int count) { + int sum = 0; + Object[] arr = arr2; + for (int i = 0; i < count; ++i) { + if (arr[i & 1023] instanceof Level1) { + ++sum; + } + } + result = sum; + } + + public void timeInstanceOfLevel3ToLevel1(int count) { + int sum = 0; + Object[] arr = arr3; + for (int i = 0; i < count; ++i) { + if (arr[i & 1023] instanceof Level1) { + ++sum; + } + } + result = sum; + } + + public void timeInstanceOfLevel9ToLevel1(int count) { + int sum = 0; + Object[] arr = arr9; + for (int i = 0; i < count; ++i) { + if (arr[i & 1023] instanceof Level1) { + ++sum; + } + } + result = sum; + } + + public void timeInstanceOfLevel9ToLevel2(int count) { + int sum = 0; + Object[] arr = arr9; + for (int i = 0; i < count; ++i) { + if (arr[i & 1023] instanceof Level2) { + ++sum; + } + } + result = sum; + } + + public static Object[] createArray(int level) { + try { + Class<?>[] ls = { + null, + Level1.class, + Level2.class, + Level3.class, + Level4.class, + Level5.class, + Level6.class, + Level7.class, + Level8.class, + Level9.class, + }; + Class<?> l = ls[level]; + Object[] array = new Object[1024]; + for (int i = 0; i < array.length; ++i) { + array[i] = l.newInstance(); + } + return array; + } catch (Exception unexpected) { + throw new Error("Initialization failure!"); + } + } + Object[] arr1 = createArray(1); + Object[] arr2 = createArray(2); + Object[] arr3 = createArray(3); + Object[] arr9 = createArray(9); + int result; +} + +class Level1 { } +class Level2 extends Level1 { } +class Level3 extends Level2 { } +class Level4 extends Level3 { } +class Level5 extends Level4 { } +class Level6 extends Level5 { } +class Level7 extends Level6 { } +class Level8 extends Level7 { } +class Level9 extends Level8 { } diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 8ba48be403..4a35ccfa13 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -333,6 +333,7 @@ ART_TEST_MODULES := \ art_dexoptanalyzer_tests \ art_hiddenapi_tests \ art_imgdiag_tests \ + art_libdexfile_tests \ art_oatdump_tests \ art_patchoat_tests \ art_profman_tests \ @@ -382,12 +383,14 @@ ART_VALGRIND_SUPPORTED_ARCH := arm arm64 x86_64 # Valgrind is not supported for x86 ifneq (,$(filter $(ART_VALGRIND_SUPPORTED_ARCH),$(TARGET_ARCH))) +art_vg_arch := $(if $(filter x86_64,$(TARGET_ARCH)),amd64,$(TARGET_ARCH)) ART_VALGRIND_TARGET_DEPENDENCIES += \ $(TARGET_OUT_EXECUTABLES)/valgrind \ - $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/memcheck-$(TARGET_ARCH)-linux \ - $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_core-$(TARGET_ARCH)-linux.so \ - $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_memcheck-$(TARGET_ARCH)-linux.so \ + $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/memcheck-$(art_vg_arch)-linux \ + $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_core-$(art_vg_arch)-linux.so \ + $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/vgpreload_memcheck-$(art_vg_arch)-linux.so \ $(TARGET_OUT_SHARED_LIBRARIES)/valgrind/default.supp +art_vg_arch := endif ifdef TARGET_2ND_ARCH diff --git a/compiler/Android.bp b/compiler/Android.bp index 453965947d..ba08d7975b 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -184,7 +184,6 @@ art_cc_defaults { }, generated_sources: ["art_compiler_operator_srcs"], shared_libs: [ - "libdexfile", "libbase", "libcutils", // for atrace. "liblzma", @@ -250,6 +249,7 @@ art_cc_library { }, shared_libs: [ "libart", + "libdexfile", ], pgo: { @@ -295,6 +295,7 @@ art_cc_library { }, shared_libs: [ "libartd", + "libdexfiled", ], } diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 64a1eccf60..a38e2717cf 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -960,14 +960,18 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction, HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod, dchecked_integral_cast<uint64_t>(string_init_entry_point) }; - MethodReference target_method(dex_file_, method_idx); + ScopedObjectAccess soa(Thread::Current()); + MethodReference target_method(resolved_method->GetDexFile(), + resolved_method->GetDexMethodIndex()); + // We pass null for the resolved_method to ensure optimizations + // don't rely on it. HInvoke* invoke = new (allocator_) HInvokeStaticOrDirect( allocator_, number_of_arguments - 1, DataType::Type::kReference /*return_type */, dex_pc, method_idx, - nullptr, + nullptr /* resolved_method */, dispatch_info, invoke_type, target_method, diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 43ca2cf874..f91d37b3ac 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -4567,7 +4567,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { kFieldClinitCheckRequirementSize>; // Cached values of the resolved method, to avoid needing the mutator lock. - MethodReference target_method_; + const MethodReference target_method_; DispatchInfo dispatch_info_; }; std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 8bb124e066..67a61fc01d 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -537,14 +537,13 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst Thread* self = Thread::Current(); StackHandleScope<2> hs(self); const DexFile& dex_file = *invoke->GetTargetMethod().dex_file; + uint32_t dex_method_index = invoke->GetTargetMethod().index; Handle<mirror::DexCache> dex_cache( hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_))); - // Use a null loader. We should probably use the compiling method's class loader, - // but then we would need to pass it to RTPVisitor just for this debug check. Since - // the method is from the String class, the null loader is good enough. + // Use a null loader, the target method is in a boot classpath dex file. Handle<mirror::ClassLoader> loader(hs.NewHandle<mirror::ClassLoader>(nullptr)); ArtMethod* method = cl->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>( - invoke->GetDexMethodIndex(), dex_cache, loader, /* referrer */ nullptr, kDirect); + dex_method_index, dex_cache, loader, /* referrer */ nullptr, kDirect); DCHECK(method != nullptr); mirror::Class* declaring_class = method->GetDeclaringClass(); DCHECK(declaring_class != nullptr); diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index ab06ddda2d..dd16ba4909 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -152,7 +152,7 @@ art_cc_binary { "libartd-compiler", "libartd-dexlayout", "libartd", - "libdexfile", + "libdexfiled", "libbase", "liblz4", "libsigchain", @@ -185,6 +185,7 @@ art_cc_binary { "libart-compiler", "libart-dexlayout", "libart", + "libdexfile", "libvixl-arm", "libvixl-arm64", ] + art_static_dependencies, @@ -216,6 +217,7 @@ art_cc_binary { "libartd-compiler", "libartd-dexlayout", "libartd", + "libdexfiled", "libvixld-arm", "libvixld-arm64", ] + art_static_dependencies, diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index 73eaad47a1..42d228078c 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -2364,7 +2364,7 @@ void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { FixupClassVisitor visitor(this, copy); ObjPtr<mirror::Object>(orig)->VisitReferences(visitor, visitor); - if (compile_app_image_) { + if (kBitstringSubtypeCheckEnabled && compile_app_image_) { // When we call SubtypeCheck::EnsureInitialize, it Assigns new bitstring // values to the parent of that class. // diff --git a/dexdump/Android.bp b/dexdump/Android.bp index f6b7a6b68a..eca08448bc 100644 --- a/dexdump/Android.bp +++ b/dexdump/Android.bp @@ -45,6 +45,7 @@ art_cc_binary { host_supported: true, device_supported: false, static_libs: [ + "libdexfile", "libbase", ] + art_static_dependencies, target: { diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc index 8778b129c5..61a1209ed1 100644 --- a/dexdump/dexdump.cc +++ b/dexdump/dexdump.cc @@ -34,19 +34,14 @@ #include "dexdump.h" -#include <fcntl.h> #include <inttypes.h> #include <stdio.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <iostream> #include <memory> #include <sstream> #include <vector> +#include "android-base/file.h" #include "android-base/logging.h" #include "android-base/stringprintf.h" @@ -1879,34 +1874,6 @@ static void processDexFile(const char* fileName, } } -static bool openAndMapFile(const char* fileName, - const uint8_t** base, - size_t* size, - std::string* error_msg) { - int fd = open(fileName, O_RDONLY); - if (fd < 0) { - *error_msg = "open failed"; - return false; - } - struct stat st; - if (fstat(fd, &st) < 0) { - *error_msg = "stat failed"; - return false; - } - *size = st.st_size; - if (*size == 0) { - *error_msg = "size == 0"; - return false; - } - void* addr = mmap(nullptr /*addr*/, *size, PROT_READ, MAP_PRIVATE, fd, 0 /*offset*/); - if (addr == MAP_FAILED) { - *error_msg = "mmap failed"; - return false; - } - *base = reinterpret_cast<const uint8_t*>(addr); - return true; -} - /* * Processes a single file (either direct .dex or indirect .zip/.jar/.apk). */ @@ -1918,17 +1885,22 @@ int processFile(const char* fileName) { // If the file is not a .dex file, the function tries .zip/.jar/.apk files, // all of which are Zip archives with "classes.dex" inside. const bool kVerifyChecksum = !gOptions.ignoreBadChecksum; - const uint8_t* base = nullptr; - size_t size = 0; - std::string error_msg; - if (!openAndMapFile(fileName, &base, &size, &error_msg)) { - LOG(ERROR) << error_msg; + std::string content; + // TODO: add an api to android::base to read a std::vector<uint8_t>. + if (!android::base::ReadFileToString(fileName, &content)) { + LOG(ERROR) << "ReadFileToString failed"; return -1; } const DexFileLoader dex_file_loader; + std::string error_msg; std::vector<std::unique_ptr<const DexFile>> dex_files; - if (!dex_file_loader.OpenAll( - base, size, fileName, /*verify*/ true, kVerifyChecksum, &error_msg, &dex_files)) { + if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), + content.size(), + fileName, + /*verify*/ true, + kVerifyChecksum, + &error_msg, + &dex_files)) { // Display returned error message to user. Note that this error behavior // differs from the error messages shown by the original Dalvik dexdump. LOG(ERROR) << error_msg; diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp index 3ea7f4ba82..bea61d0c71 100644 --- a/dexlayout/Android.bp +++ b/dexlayout/Android.bp @@ -27,7 +27,6 @@ art_cc_defaults { ], export_include_dirs: ["."], shared_libs: [ - "libdexfile", "libbase", ], static_libs: ["libz"], @@ -36,7 +35,10 @@ art_cc_defaults { art_cc_library { name: "libart-dexlayout", defaults: ["libart-dexlayout-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], pgo: { instrumentation: true, @@ -51,7 +53,10 @@ art_cc_library { "libart-dexlayout-defaults", "art_debug_defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } cc_defaults { diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc index 31a146d90e..6a50258570 100644 --- a/dexlist/dexlist.cc +++ b/dexlist/dexlist.cc @@ -23,15 +23,11 @@ * List all methods in all concrete classes in one or more DEX files. */ -#include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> +#include <android-base/file.h> #include <android-base/logging.h> #include "dex/code_item_accessors-inl.h" @@ -170,34 +166,6 @@ void dumpClass(const DexFile* pDexFile, u4 idx) { } } -static bool openAndMapFile(const char* fileName, - const uint8_t** base, - size_t* size, - std::string* error_msg) { - int fd = open(fileName, O_RDONLY); - if (fd < 0) { - *error_msg = "open failed"; - return false; - } - struct stat st; - if (fstat(fd, &st) < 0) { - *error_msg = "stat failed"; - return false; - } - *size = st.st_size; - if (*size == 0) { - *error_msg = "size == 0"; - return false; - } - void* addr = mmap(nullptr /*addr*/, *size, PROT_READ, MAP_PRIVATE, fd, 0 /*offset*/); - if (addr == MAP_FAILED) { - *error_msg = "mmap failed"; - return false; - } - *base = reinterpret_cast<const uint8_t*>(addr); - return true; -} - /* * Processes a single file (either direct .dex or indirect .zip/.jar/.apk). */ @@ -205,17 +173,22 @@ static int processFile(const char* fileName) { // If the file is not a .dex file, the function tries .zip/.jar/.apk files, // all of which are Zip archives with "classes.dex" inside. static constexpr bool kVerifyChecksum = true; - const uint8_t* base = nullptr; - size_t size = 0; - std::string error_msg; - if (!openAndMapFile(fileName, &base, &size, &error_msg)) { - LOG(ERROR) << error_msg; + std::string content; + // TODO: add an api to android::base to read a std::vector<uint8_t>. + if (!android::base::ReadFileToString(fileName, &content)) { + LOG(ERROR) << "ReadFileToString failed"; return -1; } std::vector<std::unique_ptr<const DexFile>> dex_files; + std::string error_msg; const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll( - base, size, fileName, /*verify*/ true, kVerifyChecksum, &error_msg, &dex_files)) { + if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), + content.size(), + fileName, + /*verify*/ true, + kVerifyChecksum, + &error_msg, + &dex_files)) { LOG(ERROR) << error_msg; return -1; } diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp new file mode 100644 index 0000000000..90c603f290 --- /dev/null +++ b/libdexfile/Android.bp @@ -0,0 +1,125 @@ +// +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_defaults { + name: "libdexfile_defaults", + defaults: ["art_defaults"], + host_supported: true, + srcs: [ + "dex/compact_dex_debug_info.cc", + "dex/compact_dex_file.cc", + "dex/descriptors_names.cc", + "dex/dex_file.cc", + "dex/dex_file_exception_helpers.cc", + "dex/dex_file_loader.cc", + "dex/dex_file_tracking_registrar.cc", + "dex/dex_file_verifier.cc", + "dex/dex_instruction.cc", + "dex/modifiers.cc", + "dex/standard_dex_file.cc", + "dex/utf.cc", + ], + + target: { + android: { + static_libs: [ + "libziparchive", + "libz", + "libbase", + ], + shared_libs: [ + "libutils", + ], + }, + host: { + shared_libs: [ + "libziparchive", + "libz", + ], + }, + }, + generated_sources: ["dexfile_operator_srcs"], + shared_libs: [ + "liblog", + // For common macros. + "libbase", + "libz", + ], + header_libs: [ + // This is needed to resolve the base/ header file inclusions here. + // TODO: move those headers to art/ rather than under runtime. + "libart_runtime_headers", + ], + export_include_dirs: ["."], + export_shared_lib_headers: [ + "libbase", + ], +} + +gensrcs { + name: "dexfile_operator_srcs", + cmd: "$(location generate-operator-out.py) art/libdexfile $(in) > $(out)", + tool_files: ["generate-operator-out.py"], + srcs: [ + "dex/dex_file.h", + "dex/dex_instruction.h", + "dex/dex_instruction_utils.h", + "dex/invoke_type.h", + ], + output_extension: "operator_out.cc", +} + +// TODO: add build support for libdexfiled, as we use DCHECK, etc. +art_cc_library { + name: "libdexfile", + defaults: ["libdexfile_defaults"], + // Leave the symbols in the shared library so that stack unwinders can + // produce meaningful name resolution. + strip: { + keep_symbols: true, + }, +} + +art_cc_library { + name: "libdexfiled", + defaults: [ + "art_debug_defaults", + "libdexfile_defaults", + ], +} + +art_cc_test { + name: "art_libdexfile_tests", + defaults: [ + "art_gtest_defaults", + ], + srcs: [ + "dex/code_item_accessors_test.cc", + "dex/compact_dex_debug_info_test.cc", + "dex/compact_dex_file_test.cc", + "dex/dex_file_loader_test.cc", + "dex/dex_file_verifier_test.cc", + "dex/dex_instruction_test.cc", + "dex/utf_test.cc", + ], + shared_libs: [ + "libbacktrace", + "libziparchive", + ], + include_dirs: [ + "external/zlib", + ], +} diff --git a/runtime/dex/base64_test_util.h b/libdexfile/dex/base64_test_util.h index 0657f9fd01..5d73759af3 100644 --- a/runtime/dex/base64_test_util.h +++ b/libdexfile/dex/base64_test_util.h @@ -14,16 +14,17 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_ -#define ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_ +#ifndef ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_ +#define ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_ -#include <base/logging.h> #include <stdint.h> #include <stdlib.h> #include <memory> #include <vector> +#include <android-base/logging.h> + namespace art { static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) { @@ -96,4 +97,4 @@ static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) { } // namespace art -#endif // ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_ +#endif // ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_ diff --git a/runtime/dex/code_item_accessors-inl.h b/libdexfile/dex/code_item_accessors-inl.h index 9c39935d3b..c166f5f19e 100644 --- a/runtime/dex/code_item_accessors-inl.h +++ b/libdexfile/dex/code_item_accessors-inl.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_ -#define ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_ +#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ +#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ #include "code_item_accessors.h" @@ -201,4 +201,4 @@ inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(bool is_static, } // namespace art -#endif // ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_INL_H_ +#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_INL_H_ diff --git a/runtime/dex/code_item_accessors.h b/libdexfile/dex/code_item_accessors.h index beb78f6e4f..ba7c126ed8 100644 --- a/runtime/dex/code_item_accessors.h +++ b/libdexfile/dex/code_item_accessors.h @@ -16,10 +16,9 @@ // TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump. -#ifndef ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_ -#define ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_ +#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ +#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ -#include "base/mutex.h" #include "compact_dex_file.h" #include "dex_file.h" #include "dex_instruction_iterator.h" @@ -164,4 +163,4 @@ class CodeItemDebugInfoAccessor : public CodeItemDataAccessor { } // namespace art -#endif // ART_RUNTIME_DEX_CODE_ITEM_ACCESSORS_H_ +#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ diff --git a/runtime/dex/code_item_accessors_test.cc b/libdexfile/dex/code_item_accessors_test.cc index 2bb4dde649..2bb4dde649 100644 --- a/runtime/dex/code_item_accessors_test.cc +++ b/libdexfile/dex/code_item_accessors_test.cc diff --git a/runtime/dex/compact_dex_debug_info.cc b/libdexfile/dex/compact_dex_debug_info.cc index 19495ca92c..19495ca92c 100644 --- a/runtime/dex/compact_dex_debug_info.cc +++ b/libdexfile/dex/compact_dex_debug_info.cc diff --git a/runtime/dex/compact_dex_debug_info.h b/libdexfile/dex/compact_dex_debug_info.h index 1aff75879e..bfd0bbe65c 100644 --- a/runtime/dex/compact_dex_debug_info.h +++ b/libdexfile/dex/compact_dex_debug_info.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_ -#define ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_ +#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_ +#define ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_ #include <cstdint> #include <vector> @@ -62,4 +62,4 @@ class CompactDexDebugInfoOffsetTable { } // namespace art -#endif // ART_RUNTIME_DEX_COMPACT_DEX_DEBUG_INFO_H_ +#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_DEBUG_INFO_H_ diff --git a/runtime/dex/compact_dex_debug_info_test.cc b/libdexfile/dex/compact_dex_debug_info_test.cc index 3267612443..7911a86539 100644 --- a/runtime/dex/compact_dex_debug_info_test.cc +++ b/libdexfile/dex/compact_dex_debug_info_test.cc @@ -16,7 +16,7 @@ #include <vector> -#include "base/logging.h" +#include <android-base/logging.h> #include "dex/compact_dex_debug_info.h" #include "gtest/gtest.h" @@ -74,7 +74,7 @@ TEST(CompactDexDebugInfoTest, TestBuildAndAccess) { /*out*/ &table_offset); EXPECT_LT(sorted_data.size(), data.size()); { - ScopedLogSeverity sls(LogSeverity::INFO); + android::base::ScopedLogSeverity sls(android::base::LogSeverity::INFO); LOG(INFO) << "raw size " << before_size << " table size " << data.size() << " sorted table size " << sorted_data.size(); diff --git a/runtime/dex/compact_dex_file.cc b/libdexfile/dex/compact_dex_file.cc index ce289d4d7b..ce289d4d7b 100644 --- a/runtime/dex/compact_dex_file.cc +++ b/libdexfile/dex/compact_dex_file.cc diff --git a/runtime/dex/compact_dex_file.h b/libdexfile/dex/compact_dex_file.h index 31aeb27872..47b170c4a8 100644 --- a/runtime/dex/compact_dex_file.h +++ b/libdexfile/dex/compact_dex_file.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_ -#define ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_ +#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_ +#define ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_ #include "base/casts.h" #include "dex_file.h" @@ -288,4 +288,4 @@ class CompactDexFile : public DexFile { } // namespace art -#endif // ART_RUNTIME_DEX_COMPACT_DEX_FILE_H_ +#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_ diff --git a/runtime/dex/compact_dex_file_test.cc b/libdexfile/dex/compact_dex_file_test.cc index 517c5873ed..517c5873ed 100644 --- a/runtime/dex/compact_dex_file_test.cc +++ b/libdexfile/dex/compact_dex_file_test.cc diff --git a/runtime/dex/compact_dex_level.h b/libdexfile/dex/compact_dex_level.h index de9ca3c783..599ec4db19 100644 --- a/runtime/dex/compact_dex_level.h +++ b/libdexfile/dex/compact_dex_level.h @@ -14,12 +14,11 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_ -#define ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_ +#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_ +#define ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_ #include <string> -#include "base/macros.h" #include "dex_file.h" namespace art { @@ -47,4 +46,4 @@ static constexpr CompactDexLevel kDefaultCompactDexLevel = ART_DEFAULT_COMPACT_D } // namespace art -#endif // ART_RUNTIME_DEX_COMPACT_DEX_LEVEL_H_ +#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_LEVEL_H_ diff --git a/runtime/dex/compact_dex_utils.h b/libdexfile/dex/compact_dex_utils.h index 1c7e9514fd..c88b799e1f 100644 --- a/runtime/dex/compact_dex_utils.h +++ b/libdexfile/dex/compact_dex_utils.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_ -#define ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_ +#ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_ +#define ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_ #include <vector> @@ -34,4 +34,4 @@ static inline void AlignmentPadVector(std::vector<T, Allocator<T>>* dest, } // namespace art -#endif // ART_RUNTIME_DEX_COMPACT_DEX_UTILS_H_ +#endif // ART_LIBDEXFILE_DEX_COMPACT_DEX_UTILS_H_ diff --git a/runtime/dex/descriptors_names.cc b/libdexfile/dex/descriptors_names.cc index 8124e7256f..8124e7256f 100644 --- a/runtime/dex/descriptors_names.cc +++ b/libdexfile/dex/descriptors_names.cc diff --git a/runtime/dex/descriptors_names.h b/libdexfile/dex/descriptors_names.h index 22e9573556..10738eead0 100644 --- a/runtime/dex/descriptors_names.h +++ b/libdexfile/dex/descriptors_names.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_ -#define ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_ +#ifndef ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_ +#define ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_ #include <string> @@ -60,4 +60,4 @@ bool IsValidMemberName(const char* s); } // namespace art -#endif // ART_RUNTIME_DEX_DESCRIPTORS_NAMES_H_ +#endif // ART_LIBDEXFILE_DEX_DESCRIPTORS_NAMES_H_ diff --git a/runtime/dex_cache_resolved_classes.h b/libdexfile/dex/dex_cache_resolved_classes.h index ca6afc5b92..4c9acbf118 100644 --- a/runtime/dex_cache_resolved_classes.h +++ b/libdexfile/dex/dex_cache_resolved_classes.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_ -#define ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_ +#define ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_ #include <string> #include <unordered_set> @@ -90,4 +90,4 @@ inline bool operator<(const DexCacheResolvedClasses& a, const DexCacheResolvedCl } // namespace art -#endif // ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_ diff --git a/runtime/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h index aa53daac35..c86e879a76 100644 --- a/runtime/dex/dex_file-inl.h +++ b/libdexfile/dex/dex_file-inl.h @@ -14,10 +14,9 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_INL_H_ -#define ART_RUNTIME_DEX_DEX_FILE_INL_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_ -#include "base/bit_utils.h" #include "base/casts.h" #include "base/stringpiece.h" #include "compact_dex_file.h" @@ -518,4 +517,4 @@ inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator& } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_INL_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_ diff --git a/runtime/dex/dex_file.cc b/libdexfile/dex/dex_file.cc index 18eb903551..6a704c152c 100644 --- a/runtime/dex/dex_file.cc +++ b/libdexfile/dex/dex_file.cc @@ -45,6 +45,21 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong"); static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial"); +void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) { + uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer()); + uint32_t new_flag = class_it.GetMemberAccessFlags(); + bool is_method = class_it.IsAtMethod(); + // Go back 1 uleb to start. + data = ReverseSearchUnsignedLeb128(data); + if (is_method) { + // Methods have another uleb field before the access flags + data = ReverseSearchUnsignedLeb128(data); + } + DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)), + new_flag); + UpdateUnsignedLeb128(data, new_flag); +} + uint32_t DexFile::CalculateChecksum() const { return CalculateChecksum(Begin(), Size()); } diff --git a/runtime/dex/dex_file.h b/libdexfile/dex/dex_file.h index cf8c840b59..a62ab62734 100644 --- a/runtime/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_H_ -#define ART_RUNTIME_DEX_DEX_FILE_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_H_ #include <memory> #include <string> @@ -35,6 +35,7 @@ namespace art { +class ClassDataItemIterator; class CompactDexFile; enum InvokeType : uint32_t; class MemMap; @@ -1000,6 +1001,9 @@ class DexFile { return container_.get(); } + // Changes the dex file pointed to by class_it to not have any hiddenapi flags. + static void UnHideAccessFlags(ClassDataItemIterator& class_it); + protected: // First Dex format version supporting default methods. static const uint32_t kDefaultMethodsVersion = 37; @@ -1440,4 +1444,4 @@ std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::Val } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_H_ diff --git a/runtime/dex/dex_file_exception_helpers.cc b/libdexfile/dex/dex_file_exception_helpers.cc index 8e597fd3dd..8e597fd3dd 100644 --- a/runtime/dex/dex_file_exception_helpers.cc +++ b/libdexfile/dex/dex_file_exception_helpers.cc diff --git a/runtime/dex/dex_file_exception_helpers.h b/libdexfile/dex/dex_file_exception_helpers.h index bd6cb7e747..a05fd68e86 100644 --- a/runtime/dex/dex_file_exception_helpers.h +++ b/libdexfile/dex/dex_file_exception_helpers.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ -#define ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ #include "dex_file.h" @@ -65,4 +65,4 @@ class CatchHandlerIterator { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_EXCEPTION_HELPERS_H_ diff --git a/runtime/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc index 2c75c5b5d9..2c75c5b5d9 100644 --- a/runtime/dex/dex_file_loader.cc +++ b/libdexfile/dex/dex_file_loader.cc diff --git a/runtime/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h index 508397cb00..41d9b1691b 100644 --- a/runtime/dex/dex_file_loader.h +++ b/libdexfile/dex/dex_file_loader.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_LOADER_H_ -#define ART_RUNTIME_DEX_DEX_FILE_LOADER_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ #include <cstdint> #include <memory> @@ -195,4 +195,4 @@ class DexFileLoader { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_LOADER_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ diff --git a/runtime/dex/dex_file_loader_test.cc b/libdexfile/dex/dex_file_loader_test.cc index ab5c3f9a26..ab5c3f9a26 100644 --- a/runtime/dex/dex_file_loader_test.cc +++ b/libdexfile/dex/dex_file_loader_test.cc diff --git a/runtime/dex/dex_file_reference.h b/libdexfile/dex/dex_file_reference.h index 6f882900c6..3ac778121a 100644 --- a/runtime/dex/dex_file_reference.h +++ b/libdexfile/dex/dex_file_reference.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_ -#define ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_ #include <cstdint> @@ -49,4 +49,4 @@ inline bool operator==(const DexFileReference& a, const DexFileReference& b) { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_REFERENCE_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_ diff --git a/runtime/dex/dex_file_tracking_registrar.cc b/libdexfile/dex/dex_file_tracking_registrar.cc index 78ea9c16cb..78ea9c16cb 100644 --- a/runtime/dex/dex_file_tracking_registrar.cc +++ b/libdexfile/dex/dex_file_tracking_registrar.cc diff --git a/runtime/dex/dex_file_tracking_registrar.h b/libdexfile/dex/dex_file_tracking_registrar.h index 71b8ed7bde..8b7716e729 100644 --- a/runtime/dex/dex_file_tracking_registrar.h +++ b/libdexfile/dex/dex_file_tracking_registrar.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ -#define ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ #include <deque> #include <tuple> @@ -78,4 +78,4 @@ void RegisterDexFile(const DexFile* dex_file); } // namespace dex } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_TRACKING_REGISTRAR_H_ diff --git a/runtime/dex/dex_file_types.h b/libdexfile/dex/dex_file_types.h index 2c508f9c99..2bb70ff261 100644 --- a/runtime/dex/dex_file_types.h +++ b/libdexfile/dex/dex_file_types.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_TYPES_H_ -#define ART_RUNTIME_DEX_DEX_FILE_TYPES_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_ #include <limits> #include <ostream> @@ -114,4 +114,4 @@ template<> struct hash<art::dex::TypeIndex> { } // namespace std -#endif // ART_RUNTIME_DEX_DEX_FILE_TYPES_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_ diff --git a/runtime/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc index 62667052ad..62667052ad 100644 --- a/runtime/dex/dex_file_verifier.cc +++ b/libdexfile/dex/dex_file_verifier.cc diff --git a/runtime/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h index 6cb5d4c629..c4982c24c9 100644 --- a/runtime/dex/dex_file_verifier.h +++ b/libdexfile/dex/dex_file_verifier.h @@ -14,12 +14,11 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_ -#define ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_ +#define ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_ #include <unordered_set> -#include "base/allocator.h" #include "base/hash_map.h" #include "dex_file.h" #include "dex_file_types.h" @@ -254,4 +253,4 @@ class DexFileVerifier { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_FILE_VERIFIER_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_FILE_VERIFIER_H_ diff --git a/runtime/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc index 1cd4b2c07b..1cd4b2c07b 100644 --- a/runtime/dex/dex_file_verifier_test.cc +++ b/libdexfile/dex/dex_file_verifier_test.cc diff --git a/runtime/dex/dex_instruction-inl.h b/libdexfile/dex/dex_instruction-inl.h index a6b8414e62..6bef18c85f 100644 --- a/runtime/dex/dex_instruction-inl.h +++ b/libdexfile/dex/dex_instruction-inl.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_ -#define ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_ +#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_ #include "dex_instruction.h" @@ -555,4 +555,4 @@ inline void Instruction::GetVarArgs(uint32_t arg[kMaxVarArgRegs], uint16_t inst_ } // namespace art -#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_INL_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_INL_H_ diff --git a/runtime/dex/dex_instruction.cc b/libdexfile/dex/dex_instruction.cc index 886218129e..886218129e 100644 --- a/runtime/dex/dex_instruction.cc +++ b/libdexfile/dex/dex_instruction.cc diff --git a/runtime/dex/dex_instruction.h b/libdexfile/dex/dex_instruction.h index de14ed3c41..c9533656d3 100644 --- a/runtime/dex/dex_instruction.h +++ b/libdexfile/dex/dex_instruction.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_H_ -#define ART_RUNTIME_DEX_DEX_INSTRUCTION_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ +#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ #include <android-base/logging.h> @@ -754,4 +754,4 @@ class NoReceiverInstructionOperands FINAL : public InstructionOperands { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ diff --git a/runtime/dex/dex_instruction_iterator.h b/libdexfile/dex/dex_instruction_iterator.h index c1b3118f85..db3ff95e02 100644 --- a/runtime/dex/dex_instruction_iterator.h +++ b/libdexfile/dex/dex_instruction_iterator.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_ -#define ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_ +#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_ #include <iterator> @@ -234,4 +234,4 @@ class SafeDexInstructionIterator : public DexInstructionIteratorBase { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_ITERATOR_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_ITERATOR_H_ diff --git a/runtime/dex/dex_instruction_list.h b/libdexfile/dex/dex_instruction_list.h index aa63fadb66..9f0aba421a 100644 --- a/runtime/dex/dex_instruction_list.h +++ b/libdexfile/dex/dex_instruction_list.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_ -#define ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_ +#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_ // V(opcode, instruction_code, name, format, index, flags, extended_flags, verifier_flags); #define DEX_INSTRUCTION_LIST(V) \ @@ -304,5 +304,5 @@ V(k4rcc) \ V(k51l) -#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_ -#undef ART_RUNTIME_DEX_DEX_INSTRUCTION_LIST_H_ // the guard in this file is just for cpplint +#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_ +#undef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_LIST_H_ // the guard in this file is just for cpplint diff --git a/runtime/dex/dex_instruction_test.cc b/libdexfile/dex/dex_instruction_test.cc index c944085b9e..c944085b9e 100644 --- a/runtime/dex/dex_instruction_test.cc +++ b/libdexfile/dex/dex_instruction_test.cc diff --git a/runtime/dex/dex_instruction_utils.h b/libdexfile/dex/dex_instruction_utils.h index 27501927e7..e7614ada31 100644 --- a/runtime/dex/dex_instruction_utils.h +++ b/libdexfile/dex/dex_instruction_utils.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_ -#define ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_ +#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ +#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ #include "dex_instruction.h" @@ -216,4 +216,4 @@ constexpr DexMemAccessType AGetOrAPutMemAccessType(Instruction::Code code) { } // namespace art -#endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_UTILS_H_ +#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_UTILS_H_ diff --git a/runtime/dex/invoke_type.h b/libdexfile/dex/invoke_type.h index 726d269a3e..9b3af673a8 100644 --- a/runtime/dex/invoke_type.h +++ b/libdexfile/dex/invoke_type.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_INVOKE_TYPE_H_ -#define ART_RUNTIME_DEX_INVOKE_TYPE_H_ +#ifndef ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_ +#define ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_ #include <iosfwd> @@ -35,4 +35,4 @@ std::ostream& operator<<(std::ostream& os, const InvokeType& rhs); } // namespace art -#endif // ART_RUNTIME_DEX_INVOKE_TYPE_H_ +#endif // ART_LIBDEXFILE_DEX_INVOKE_TYPE_H_ diff --git a/runtime/dex/modifiers.cc b/libdexfile/dex/modifiers.cc index 30daefb172..30daefb172 100644 --- a/runtime/dex/modifiers.cc +++ b/libdexfile/dex/modifiers.cc diff --git a/runtime/dex/modifiers.h b/libdexfile/dex/modifiers.h index 2998f602d4..2425a588df 100644 --- a/runtime/dex/modifiers.h +++ b/libdexfile/dex/modifiers.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_MODIFIERS_H_ -#define ART_RUNTIME_DEX_MODIFIERS_H_ +#ifndef ART_LIBDEXFILE_DEX_MODIFIERS_H_ +#define ART_LIBDEXFILE_DEX_MODIFIERS_H_ #include <stdint.h> @@ -144,5 +144,5 @@ std::string PrettyJavaAccessFlags(uint32_t access_flags); } // namespace art -#endif // ART_RUNTIME_DEX_MODIFIERS_H_ +#endif // ART_LIBDEXFILE_DEX_MODIFIERS_H_ diff --git a/runtime/dex/standard_dex_file.cc b/libdexfile/dex/standard_dex_file.cc index f7317eb997..f7317eb997 100644 --- a/runtime/dex/standard_dex_file.cc +++ b/libdexfile/dex/standard_dex_file.cc diff --git a/runtime/dex/standard_dex_file.h b/libdexfile/dex/standard_dex_file.h index e0e9f2f11c..9b13caa2be 100644 --- a/runtime/dex/standard_dex_file.h +++ b/libdexfile/dex/standard_dex_file.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_ -#define ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_ +#ifndef ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_ +#define ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_ #include <iosfwd> @@ -115,4 +115,4 @@ class StandardDexFile : public DexFile { } // namespace art -#endif // ART_RUNTIME_DEX_STANDARD_DEX_FILE_H_ +#endif // ART_LIBDEXFILE_DEX_STANDARD_DEX_FILE_H_ diff --git a/runtime/dex/utf-inl.h b/libdexfile/dex/utf-inl.h index 4f626a8580..5355766aae 100644 --- a/runtime/dex/utf-inl.h +++ b/libdexfile/dex/utf-inl.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_UTF_INL_H_ -#define ART_RUNTIME_DEX_UTF_INL_H_ +#ifndef ART_LIBDEXFILE_DEX_UTF_INL_H_ +#define ART_LIBDEXFILE_DEX_UTF_INL_H_ #include "utf.h" @@ -96,4 +96,4 @@ inline int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* u } // namespace art -#endif // ART_RUNTIME_DEX_UTF_INL_H_ +#endif // ART_LIBDEXFILE_DEX_UTF_INL_H_ diff --git a/runtime/dex/utf.cc b/libdexfile/dex/utf.cc index 772a610140..772a610140 100644 --- a/runtime/dex/utf.cc +++ b/libdexfile/dex/utf.cc diff --git a/runtime/dex/utf.h b/libdexfile/dex/utf.h index 4adfc4af8c..c86b389175 100644 --- a/runtime/dex/utf.h +++ b/libdexfile/dex/utf.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_DEX_UTF_H_ -#define ART_RUNTIME_DEX_UTF_H_ +#ifndef ART_LIBDEXFILE_DEX_UTF_H_ +#define ART_LIBDEXFILE_DEX_UTF_H_ #include "base/macros.h" @@ -132,4 +132,4 @@ std::string PrintableString(const char* utf8); } // namespace art -#endif // ART_RUNTIME_DEX_UTF_H_ +#endif // ART_LIBDEXFILE_DEX_UTF_H_ diff --git a/runtime/dex/utf_test.cc b/libdexfile/dex/utf_test.cc index d2f22d16ef..d2f22d16ef 100644 --- a/runtime/dex/utf_test.cc +++ b/libdexfile/dex/utf_test.cc diff --git a/libdexfile/generate-operator-out.py b/libdexfile/generate-operator-out.py new file mode 120000 index 0000000000..cc291d20c1 --- /dev/null +++ b/libdexfile/generate-operator-out.py @@ -0,0 +1 @@ +../tools/generate-operator-out.py
\ No newline at end of file diff --git a/oatdump/Android.bp b/oatdump/Android.bp index c93c172eb4..012100d470 100644 --- a/oatdump/Android.bp +++ b/oatdump/Android.bp @@ -51,7 +51,7 @@ art_cc_binary { "libartd", "libartd-compiler", "libartd-disassembler", - "libdexfile", + "libdexfiled", "libbase", ], } @@ -76,6 +76,7 @@ art_cc_binary { ], static_libs: [ "libart", + "libdexfile", "libart-compiler", "libart-disassembler", "libvixl-arm", @@ -106,6 +107,7 @@ art_cc_binary { ], static_libs: [ "libartd", + "libdexfiled", "libartd-compiler", "libartd-disassembler", "libvixld-arm", diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 6c9f569b19..82bb88a5d5 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -2394,9 +2394,11 @@ class ImageDumper { } else if (obj->IsClass()) { ObjPtr<mirror::Class> klass = obj->AsClass(); - os << "SUBTYPE_CHECK_BITS: "; - SubtypeCheck<ObjPtr<mirror::Class>>::Dump(klass, os); - os << "\n"; + if (kBitstringSubtypeCheckEnabled) { + os << "SUBTYPE_CHECK_BITS: "; + SubtypeCheck<ObjPtr<mirror::Class>>::Dump(klass, os); + os << "\n"; + } if (klass->NumStaticFields() != 0) { os << "STATICS:\n"; diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp index 1500bcae24..1553b78f46 100644 --- a/openjdkjvmti/Android.bp +++ b/openjdkjvmti/Android.bp @@ -58,7 +58,6 @@ cc_defaults { "libopenjdkjvmti_headers", ], shared_libs: [ - "libdexfile", "libbase", ], } @@ -70,6 +69,7 @@ art_cc_library { "libart", "libart-compiler", "libart-dexlayout", + "libdexfile", ], } @@ -83,5 +83,6 @@ art_cc_library { "libartd", "libartd-compiler", "libartd-dexlayout", + "libdexfiled", ], } diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc index 427d87eedf..90c64492d9 100644 --- a/openjdkjvmti/fixed_up_dex_file.cc +++ b/openjdkjvmti/fixed_up_dex_file.cc @@ -40,6 +40,7 @@ #include "dex/compact_dex_level.h" #include "dex_to_dex_decompiler.h" #include "dexlayout.h" +#include "leb128.h" #include "oat_file.h" #include "vdex_file.h" @@ -50,21 +51,41 @@ static void RecomputeDexChecksum(art::DexFile* dex_file) { dex_file->CalculateChecksum(); } -static void DoDexUnquicken(const art::DexFile& new_dex_file, - const art::DexFile& original_dex_file) { +static void UnhideApis(const art::DexFile& target_dex_file) { + for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) { + const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i)); + if (class_data != nullptr) { + for (art::ClassDataItemIterator class_it(target_dex_file, class_data); + class_it.HasNext(); + class_it.Next()) { + art::DexFile::UnHideAccessFlags(class_it); + } + } + } +} + +static const art::VdexFile* GetVdex(const art::DexFile& original_dex_file) { const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile(); if (oat_dex == nullptr) { - return; + return nullptr; } const art::OatFile* oat_file = oat_dex->GetOatFile(); if (oat_file == nullptr) { - return; + return nullptr; } - const art::VdexFile* vdex = oat_file->GetVdexFile(); - if (vdex == nullptr) { - return; + return oat_file->GetVdexFile(); +} + +static void DoDexUnquicken(const art::DexFile& new_dex_file, + const art::DexFile& original_dex_file) { + const art::VdexFile* vdex = GetVdex(original_dex_file); + if (vdex != nullptr) { + vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true); + } else { + // The dex file isn't quickened since it is being used directly. We might still have hiddenapis + // so we need to get rid of those. + UnhideApis(new_dex_file); } - vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true); } static void DCheckVerifyDexFile(const art::DexFile& dex) { diff --git a/profman/Android.bp b/profman/Android.bp index 6592b9dec0..163be2b64f 100644 --- a/profman/Android.bp +++ b/profman/Android.bp @@ -31,7 +31,6 @@ cc_defaults { }, shared_libs: [ - "libdexfile", "libbase", ], } @@ -41,6 +40,7 @@ art_cc_binary { defaults: ["profman-defaults"], shared_libs: [ "libart", + "libdexfile", ], } @@ -52,6 +52,7 @@ art_cc_binary { ], shared_libs: [ "libartd", + "libdexfiled", ], } diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc index 79310ac166..1dd1a4afc0 100644 --- a/profman/profile_assistant_test.cc +++ b/profman/profile_assistant_test.cc @@ -31,6 +31,8 @@ namespace art { +using Hotness = ProfileCompilationInfo::MethodHotness; + static constexpr size_t kMaxMethodIds = 65535; class ProfileAssistantTest : public CommonRuntimeTest { @@ -73,26 +75,34 @@ class ProfileAssistantTest : public CommonRuntimeTest { const ScratchFile& profile, ProfileCompilationInfo* info, uint16_t start_method_index = 0, - bool reverse_dex_write_order = false) { + bool reverse_dex_write_order = false, + uint32_t number_of_methods1 = kMaxMethodIds, + uint32_t number_of_methods2 = kMaxMethodIds) { for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) { // reverse_dex_write_order controls the order in which the dex files will be added to // the profile and thus written to disk. ProfileCompilationInfo::OfflineProfileMethodInfo pmi = GetOfflineProfileMethodInfo(dex_location1, dex_location_checksum1, - dex_location2, dex_location_checksum2); + dex_location2, dex_location_checksum2, + number_of_methods1, number_of_methods2); + Hotness::Flag flags = Hotness::kFlagPostStartup; if (reverse_dex_write_order) { - ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi)); - ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi)); + ASSERT_TRUE(info->AddMethod( + dex_location2, dex_location_checksum2, i, number_of_methods2, pmi, flags)); + ASSERT_TRUE(info->AddMethod( + dex_location1, dex_location_checksum1, i, number_of_methods1, pmi, flags)); } else { - ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi)); - ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi)); + ASSERT_TRUE(info->AddMethod( + dex_location1, dex_location_checksum1, i, number_of_methods1, pmi, flags)); + ASSERT_TRUE(info->AddMethod( + dex_location2, dex_location_checksum2, i, number_of_methods2, pmi, flags)); } } for (uint16_t i = 0; i < number_of_classes; i++) { ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, dex::TypeIndex(i), - kMaxMethodIds)); + number_of_methods1)); } ASSERT_TRUE(info->Save(GetFd(profile))); @@ -109,7 +119,6 @@ class ProfileAssistantTest : public CommonRuntimeTest { const ScratchFile& profile, ProfileCompilationInfo* info) { std::string dex_location = "location1" + id; - using Hotness = ProfileCompilationInfo::MethodHotness; for (uint32_t idx : hot_methods) { info->AddMethodIndex(Hotness::kFlagHot, dex_location, checksum, idx, number_of_methods); } @@ -137,11 +146,12 @@ class ProfileAssistantTest : public CommonRuntimeTest { ProfileCompilationInfo::OfflineProfileMethodInfo GetOfflineProfileMethodInfo( const std::string& dex_location1, uint32_t dex_checksum1, - const std::string& dex_location2, uint32_t dex_checksum2) { + const std::string& dex_location2, uint32_t dex_checksum2, + uint32_t number_of_methods1 = kMaxMethodIds, uint32_t number_of_methods2 = kMaxMethodIds) { ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back(dex_location1, dex_checksum1, kMaxMethodIds); - pmi.dex_references.emplace_back(dex_location2, dex_checksum2, kMaxMethodIds); + pmi.dex_references.emplace_back(dex_location1, dex_checksum1, number_of_methods1); + pmi.dex_references.emplace_back(dex_location2, dex_checksum2, number_of_methods2); // Monomorphic for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) { @@ -1086,10 +1096,10 @@ TEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) { ASSERT_EQ(1u, classes.size()); ASSERT_TRUE(classes.find(invalid_class_index) != classes.end()); - // Verify that the invalid method is in the profile. - ASSERT_EQ(2u, hot_methods.size()); + // Verify that the invalid method did not get in the profile. + ASSERT_EQ(1u, hot_methods.size()); uint16_t invalid_method_index = std::numeric_limits<uint16_t>::max() - 1; - ASSERT_TRUE(hot_methods.find(invalid_method_index) != hot_methods.end()); + ASSERT_FALSE(hot_methods.find(invalid_method_index) != hot_methods.end()); } TEST_F(ProfileAssistantTest, DumpOnly) { @@ -1236,4 +1246,61 @@ TEST_F(ProfileAssistantTest, MergeProfilesWithFilter) { ASSERT_TRUE(expected.Equals(result)); } +TEST_F(ProfileAssistantTest, CopyAndUpdateProfileKey) { + ScratchFile profile1; + ScratchFile reference_profile; + + // Use a real dex file to generate profile test data. During the copy-and-update the + // matching is done based on checksum so we have to match with the real thing. + std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex"); + const DexFile& d1 = *dex_files[0]; + const DexFile& d2 = *dex_files[1]; + + ProfileCompilationInfo info1; + uint16_t num_methods_to_add = std::min(d1.NumMethodIds(), d2.NumMethodIds()); + SetupProfile("fake-location1", + d1.GetLocationChecksum(), + "fake-location2", + d2.GetLocationChecksum(), + num_methods_to_add, + /*num_classes*/ 0, + profile1, + &info1, + /*start_method_index*/ 0, + /*reverse_dex_write_order*/ false, + /*number_of_methods1*/ d1.NumMethodIds(), + /*number_of_methods2*/ d2.NumMethodIds()); + + // Run profman and pass the dex file with --apk-fd. + android::base::unique_fd apk_fd( + open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY)); + ASSERT_GE(apk_fd.get(), 0); + + std::string profman_cmd = GetProfmanCmd(); + std::vector<std::string> argv_str; + argv_str.push_back(profman_cmd); + argv_str.push_back("--profile-file-fd=" + std::to_string(profile1.GetFd())); + argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd())); + argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get())); + argv_str.push_back("--copy-and-update-profile-key"); + std::string error; + + ASSERT_EQ(ExecAndReturnCode(argv_str, &error), 0) << error; + + // Verify that we can load the result. + ProfileCompilationInfo result; + ASSERT_TRUE(reference_profile.GetFile()->ResetOffset()); + ASSERT_TRUE(result.Load(reference_profile.GetFd())); + + // Verify that the renaming was done. + for (uint16_t i = 0; i < num_methods_to_add; i ++) { + std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi; + ASSERT_TRUE(result.GetMethod(d1.GetLocation(), d1.GetLocationChecksum(), i) != nullptr) << i; + ASSERT_TRUE(result.GetMethod(d2.GetLocation(), d2.GetLocationChecksum(), i) != nullptr) << i; + + ASSERT_TRUE(result.GetMethod("fake-location1", d1.GetLocationChecksum(), i) == nullptr); + ASSERT_TRUE(result.GetMethod("fake-location2", d2.GetLocationChecksum(), i) == nullptr); + } +} + } // namespace art diff --git a/profman/profman.cc b/profman/profman.cc index 387ce8dfae..5551c34b60 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -280,6 +280,8 @@ class ProfMan FINAL { Usage); } else if (option.starts_with("--generate-test-profile-seed=")) { ParseUintOption(option, "--generate-test-profile-seed", &test_profile_seed_, Usage); + } else if (option.starts_with("--copy-and-update-profile-key")) { + copy_and_update_profile_key_ = true; } else { Usage("Unknown argument '%s'", option.data()); } @@ -405,9 +407,12 @@ class ProfMan FINAL { } } } else if (!apk_files_.empty()) { - if (dex_locations_.size() != apk_files_.size()) { - Usage("The number of apk-fds must match the number of dex-locations."); - } + if (dex_locations_.empty()) { + // If no dex locations are specified use the apk names as locations. + dex_locations_ = apk_files_; + } else if (dex_locations_.size() != apk_files_.size()) { + Usage("The number of apk-fds must match the number of dex-locations."); + } } else { // No APKs were specified. CHECK(dex_locations_.empty()); @@ -895,6 +900,17 @@ class ProfMan FINAL { method_str = line.substr(method_sep_index + kMethodSep.size()); } + uint32_t flags = 0; + if (is_hot) { + flags |= ProfileCompilationInfo::MethodHotness::kFlagHot; + } + if (is_startup) { + flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup; + } + if (is_post_startup) { + flags |= ProfileCompilationInfo::MethodHotness::kFlagPostStartup; + } + TypeReference class_ref(/* dex_file */ nullptr, dex::TypeIndex()); if (!FindClass(dex_files, klass, &class_ref)) { LOG(WARNING) << "Could not find class: " << klass; @@ -930,7 +946,7 @@ class ProfMan FINAL { } } // TODO: Check return values? - profile->AddMethods(methods); + profile->AddMethods(methods, static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags)); profile->AddClasses(resolved_class_set); return true; } @@ -982,18 +998,12 @@ class ProfMan FINAL { } MethodReference ref(class_ref.dex_file, method_index); if (is_hot) { - profile->AddMethod(ProfileMethodInfo(ref, inline_caches)); - } - uint32_t flags = 0; - using Hotness = ProfileCompilationInfo::MethodHotness; - if (is_startup) { - flags |= Hotness::kFlagStartup; - } - if (is_post_startup) { - flags |= Hotness::kFlagPostStartup; + profile->AddMethod(ProfileMethodInfo(ref, inline_caches), + static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags)); } if (flags != 0) { - if (!profile->AddMethodIndex(static_cast<Hotness::Flag>(flags), ref)) { + if (!profile->AddMethodIndex( + static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags), ref)) { return false; } DCHECK(profile->GetMethodHotness(ref).IsInProfile()); @@ -1173,7 +1183,7 @@ class ProfMan FINAL { return copy_and_update_profile_key_; } - bool CopyAndUpdateProfileKey() { + int32_t CopyAndUpdateProfileKey() { // Validate that at least one profile file was passed, as well as a reference profile. if (!(profile_files_.size() == 1 ^ profile_files_fd_.size() == 1)) { Usage("Only one profile file should be specified."); @@ -1186,22 +1196,30 @@ class ProfMan FINAL { Usage("No apk files specified"); } + static constexpr int32_t kErrorFailedToUpdateProfile = -1; + static constexpr int32_t kErrorFailedToSaveProfile = -2; + static constexpr int32_t kErrorFailedToLoadProfile = -3; + bool use_fds = profile_files_fd_.size() == 1; ProfileCompilationInfo profile; // Do not clear if invalid. The input might be an archive. - if (profile.Load(profile_files_[0], /*clear_if_invalid*/ false)) { + bool load_ok = use_fds + ? profile.Load(profile_files_fd_[0]) + : profile.Load(profile_files_[0], /*clear_if_invalid*/ false); + if (load_ok) { // Open the dex files to look up classes and methods. std::vector<std::unique_ptr<const DexFile>> dex_files; OpenApkFilesFromLocations(&dex_files); if (!profile.UpdateProfileKeys(dex_files)) { - return false; + return kErrorFailedToUpdateProfile; } - return use_fds - ? profile.Save(reference_profile_file_fd_) - : profile.Save(reference_profile_file_, /*bytes_written*/ nullptr); + bool result = use_fds + ? profile.Save(reference_profile_file_fd_) + : profile.Save(reference_profile_file_, /*bytes_written*/ nullptr); + return result ? 0 : kErrorFailedToSaveProfile; } else { - return false; + return kErrorFailedToLoadProfile; } } @@ -1280,6 +1298,11 @@ static int profman(int argc, char** argv) { if (profman.ShouldCreateBootProfile()) { return profman.CreateBootProfile(); } + + if (profman.ShouldCopyAndUpdateProfileKey()) { + return profman.CopyAndUpdateProfileKey(); + } + // Process profile information and assess if we need to do a profile guided compilation. // This operation involves I/O. return profman.ProcessProfiles(); diff --git a/runtime/Android.bp b/runtime/Android.bp index 832d50e691..1ac770fd06 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -14,83 +14,6 @@ // limitations under the License. // -cc_defaults { - name: "libdexfile_defaults", - defaults: ["art_defaults"], - host_supported: true, - srcs: [ - "dex/compact_dex_debug_info.cc", - "dex/compact_dex_file.cc", - "dex/descriptors_names.cc", - "dex/dex_file.cc", - "dex/dex_file_exception_helpers.cc", - "dex/dex_file_loader.cc", - "dex/dex_file_tracking_registrar.cc", - "dex/dex_file_verifier.cc", - "dex/dex_instruction.cc", - "dex/modifiers.cc", - "dex/standard_dex_file.cc", - "dex/utf.cc", - ], - - target: { - android: { - static_libs: [ - "libziparchive", - "libz", - "libbase", - ], - shared_libs: [ - "libutils", - ], - }, - host: { - shared_libs: [ - "libziparchive", - "libz", - ], - }, - }, - generated_sources: ["dexfile_operator_srcs"], - include_dirs: [ - "external/zlib", - ], - shared_libs: [ - "liblog", - // For common macros. - "libbase", - "libz", - ], - - // Exporting "." would shadow the system elf.h with our elf.h, - // which in turn breaks any tools that reference this library. - // export_include_dirs: ["."], -} - -gensrcs { - name: "dexfile_operator_srcs", - cmd: "$(location generate-operator-out.py) art/runtime $(in) > $(out)", - tool_files: ["generate-operator-out.py"], - srcs: [ - "dex/dex_file.h", - "dex/dex_file_layout.h", - "dex/dex_instruction.h", - "dex/dex_instruction_utils.h", - "dex/invoke_type.h", - ], - output_extension: "operator_out.cc", -} - -art_cc_library { - name: "libdexfile", - defaults: ["libdexfile_defaults"], - // Leave the symbols in the shared library so that stack unwinders can - // produce meaningful name resolution. - strip: { - keep_symbols: true, - }, -} - // Keep the __jit_debug_register_code symbol as a unique symbol during ICF for architectures where // we use gold as the linker (arm, x86, x86_64). The symbol is used by the debuggers to detect when // new jit code is generated. We don't want it to be called when a different function with the same @@ -133,9 +56,9 @@ cc_defaults { "common_throws.cc", "compiler_filter.cc", "debugger.cc", + "dex/art_dex_file_loader.cc", "dex/dex_file_annotations.cc", "dex/dex_file_layout.cc", - "dex/art_dex_file_loader.cc", "dex_to_dex_decompiler.cc", "elf_file.cc", "exec_utils.cc", @@ -244,7 +167,6 @@ cc_defaults { "native/java_lang_Thread.cc", "native/java_lang_Throwable.cc", "native/java_lang_VMClassLoader.cc", - "native/java_lang_Void.cc", "native/java_lang_invoke_MethodHandleImpl.cc", "native/java_lang_ref_FinalizerReference.cc", "native/java_lang_ref_Reference.cc", @@ -487,7 +409,6 @@ cc_defaults { "jni_platform_headers", ], shared_libs: [ - "libdexfile", "libnativebridge", "libnativeloader", "libbacktrace", @@ -521,9 +442,9 @@ gensrcs { "base/callee_save_type.h", "base/enums.h", "base/mutex.h", - "debugger.h", "base/unix_file/fd_file.h", "class_status.h", + "debugger.h", "dex/dex_file_layout.h", "gc_root.h", "gc/allocator_type.h", @@ -565,6 +486,8 @@ art_cc_library { strip: { keep_symbols: true, }, + shared_libs: ["libdexfile"], + export_shared_lib_headers: ["libdexfile"], } art_cc_library { @@ -573,6 +496,8 @@ art_cc_library { "art_debug_defaults", "libart_defaults", ], + shared_libs: ["libdexfiled"], + export_shared_lib_headers: ["libdexfiled"], } art_cc_library { @@ -638,13 +563,6 @@ art_cc_test { "class_table_test.cc", "compiler_filter_test.cc", "dex/art_dex_file_loader_test.cc", - "dex/code_item_accessors_test.cc", - "dex/compact_dex_debug_info_test.cc", - "dex/compact_dex_file_test.cc", - "dex/dex_file_loader_test.cc", - "dex/dex_file_verifier_test.cc", - "dex/dex_instruction_test.cc", - "dex/utf_test.cc", "entrypoints/math_entrypoints_test.cc", "entrypoints/quick/quick_trampoline_entrypoints_test.cc", "entrypoints_order_test.cc", diff --git a/runtime/base/stringpiece.cc b/runtime/base/stringpiece.cc index 672431cf9d..aea4e74bb1 100644 --- a/runtime/base/stringpiece.cc +++ b/runtime/base/stringpiece.cc @@ -23,13 +23,6 @@ namespace art { -#if !defined(NDEBUG) -char StringPiece::operator[](size_type i) const { - CHECK_LT(i, length_); - return ptr_[i]; -} -#endif - void StringPiece::CopyToString(std::string* target) const { target->assign(ptr_, length_); } diff --git a/runtime/base/stringpiece.h b/runtime/base/stringpiece.h index 46743e9643..e7109dc18a 100644 --- a/runtime/base/stringpiece.h +++ b/runtime/base/stringpiece.h @@ -20,6 +20,8 @@ #include <string.h> #include <string> +#include <android-base/logging.h> + namespace art { // A string-like object that points to a sized piece of memory. @@ -84,13 +86,10 @@ class StringPiece { length_ = len; } -#if defined(NDEBUG) char operator[](size_type i) const { + DCHECK_LT(i, length_); return ptr_[i]; } -#else - char operator[](size_type i) const; -#endif void remove_prefix(size_type n) { ptr_ += n; diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 5549122c34..05f099f3b2 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -46,6 +46,7 @@ #include "well_known_classes.h" namespace art { +namespace { using android::base::StringAppendF; using android::base::StringPrintf; @@ -1211,7 +1212,7 @@ class ScopedCheck { // this particular instance of JNIEnv. if (env != threadEnv) { // Get the thread owning the JNIEnv that's being used. - Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self_; + Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf(); AbortF("thread %s using JNIEnv* from thread %s", ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str()); return false; @@ -1223,7 +1224,7 @@ class ScopedCheck { case kFlag_CritOkay: // okay to call this method break; case kFlag_CritBad: // not okay to call - if (threadEnv->critical_ > 0) { + if (threadEnv->GetCritical() > 0) { AbortF("thread %s using JNI after critical get", ToStr<Thread>(*self).c_str()); return false; @@ -1231,25 +1232,25 @@ class ScopedCheck { break; case kFlag_CritGet: // this is a "get" call // Don't check here; we allow nested gets. - if (threadEnv->critical_ == 0) { - threadEnv->critical_start_us_ = self->GetCpuMicroTime(); + if (threadEnv->GetCritical() == 0) { + threadEnv->SetCriticalStartUs(self->GetCpuMicroTime()); } - threadEnv->critical_++; + threadEnv->SetCritical(threadEnv->GetCritical() + 1); break; case kFlag_CritRelease: // this is a "release" call - if (threadEnv->critical_ == 0) { + if (threadEnv->GetCritical() == 0) { AbortF("thread %s called too many critical releases", ToStr<Thread>(*self).c_str()); return false; - } else if (threadEnv->critical_ == 1) { + } else if (threadEnv->GetCritical() == 1) { // Leaving the critical region, possibly warn about long critical regions. - uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->critical_start_us_; + uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs(); if (critical_duration_us > kCriticalWarnTimeUs) { LOG(WARNING) << "JNI critical lock held for " << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self; } } - threadEnv->critical_--; + threadEnv->SetCritical(threadEnv->GetCritical() - 1); break; default: LOG(FATAL) << "Bad flags (internal error): " << flags_; @@ -2621,7 +2622,7 @@ class CheckJNI { } static const JNINativeInterface* baseEnv(JNIEnv* env) { - return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions_; + return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions(); } static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { @@ -3847,10 +3848,6 @@ const JNINativeInterface gCheckNativeInterface = { CheckJNI::GetObjectRefType, }; -const JNINativeInterface* GetCheckJniNativeInterface() { - return &gCheckNativeInterface; -} - class CheckJII { public: static jint DestroyJavaVM(JavaVM* vm) { @@ -3922,6 +3919,12 @@ const JNIInvokeInterface gCheckInvokeInterface = { CheckJII::AttachCurrentThreadAsDaemon }; +} // anonymous namespace + +const JNINativeInterface* GetCheckJniNativeInterface() { + return &gCheckNativeInterface; +} + const JNIInvokeInterface* GetCheckJniInvokeInterface() { return &gCheckInvokeInterface; } diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index cd6e8d59e8..ae06f8f9bc 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -226,14 +226,7 @@ inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx, const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader); if (klass != nullptr) { - if (klass->IsInterface()) { - resolved = klass->FindInterfaceMethod(dex_cache, method_idx, pointer_size); - } else { - resolved = klass->FindClassMethod(dex_cache, method_idx, pointer_size); - } - if (resolved != nullptr) { - dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size); - } + resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx); } } return resolved; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 800427d6ab..62627287b0 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -457,7 +457,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b VoidFunctor())); // Initialize the SubtypeCheck bitstring for java.lang.Object and java.lang.Class. - { + if (kBitstringSubtypeCheckEnabled) { // It might seem the lock here is unnecessary, however all the SubtypeCheck // functions are annotated to require locks all the way down. // @@ -1856,7 +1856,7 @@ bool ClassLinker::AddImageSpace( visitor(root.Read()); } - { + if (kBitstringSubtypeCheckEnabled) { // Every class in the app image has initially SubtypeCheckInfo in the // Uninitialized state. // @@ -4484,6 +4484,14 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& Runtime::Current()->GetRuntimeCallbacks()->ClassPrepare(temp_klass, klass); + // SubtypeCheckInfo::Initialized must happen-before any new-instance for that type. + // See also ClassLinker::EnsureInitialized(). + if (kBitstringSubtypeCheckEnabled) { + MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_); + SubtypeCheck<ObjPtr<mirror::Class>>::EnsureInitialized(klass.Get()); + // TODO: Avoid taking subtype_check_lock_ if SubtypeCheck for j.l.r.Proxy is already assigned. + } + { // Lock on klass is released. Lock new class object. ObjectLock<mirror::Class> initialization_lock(self, klass); @@ -5231,7 +5239,7 @@ bool ClassLinker::EnsureInitialized(Thread* self, // can be used as a source for the IsSubClass check, and that all ancestors // of the class are Assigned (can be used as a target for IsSubClass check) // or Overflowed (can be used as a source for IsSubClass check). - { + if (kBitstringSubtypeCheckEnabled) { MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_); SubtypeCheck<ObjPtr<mirror::Class>>::EnsureInitialized(c.Get()); // TODO: Avoid taking subtype_check_lock_ if SubtypeCheck is already initialized. @@ -7931,6 +7939,38 @@ std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* clas return oss.str(); } +ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t method_idx) { + // Search for the method using dex_cache and method_idx. The Class::Find*Method() + // functions can optimize the search if the dex_cache is the same as the DexCache + // of the class, with fall-back to name and signature search otherwise. + ArtMethod* resolved = nullptr; + if (klass->IsInterface()) { + resolved = klass->FindInterfaceMethod(dex_cache, method_idx, image_pointer_size_); + } else { + resolved = klass->FindClassMethod(dex_cache, method_idx, image_pointer_size_); + } + DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr); + if (resolved != nullptr) { + // In case of jmvti, the dex file gets verified before being registered, so first + // check if it's registered before checking class tables. + const DexFile& dex_file = *dex_cache->GetDexFile(); + CHECK(!IsDexFileRegistered(Thread::Current(), dex_file) || + FindClassTable(Thread::Current(), dex_cache) == ClassTableForClassLoader(class_loader)) + << "DexFile referrer: " << dex_file.GetLocation() + << " ClassLoader: " << DescribeLoaders(class_loader, ""); + // Be a good citizen and update the dex cache to speed subsequent calls. + dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_); + const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); + CHECK(LookupResolvedType(method_id.class_idx_, dex_cache, class_loader) != nullptr) + << "Class: " << klass->PrettyClass() << ", " + << "DexFile referrer: " << dex_file.GetLocation(); + } + return resolved; +} + template <ClassLinker::ResolveMode kResolveMode> ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, Handle<mirror::DexCache> dex_cache, @@ -7963,6 +8003,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, << resolved->PrettyMethod() << ";" << resolved << "/0x" << std::hex << resolved->GetAccessFlags() << " ReferencedClass: " << descriptor + << " DexFile referrer: " << dex_file.GetLocation() << " ClassLoader: " << DescribeLoaders(class_loader.Get(), descriptor); } } else { @@ -7983,19 +8024,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, } if (!valid_dex_cache_method) { - // Search for the method using dex_cache and method_idx. The Class::Find*Method() - // functions can optimize the search if the dex_cache is the same as the DexCache - // of the class, with fall-back to name and signature search otherwise. - if (klass->IsInterface()) { - resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, pointer_size); - } else { - resolved = klass->FindClassMethod(dex_cache.Get(), method_idx, pointer_size); - } - DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr); - if (resolved != nullptr) { - // Be a good citizen and update the dex cache to speed subsequent calls. - dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size); - } + resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx); } // Note: We can check for IllegalAccessError only if we have a referrer. diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 16fa1ce801..712e3aeffa 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -27,9 +27,9 @@ #include "base/enums.h" #include "base/macros.h" #include "base/mutex.h" +#include "dex/dex_cache_resolved_classes.h" #include "dex/dex_file.h" #include "dex/dex_file_types.h" -#include "dex_cache_resolved_classes.h" #include "gc_root.h" #include "handle.h" #include "jni.h" @@ -312,6 +312,13 @@ class ClassLinker { ObjPtr<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); + // Find a method with the given index from class `klass`, and update the dex cache. + ArtMethod* FindResolvedMethod(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t method_idx) + REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a method with a given ID from the DexFile associated with the given DexCache // and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader are // used as in ResolveType. What is unique is the method type argument which is used to diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc index 08cf30d5bf..0817cb4b6a 100644 --- a/runtime/dex/art_dex_file_loader.cc +++ b/runtime/dex/art_dex_file_loader.cc @@ -25,10 +25,10 @@ #include "base/stl_util.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" -#include "compact_dex_file.h" -#include "dex_file.h" -#include "dex_file_verifier.h" -#include "standard_dex_file.h" +#include "dex/compact_dex_file.h" +#include "dex/dex_file.h" +#include "dex/dex_file_verifier.h" +#include "dex/standard_dex_file.h" #include "zip_archive.h" namespace art { diff --git a/runtime/dex/art_dex_file_loader.h b/runtime/dex/art_dex_file_loader.h index b31d1e94e0..3585381f9b 100644 --- a/runtime/dex/art_dex_file_loader.h +++ b/runtime/dex/art_dex_file_loader.h @@ -22,8 +22,8 @@ #include <string> #include <vector> -#include "dex_file_loader.h" #include "base/macros.h" +#include "dex/dex_file_loader.h" namespace art { diff --git a/runtime/dex/art_dex_file_loader_test.cc b/runtime/dex/art_dex_file_loader_test.cc index f4013810a4..25d4dd0875 100644 --- a/runtime/dex/art_dex_file_loader_test.cc +++ b/runtime/dex/art_dex_file_loader_test.cc @@ -14,8 +14,6 @@ * limitations under the License. */ -#include "dex_file.h" - #include <sys/mman.h> #include <memory> @@ -23,12 +21,13 @@ #include "art_dex_file_loader.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" -#include "base64_test_util.h" -#include "code_item_accessors-inl.h" #include "common_runtime_test.h" -#include "descriptors_names.h" -#include "dex_file-inl.h" -#include "dex_file_loader.h" +#include "dex/base64_test_util.h" +#include "dex/code_item_accessors-inl.h" +#include "dex/descriptors_names.h" +#include "dex/dex_file.h" +#include "dex/dex_file-inl.h" +#include "dex/dex_file_loader.h" #include "mem_map.h" #include "os.h" #include "scoped_thread_state_change-inl.h" diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc index e01890f541..3431bb7efb 100644 --- a/runtime/dex/dex_file_annotations.cc +++ b/runtime/dex/dex_file_annotations.cc @@ -23,7 +23,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "class_linker-inl.h" -#include "dex_file-inl.h" +#include "dex/dex_file-inl.h" #include "jni_internal.h" #include "jvalue-inl.h" #include "mirror/field.h" diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h index 26773729c2..d7ebf84b1c 100644 --- a/runtime/dex/dex_file_annotations.h +++ b/runtime/dex/dex_file_annotations.h @@ -17,7 +17,7 @@ #ifndef ART_RUNTIME_DEX_DEX_FILE_ANNOTATIONS_H_ #define ART_RUNTIME_DEX_DEX_FILE_ANNOTATIONS_H_ -#include "dex_file.h" +#include "dex/dex_file.h" #include "handle.h" #include "mirror/dex_cache.h" diff --git a/runtime/dex/dex_file_layout.cc b/runtime/dex/dex_file_layout.cc index 312898d82f..d85d61d56b 100644 --- a/runtime/dex/dex_file_layout.cc +++ b/runtime/dex/dex_file_layout.cc @@ -19,8 +19,7 @@ #include <sys/mman.h> #include "base/file_utils.h" -#include "descriptors_names.h" -#include "dex_file.h" +#include "dex/dex_file.h" namespace art { diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 9ef7d426df..404c5357bf 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -99,14 +99,13 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, << "This must be due to playing wrongly with class loaders"; } - inlined_method = klass->FindClassMethod(dex_cache, method_index, kRuntimePointerSize); + inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index); if (inlined_method == nullptr) { LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor << " does not have " << dex_file->GetMethodName(method_id) << dex_file->GetMethodSignature(method_id) << " declared. " << "This must be due to duplicate classes or playing wrongly with class loaders"; } - dex_cache->SetResolvedMethod(method_index, inlined_method, kRuntimePointerSize); return inlined_method; } diff --git a/runtime/image.cc b/runtime/image.cc index 8e3615ffcf..99406229a5 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -26,7 +26,7 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '4', '\0' }; // Math.pow() intrinsic. +const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '5', '\0' }; // Bitstring type check off. ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 24cedb093b..0ae6dbfa88 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -269,7 +269,20 @@ static void InstrumentationInstallStack(Thread* thread, void* arg) } } else { CHECK_NE(return_pc, 0U); - CHECK(!reached_existing_instrumentation_frames_); + if (UNLIKELY(reached_existing_instrumentation_frames_)) { + std::string thread_name; + GetThread()->GetThreadName(thread_name); + uint32_t dex_pc = dex::kDexNoIndex; + if (last_return_pc_ != 0 && + GetCurrentOatQuickMethodHeader() != nullptr) { + dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_); + } + LOG(FATAL) << "While walking " << thread_name << " found existing instrumentation frames." + << " method is " << GetMethod()->PrettyMethod() + << " return_pc is " << std::hex << return_pc + << " dex pc: " << dex_pc; + UNREACHABLE(); + } InstrumentationStackFrame instrumentation_frame( m->IsRuntimeMethod() ? nullptr : GetThisObject(), m, diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 85acc71377..f8dd8293ca 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -235,6 +235,20 @@ void UnstartedRuntime::UnstartedClassForNameLong( UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.forName"); } +void UnstartedRuntime::UnstartedClassGetPrimitiveClass( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + ObjPtr<mirror::String> class_name = GetClassName(self, shadow_frame, arg_offset); + ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(class_name); + if (UNLIKELY(klass == nullptr)) { + DCHECK(self->IsExceptionPending()); + AbortTransactionOrFail(self, + "Class.getPrimitiveClass() failed: %s", + self->GetException()->GetDetailMessage()->ToModifiedUtf8().c_str()); + return; + } + result->SetL(klass); +} + void UnstartedRuntime::UnstartedClassClassForName( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.classForName"); @@ -738,12 +752,6 @@ void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass( } } -void UnstartedRuntime::UnstartedVoidLookupType( - Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result, - size_t arg_offset ATTRIBUTE_UNUSED) { - result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V')); -} - // Arraycopy emulation. // Note: we can't use any fast copy functions, as they are not available under transaction. diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index c029e07432..3cc598aed7 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -23,6 +23,7 @@ V(CharacterToUpperCase, "int java.lang.Character.toUpperCase(int)") \ V(ClassForName, "java.lang.Class java.lang.Class.forName(java.lang.String)") \ V(ClassForNameLong, "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)") \ + V(ClassGetPrimitiveClass, "java.lang.Class java.lang.Class.getPrimitiveClass(java.lang.String)") \ V(ClassClassForName, "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)") \ V(ClassNewInstance, "java.lang.Object java.lang.Class.newInstance()") \ V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \ @@ -36,7 +37,6 @@ V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \ V(ConstructorNewInstance0, "java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[])") \ V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \ - V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \ V(SystemArraycopy, "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") \ V(SystemArraycopyByte, "void java.lang.System.arraycopy(byte[], int, byte[], int, int)") \ V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \ diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h index 8c81c2565d..ac20afecd4 100644 --- a/runtime/java_vm_ext.h +++ b/runtime/java_vm_ext.h @@ -225,7 +225,7 @@ class JavaVMExt : public JavaVM { // Extra checking. bool check_jni_; - bool force_copy_; + const bool force_copy_; const bool tracing_enabled_; // Extra diagnostics. diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index de4d02edaf..dcb4a20b5f 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -168,9 +168,10 @@ bool ProfileCompilationInfo::AddMethodIndex(MethodHotness::Flag flags, return data->AddMethod(flags, method_idx); } -bool ProfileCompilationInfo::AddMethods(const std::vector<ProfileMethodInfo>& methods) { +bool ProfileCompilationInfo::AddMethods(const std::vector<ProfileMethodInfo>& methods, + MethodHotness::Flag flags) { for (const ProfileMethodInfo& method : methods) { - if (!AddMethod(method)) { + if (!AddMethod(method, flags)) { return false; } } @@ -644,15 +645,26 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location, uint32_t dex_checksum, uint16_t method_index, uint32_t num_method_ids, - const OfflineProfileMethodInfo& pmi) { + const OfflineProfileMethodInfo& pmi, + MethodHotness::Flag flags) { DexFileData* const data = GetOrAddDexFileData(GetProfileDexFileKey(dex_location), dex_checksum, num_method_ids); - if (data == nullptr) { // checksum mismatch + if (data == nullptr) { + // The data is null if there is a mismatch in the checksum or number of method ids. return false; } + // Add the method. InlineCacheMap* inline_cache = data->FindOrAddMethod(method_index); + if (inline_cache == nullptr) { + // Happens if the method index is outside the range (i.e. is greater then the number + // of methods in the dex file). This should not happen during normal execution, + // But tools (e.g. boot image aggregation tools) and tests stress this behaviour. + return false; + } + + data->SetMethodHotness(method_index, flags); if (pmi.inline_caches == nullptr) { // If we don't have inline caches return success right away. @@ -691,12 +703,16 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location, return true; } -bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { +bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi, MethodHotness::Flag flags) { DexFileData* const data = GetOrAddDexFileData(pmi.ref.dex_file); if (data == nullptr) { // checksum mismatch return false; } InlineCacheMap* inline_cache = data->FindOrAddMethod(pmi.ref.index); + if (inline_cache == nullptr) { + return false; + } + data->SetMethodHotness(pmi.ref.index, flags); for (const ProfileMethodInfo::ProfileInlineCache& cache : pmi.inline_caches) { if (cache.is_missing_types) { @@ -811,6 +827,9 @@ bool ProfileCompilationInfo::ReadMethods(SafeBuffer& buffer, uint16_t method_index = last_method_index + diff_with_last_method_index; last_method_index = method_index; InlineCacheMap* inline_cache = data->FindOrAddMethod(method_index); + if (inline_cache == nullptr) { + return false; + } if (!ReadInlineCache(buffer, number_of_dex_files, dex_profile_index_remap, @@ -1521,6 +1540,9 @@ bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other, for (const auto& other_method_it : other_dex_data->method_map) { uint16_t other_method_index = other_method_it.first; InlineCacheMap* inline_cache = dex_data->FindOrAddMethod(other_method_index); + if (inline_cache == nullptr) { + return false; + } const auto& other_inline_cache = other_method_it.second; for (const auto& other_ic_it : other_inline_cache) { uint16_t other_dex_pc = other_ic_it.first; @@ -1955,6 +1977,10 @@ bool ProfileCompilationInfo::IsEmpty() const { ProfileCompilationInfo::InlineCacheMap* ProfileCompilationInfo::DexFileData::FindOrAddMethod(uint16_t method_index) { + if (method_index >= num_method_ids) { + LOG(ERROR) << "Invalid method index " << method_index << ". num_method_ids=" << num_method_ids; + return nullptr; + } return &(method_map.FindOrAdd( method_index, InlineCacheMap(std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)))->second); @@ -1967,12 +1993,8 @@ bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, s return false; } - if ((flags & MethodHotness::kFlagStartup) != 0) { - method_bitmap.StoreBit(MethodBitIndex(/*startup*/ true, index), /*value*/ true); - } - if ((flags & MethodHotness::kFlagPostStartup) != 0) { - method_bitmap.StoreBit(MethodBitIndex(/*startup*/ false, index), /*value*/ true); - } + SetMethodHotness(index, flags); + if ((flags & MethodHotness::kFlagHot) != 0) { method_map.FindOrAdd( index, @@ -1981,6 +2003,17 @@ bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, s return true; } +void ProfileCompilationInfo::DexFileData::SetMethodHotness(size_t index, + MethodHotness::Flag flags) { + DCHECK_LT(index, num_method_ids); + if ((flags & MethodHotness::kFlagStartup) != 0) { + method_bitmap.StoreBit(MethodBitIndex(/*startup*/ true, index), /*value*/ true); + } + if ((flags & MethodHotness::kFlagPostStartup) != 0) { + method_bitmap.StoreBit(MethodBitIndex(/*startup*/ false, index), /*value*/ true); + } +} + ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::DexFileData::GetHotnessInfo( uint32_t dex_method_index) const { MethodHotness ret; diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index 1973f3f09e..3213c85156 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -24,7 +24,7 @@ #include "base/arena_containers.h" #include "base/arena_object.h" #include "bit_memory_region.h" -#include "dex_cache_resolved_classes.h" +#include "dex/dex_cache_resolved_classes.h" #include "dex/dex_file.h" #include "dex/dex_file_types.h" #include "method_reference.h" @@ -241,7 +241,7 @@ class ProfileCompilationInfo { ~ProfileCompilationInfo(); // Add the given methods to the current profile object. - bool AddMethods(const std::vector<ProfileMethodInfo>& methods); + bool AddMethods(const std::vector<ProfileMethodInfo>& methods, MethodHotness::Flag flags); // Add the given classes to the current profile object. bool AddClasses(const std::set<DexCacheResolvedClasses>& resolved_classes); @@ -278,7 +278,7 @@ class ProfileCompilationInfo { bool AddMethodIndex(MethodHotness::Flag flags, const MethodReference& ref); // Add a method to the profile using its online representation (containing runtime structures). - bool AddMethod(const ProfileMethodInfo& pmi); + bool AddMethod(const ProfileMethodInfo& pmi, MethodHotness::Flag flags); // Bulk add sampled methods and/or hot methods for a single dex, fast since it only has one // GetOrAddDexFileData call. @@ -500,6 +500,7 @@ class ProfileCompilationInfo { } } + void SetMethodHotness(size_t index, MethodHotness::Flag flags); MethodHotness GetHotnessInfo(uint32_t dex_method_index) const; // The allocator used to allocate new inline cache maps. @@ -559,7 +560,8 @@ class ProfileCompilationInfo { uint32_t dex_checksum, uint16_t method_index, uint32_t num_method_ids, - const OfflineProfileMethodInfo& pmi); + const OfflineProfileMethodInfo& pmi, + MethodHotness::Flag flags); // Add a class index to the profile. bool AddClassIndex(const std::string& dex_location, diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc index 4ac11ee422..e6917956ae 100644 --- a/runtime/jit/profile_compilation_info_test.cc +++ b/runtime/jit/profile_compilation_info_test.cc @@ -80,7 +80,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { uint16_t method_index, const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi, ProfileCompilationInfo* info) { - return info->AddMethod(dex_location, checksum, method_index, kMaxMethodIds, pmi); + return info->AddMethod( + dex_location, checksum, method_index, kMaxMethodIds, pmi, Hotness::kFlagPostStartup); } bool AddClass(const std::string& dex_location, @@ -99,7 +100,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { bool SaveProfilingInfo( const std::string& filename, const std::vector<ArtMethod*>& methods, - const std::set<DexCacheResolvedClasses>& resolved_classes) { + const std::set<DexCacheResolvedClasses>& resolved_classes, + Hotness::Flag flags) { ProfileCompilationInfo info; std::vector<ProfileMethodInfo> profile_methods; ScopedObjectAccess soa(Thread::Current()); @@ -107,7 +109,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { profile_methods.emplace_back( MethodReference(method->GetDexFile(), method->GetDexMethodIndex())); } - if (!info.AddMethods(profile_methods) || !info.AddClasses(resolved_classes)) { + if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) { return false; } if (info.GetNumberOfMethods() != profile_methods.size()) { @@ -130,6 +132,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { bool SaveProfilingInfoWithFakeInlineCaches( const std::string& filename, const std::vector<ArtMethod*>& methods, + Hotness::Flag flags, /*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) { ProfileCompilationInfo info; std::vector<ProfileMethodInfo> profile_methods; @@ -170,7 +173,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { profile_methods_map->Put(method, pmi); } - if (!info.AddMethods(profile_methods) || info.GetNumberOfMethods() != profile_methods.size()) { + if (!info.AddMethods(profile_methods, flags) + || info.GetNumberOfMethods() != profile_methods.size()) { return false; } return info.Save(filename, nullptr); @@ -345,7 +349,8 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) { // Save virtual methods from Main. std::set<DexCacheResolvedClasses> resolved_classes; std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;"); - ASSERT_TRUE(SaveProfilingInfo(profile.GetFilename(), main_methods, resolved_classes)); + ASSERT_TRUE(SaveProfilingInfo( + profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup)); // Check that what we saved is in the profile. ProfileCompilationInfo info1; @@ -354,14 +359,16 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) { { ScopedObjectAccess soa(self); for (ArtMethod* m : main_methods) { - ASSERT_TRUE(info1.GetMethodHotness( - MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot()); + Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())); + ASSERT_TRUE(h.IsHot()); + ASSERT_TRUE(h.IsPostStartup()); } } // Save virtual methods from Second. std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;"); - ASSERT_TRUE(SaveProfilingInfo(profile.GetFilename(), second_methods, resolved_classes)); + ASSERT_TRUE(SaveProfilingInfo( + profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup)); // Check that what we saved is in the profile (methods form Main and Second). ProfileCompilationInfo info2; @@ -371,12 +378,14 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethods) { { ScopedObjectAccess soa(self); for (ArtMethod* m : main_methods) { - ASSERT_TRUE( - info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot()); + Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())); + ASSERT_TRUE(h.IsHot()); + ASSERT_TRUE(h.IsPostStartup()); } for (ArtMethod* m : second_methods) { - ASSERT_TRUE( - info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot()); + Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())); + ASSERT_TRUE(h.IsHot()); + ASSERT_TRUE(h.IsStartup()); } } } @@ -730,7 +739,7 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) { SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map; ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches( - profile.GetFilename(), main_methods, &profile_methods_map)); + profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map)); // Check that what we saved is in the profile. ProfileCompilationInfo info; @@ -739,8 +748,9 @@ TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) { { ScopedObjectAccess soa(self); for (ArtMethod* m : main_methods) { - ASSERT_TRUE( - info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())).IsHot()); + Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())); + ASSERT_TRUE(h.IsHot()); + ASSERT_TRUE(h.IsStartup()); const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second; std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi = info.GetMethod(m->GetDexFile()->GetLocation(), diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc index 8f0ac33594..53f48644f2 100644 --- a/runtime/jit/profile_saver.cc +++ b/runtime/jit/profile_saver.cc @@ -511,7 +511,7 @@ bool ProfileSaver::ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number uint64_t last_save_number_of_methods = info.GetNumberOfMethods(); uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses(); - info.AddMethods(profile_methods); + info.AddMethods(profile_methods, ProfileCompilationInfo::MethodHotness::kFlagPostStartup); auto profile_cache_it = profile_cache_.find(filename); if (profile_cache_it != profile_cache_.end()) { info.MergeWith(*(profile_cache_it->second)); diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h index 0e8fd03057..291ac48e86 100644 --- a/runtime/jni_env_ext.h +++ b/runtime/jni_env_ext.h @@ -96,6 +96,15 @@ class JNIEnvExt : public JNIEnv { } Thread* GetSelf() const { return self_; } + uint32_t GetCritical() const { return critical_; } + void SetCritical(uint32_t new_critical) { critical_ = new_critical; } + uint64_t GetCriticalStartUs() const { return critical_start_us_; } + void SetCriticalStartUs(uint64_t new_critical_start_us) { + critical_start_us_ = new_critical_start_us; + } + const JNINativeInterface* GetUncheckedFunctions() const { + return unchecked_functions_; + } JavaVMExt* GetVm() const { return vm_; } bool IsRuntimeDeleted() const { return runtime_deleted_; } @@ -190,9 +199,7 @@ class JNIEnvExt : public JNIEnv { // If we are a JNI env for a daemon thread with a deleted runtime. bool runtime_deleted_; - friend class CheckJNI; friend class JNI; - friend class ScopedCheck; friend class ScopedJniEnvLocalRefState; friend class Thread; ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 36388eb3aa..86d538ec80 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -550,7 +550,7 @@ inline bool Class::IsSubClass(ObjPtr<Class> klass) { current = current->GetSuperClass(); } while (current != nullptr); - if (kIsDebugBuild) { + if (kIsDebugBuild && kBitstringSubtypeCheckEnabled) { ObjPtr<mirror::Class> dis(this); SubtypeCheckInfo::Result sc_result = SubtypeCheck<ObjPtr<Class>>::IsSubtypeOf(dis, klass); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 8a7defd362..5d730ce0b0 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -72,6 +72,42 @@ void Class::VisitRoots(RootVisitor* visitor) { java_lang_Class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); } +ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) { + const char* expected_name = nullptr; + ClassLinker::ClassRoot class_root = ClassLinker::kJavaLangObject; // Invalid. + if (name != nullptr && name->GetLength() >= 2) { + // Perfect hash for the expected values: from the second letters of the primitive types, + // only 'y' has the bit 0x10 set, so use it to change 'b' to 'B'. + char hash = name->CharAt(0) ^ ((name->CharAt(1) & 0x10) << 1); + switch (hash) { + case 'b': expected_name = "boolean"; class_root = ClassLinker::kPrimitiveBoolean; break; + case 'B': expected_name = "byte"; class_root = ClassLinker::kPrimitiveByte; break; + case 'c': expected_name = "char"; class_root = ClassLinker::kPrimitiveChar; break; + case 'd': expected_name = "double"; class_root = ClassLinker::kPrimitiveDouble; break; + case 'f': expected_name = "float"; class_root = ClassLinker::kPrimitiveFloat; break; + case 'i': expected_name = "int"; class_root = ClassLinker::kPrimitiveInt; break; + case 'l': expected_name = "long"; class_root = ClassLinker::kPrimitiveLong; break; + case 's': expected_name = "short"; class_root = ClassLinker::kPrimitiveShort; break; + case 'v': expected_name = "void"; class_root = ClassLinker::kPrimitiveVoid; break; + default: break; + } + } + if (expected_name != nullptr && name->Equals(expected_name)) { + ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->GetClassRoot(class_root); + DCHECK(klass != nullptr); + return klass; + } else { + Thread* self = Thread::Current(); + if (name == nullptr) { + // Note: ThrowNullPointerException() requires a message which we deliberately want to omit. + self->ThrowNewException("Ljava/lang/NullPointerException;", /* msg */ nullptr); + } else { + self->ThrowNewException("Ljava/lang/ClassNotFoundException;", name->ToModifiedUtf8().c_str()); + } + return nullptr; + } +} + ClassExt* Class::EnsureExtDataPresent(Thread* self) { ObjPtr<ClassExt> existing(GetExtData()); if (!existing.IsNull()) { @@ -156,9 +192,19 @@ void Class::SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self self->AssertPendingException(); } - { + if (kBitstringSubtypeCheckEnabled) { + // FIXME: This looks broken with respect to aborted transactions. ObjPtr<mirror::Class> h_this_ptr = h_this.Get(); SubtypeCheck<ObjPtr<mirror::Class>>::WriteStatus(h_this_ptr, new_status); + } else { + // The ClassStatus is always in the 4 most-significant bits of status_. + static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32"); + uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize); + if (Runtime::Current()->IsActiveTransaction()) { + h_this->SetField32Volatile<true>(StatusOffset(), new_status_value); + } else { + h_this->SetField32Volatile<false>(StatusOffset(), new_status_value); + } } // Setting the object size alloc fast path needs to be after the status write so that if the diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index ced7c7c908..b9a31e54b7 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -81,7 +81,7 @@ class MANAGED Class FINAL : public Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> ClassStatus GetStatus() REQUIRES_SHARED(Locks::mutator_lock_) { // Avoid including "subtype_check_bits_and_status.h" to get the field. - // The ClassStatus is always in the 4 most-significant of status_. + // The ClassStatus is always in the 4 most-significant bits of status_. return enum_cast<ClassStatus>( static_cast<uint32_t>(GetField32Volatile<kVerifyFlags>(StatusOffset())) >> (32 - 4)); } @@ -1134,6 +1134,10 @@ class MANAGED Class FINAL : public Object { void VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_); + // Get one of the primitive classes. + static ObjPtr<mirror::Class> GetPrimitiveClass(ObjPtr<mirror::String> name) + REQUIRES_SHARED(Locks::mutator_lock_); + // When class is verified, set the kAccSkipAccessChecks flag on each method. void SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 57a429cf1e..505b745200 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -405,18 +405,15 @@ static void PreloadDexCachesResolveMethod(ObjPtr<mirror::DexCache> dex_cache, ui } const DexFile* dex_file = dex_cache->GetDexFile(); const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx); - ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType( + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + + ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType( method_id.class_idx_, dex_cache, /* class_loader */ nullptr); if (klass == nullptr) { return; } - ArtMethod* method = klass->IsInterface() - ? klass->FindInterfaceMethod(dex_cache, method_idx, kRuntimePointerSize) - : klass->FindClassMethod(dex_cache, method_idx, kRuntimePointerSize); - if (method == nullptr) { - return; - } - dex_cache->SetResolvedMethod(method_idx, method, kRuntimePointerSize); + // Call FindResolvedMethod to populate the dex cache. + class_linker->FindResolvedMethod(klass, dex_cache, /* class_loader */ nullptr, method_idx); } struct DexCacheStats { diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 4597f68f54..e518553292 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -176,6 +176,12 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean return soa.AddLocalReference<jclass>(c.Get()); } +static jclass Class_getPrimitiveClass(JNIEnv* env, jclass, jstring name) { + ScopedFastNativeObjectAccess soa(env); + ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(soa.Decode<mirror::String>(name)); + return soa.AddLocalReference<jclass>(klass); +} + static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { ScopedFastNativeObjectAccess soa(env); StackHandleScope<1> hs(soa.Self()); @@ -869,6 +875,7 @@ static JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Class, getInnerClassFlags, "(I)I"), FAST_NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"), FAST_NATIVE_METHOD(Class, getInterfacesInternal, "()[Ljava/lang/Class;"), + FAST_NATIVE_METHOD(Class, getPrimitiveClass, "(Ljava/lang/String;)Ljava/lang/Class;"), FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"), FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"), FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"), diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 7aca12e56b..d0aec116a4 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -120,7 +120,6 @@ #include "native/java_lang_Thread.h" #include "native/java_lang_Throwable.h" #include "native/java_lang_VMClassLoader.h" -#include "native/java_lang_Void.h" #include "native/java_lang_invoke_MethodHandleImpl.h" #include "native/java_lang_ref_FinalizerReference.h" #include "native/java_lang_ref_Reference.h" @@ -1746,7 +1745,6 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { register_java_lang_Thread(env); register_java_lang_Throwable(env); register_java_lang_VMClassLoader(env); - register_java_lang_Void(env); register_java_util_concurrent_atomic_AtomicLong(env); register_libcore_util_CharsetUtils(env); register_org_apache_harmony_dalvik_ddmc_DdmServer(env); diff --git a/runtime/subtype_check.h b/runtime/subtype_check.h index 54d2f00106..3b1d5f8c4a 100644 --- a/runtime/subtype_check.h +++ b/runtime/subtype_check.h @@ -24,6 +24,9 @@ #include "mirror/class.h" #include "runtime.h" +// Build flag for the bitstring subtype check runtime hooks. +constexpr bool kBitstringSubtypeCheckEnabled = false; + /** * Any node in a tree can have its path (from the root to the node) represented as a string by * concatenating the path of the parent to that of the current node. diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 0829c5422e..443c35f979 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -263,18 +263,6 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file, UnquickenDexFile(target_dex_file, source_dex_file.Begin(), decompile_return_instruction); } -static void UpdateAccessFlags(uint8_t* data, uint32_t new_flag, bool is_method) { - // Go back 1 uleb to start. - data = ReverseSearchUnsignedLeb128(data); - if (is_method) { - // Methods have another uleb field before the access flags - data = ReverseSearchUnsignedLeb128(data); - } - DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)), - new_flag); - UpdateUnsignedLeb128(data, new_flag); -} - void VdexFile::UnquickenDexFile(const DexFile& target_dex_file, const uint8_t* source_dex_begin, bool decompile_return_instruction) const { @@ -312,14 +300,8 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file, quicken_data, decompile_return_instruction); } - UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()), - class_it.GetMemberAccessFlags(), - /*is_method*/ true); - } else { - UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()), - class_it.GetMemberAccessFlags(), - /*is_method*/ false); } + DexFile::UnHideAccessFlags(class_it); } } } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 3e9dfd18d7..66e578f312 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3899,21 +3899,13 @@ ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess( } ObjPtr<mirror::Class> klass = klass_type.GetClass(); const RegType& referrer = GetDeclaringClass(); - auto* cl = Runtime::Current()->GetClassLinker(); - auto pointer_size = cl->GetImagePointerSize(); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + PointerSize pointer_size = class_linker->GetImagePointerSize(); ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size); if (res_method == nullptr) { - // Try to find the method with the appropriate lookup for the klass type (interface or not). - // If this lookup does not match `method_type`, errors shall be reported below. - if (klass->IsInterface()) { - res_method = klass->FindInterfaceMethod(dex_cache_.Get(), dex_method_idx, pointer_size); - } else { - res_method = klass->FindClassMethod(dex_cache_.Get(), dex_method_idx, pointer_size); - } - if (res_method != nullptr) { - dex_cache_->SetResolvedMethod(dex_method_idx, res_method, pointer_size); - } + res_method = class_linker->FindResolvedMethod( + klass, dex_cache_.Get(), class_loader_.Get(), dex_method_idx); } // Record result of method resolution attempt. The klass resolution has recorded whether diff --git a/test/670-bitstring-type-check/build b/test/670-bitstring-type-check/build new file mode 100644 index 0000000000..38307f2c0f --- /dev/null +++ b/test/670-bitstring-type-check/build @@ -0,0 +1,216 @@ +#!/bin/bash +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Stop if something fails. +set -e + +# Write out the source file. + +mkdir src +cat >src/Main.java <<EOF +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +EOF + +for i in {0..8192}; do echo "class Level1Class$i { }" >>src/Main.java; done +for i in {0..1024}; do echo "class Level2Class$i extends Level1Class0 { }" >>src/Main.java; done + +cat >>src/Main.java <<EOF +class Level3Class0 extends Level2Class0 { } +class Level4Class0 extends Level3Class0 { } +class Level5Class0 extends Level4Class0 { } +class Level6Class0 extends Level5Class0 { } +class Level7Class0 extends Level6Class0 { } +class Level8Class0 extends Level7Class0 { } +class Level9Class0 extends Level8Class0 { } + +public class Main { + public static void main(String[] args) throws Exception { + // 8193 classes at level 1 make sure we shall have an overflow if there are 13 or + // less bits for the level 1 character. 1025 classes at level 2 similarly guarantees + // an overflow if the number of bits for level 2 character is 10 or less. To test + // type checks also for the depth overflow, we provide a hierarchy 9 levels deep. + + // Make sure the bitstrings are initialized. + for (int i = 0; i <= 8192; ++i) { + Class.forName("Level1Class" + i).newInstance(); + } + for (int i = 0; i <= 1024; ++i) { + Class.forName("Level2Class" + i).newInstance(); + } + + // Note: Using a different class for tests so that verification of Main.main() does + // not try to resolve classes used by the tests. This guarantees uninitialized type + // check bitstrings when we enter Main.main() and start initializing them above. + Helper.testInstanceOf(); + Helper.testCheckCast(); + } +} + +class Helper { + public static void testInstanceOf() throws Exception { + for (int i = 1; i <= 9; ++i) { + Object o = createInstance("Level" + i + "Class0"); + assertTrue(o instanceof Level1Class0); + if (o instanceof Level2Class0) { + assertFalse(i < 2); + } else { + assertTrue(i < 2); + } + if (o instanceof Level3Class0) { + assertFalse(i < 3); + } else { + assertTrue(i < 3); + } + if (o instanceof Level4Class0) { + assertFalse(i < 4); + } else { + assertTrue(i < 4); + } + if (o instanceof Level5Class0) { + assertFalse(i < 5); + } else { + assertTrue(i < 5); + } + if (o instanceof Level6Class0) { + assertFalse(i < 6); + } else { + assertTrue(i < 6); + } + if (o instanceof Level7Class0) { + assertFalse(i < 7); + } else { + assertTrue(i < 7); + } + if (o instanceof Level8Class0) { + assertFalse(i < 8); + } else { + assertTrue(i < 8); + } + if (o instanceof Level9Class0) { + assertFalse(i < 9); + } else { + assertTrue(i < 9); + } + } + + assertTrue(createInstance("Level1Class8192") instanceof Level1Class8192); + assertFalse(createInstance("Level1Class8192") instanceof Level1Class0); + assertTrue(createInstance("Level2Class1024") instanceof Level2Class1024); + assertTrue(createInstance("Level2Class1024") instanceof Level1Class0); + assertFalse(createInstance("Level2Class1024") instanceof Level2Class0); + } + + public static void testCheckCast() throws Exception { + for (int i = 1; i <= 9; ++i) { + Object o = createInstance("Level" + i + "Class0"); + Level1Class0 l1c0 = (Level1Class0) o; + try { + Level2Class0 l2c0 = (Level2Class0) o; + assertFalse(i < 2); + } catch (ClassCastException cce) { + assertTrue(i < 2); + } + try { + Level3Class0 l3c0 = (Level3Class0) o; + assertFalse(i < 3); + } catch (ClassCastException cce) { + assertTrue(i < 3); + } + try { + Level4Class0 l4c0 = (Level4Class0) o; + assertFalse(i < 4); + } catch (ClassCastException cce) { + assertTrue(i < 4); + } + try { + Level5Class0 l5c0 = (Level5Class0) o; + assertFalse(i < 5); + } catch (ClassCastException cce) { + assertTrue(i < 5); + } + try { + Level6Class0 l6c0 = (Level6Class0) o; + assertFalse(i < 6); + } catch (ClassCastException cce) { + assertTrue(i < 6); + } + try { + Level7Class0 l7c0 = (Level7Class0) o; + assertFalse(i < 7); + } catch (ClassCastException cce) { + assertTrue(i < 7); + } + try { + Level8Class0 l8c0 = (Level8Class0) o; + assertFalse(i < 8); + } catch (ClassCastException cce) { + assertTrue(i < 8); + } + try { + Level9Class0 l9c0 = (Level9Class0) o; + assertFalse(i < 9); + } catch (ClassCastException cce) { + assertTrue(i < 9); + } + } + + Level1Class8192 l1c8192 = (Level1Class8192) createInstance("Level1Class8192"); + try { + Level1Class0 l1c0 = (Level1Class0) createInstance("Level1Class8192"); + throw new AssertionError("Unexpected"); + } catch (ClassCastException expected) {} + Level2Class1024 l2c1024 = (Level2Class1024) createInstance("Level2Class1024"); + Level1Class0 l1c0 = (Level1Class0) createInstance("Level2Class1024"); + try { + Level2Class0 l2c0 = (Level2Class0) createInstance("Level2Class1024"); + throw new AssertionError("Unexpected"); + } catch (ClassCastException expected) {} + } + + public static Object createInstance(String className) throws Exception { + return Class.forName(className).newInstance(); + } + + public static void assertTrue(boolean value) throws Exception { + if (!value) { + throw new AssertionError(); + } + } + + public static void assertFalse(boolean value) throws Exception { + if (value) { + throw new AssertionError(); + } + } +} +EOF + +./default-build "$@" diff --git a/test/670-bitstring-type-check/expected.txt b/test/670-bitstring-type-check/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/670-bitstring-type-check/expected.txt diff --git a/test/670-bitstring-type-check/info.txt b/test/670-bitstring-type-check/info.txt new file mode 100644 index 0000000000..a34ba86171 --- /dev/null +++ b/test/670-bitstring-type-check/info.txt @@ -0,0 +1 @@ +Tests for the bitstring type checks. diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java index ddfadf3626..1a60185f49 100644 --- a/test/912-classes/src-art/art/Test912.java +++ b/test/912-classes/src-art/art/Test912.java @@ -398,6 +398,7 @@ public class Test912 { public static double dummy = Math.random(); // So it can't be compile-time initialized. } + @SuppressWarnings("RandomCast") private static class TestForInitFail { public static int dummy = ((int)Math.random())/0; // So it throws when initializing. } diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc index dfefce207b..9e65a9964c 100644 --- a/test/983-source-transform-verify/source_transform.cc +++ b/test/983-source-transform-verify/source_transform.cc @@ -14,30 +14,13 @@ * limitations under the License. */ -#include <inttypes.h> +#include "source_transform.h" -#include <cstdio> -#include <cstring> -#include <iostream> -#include <vector> +#include "jni.h" #include "android-base/stringprintf.h" -#include "jni.h" #include "jvmti.h" - -#include "base/macros.h" -#include "bytecode_utils.h" -#include "dex/code_item_accessors-inl.h" -#include "dex/art_dex_file_loader.h" -#include "dex/dex_file.h" -#include "dex/dex_file_loader.h" -#include "dex/dex_instruction.h" -#include "jit/jit.h" -#include "native_stack_dump.h" -#include "runtime.h" -#include "scoped_thread_state_change-inl.h" -#include "thread-current-inl.h" -#include "thread_list.h" +#include "scoped_local_ref.h" // Test infrastructure #include "jvmti_helper.h" @@ -48,9 +31,18 @@ namespace Test983SourceTransformVerify { constexpr bool kSkipInitialLoad = true; +static void Println(JNIEnv* env, const char* msg) { + ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983")); + jmethodID println_method = env->GetStaticMethodID(test_klass.get(), + "doPrintln", + "(Ljava/lang/String;)V"); + ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg)); + env->CallStaticVoidMethod(test_klass.get(), println_method, data.get()); +} + // The hook we are using. void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, - JNIEnv* jni_env ATTRIBUTE_UNUSED, + JNIEnv* env, jclass class_being_redefined, jobject loader ATTRIBUTE_UNUSED, const char* name, @@ -60,78 +52,24 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, jint* new_class_data_len ATTRIBUTE_UNUSED, unsigned char** new_class_data ATTRIBUTE_UNUSED) { if (kSkipInitialLoad && class_being_redefined == nullptr) { - // Something got loaded concurrently. Just ignore it for now. + // Something got loaded concurrently. Just ignore it for now. To make sure the test is + // repeatable we only care about things that come from RetransformClasses. return; } - std::cout << "Dex file hook for " << name << std::endl; + Println(env, android::base::StringPrintf("Dex file hook for %s", name).c_str()); if (IsJVM()) { return; } - // Due to b/72402467 the class_data_len might just be an estimate. - CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header)); - const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data); - uint32_t header_file_size = header->file_size_; - CHECK_LE(static_cast<jint>(header_file_size), class_data_len); - class_data_len = static_cast<jint>(header_file_size); - - const ArtDexFileLoader dex_file_loader; - std::string error; - std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data, - class_data_len, - "fake_location.dex", - /*location_checksum*/ 0, - /*oat_dex_file*/ nullptr, - /*verify*/ true, - /*verify_checksum*/ true, - &error)); - if (dex.get() == nullptr) { - std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl; - return; - } - for (uint32_t i = 0; i < dex->NumClassDefs(); i++) { - const DexFile::ClassDef& def = dex->GetClassDef(i); - const uint8_t* data_item = dex->GetClassData(def); - if (data_item == nullptr) { - continue; - } - for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) { - if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) { - continue; - } - for (const DexInstructionPcPair& pair : - art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) { - const Instruction& inst = pair.Inst(); - int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly); - if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER || - (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) { - std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex()) - << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : " - << inst.DumpString(dex.get()) << std::endl; - continue; - } - } - } - } + VerifyClassData(class_data_len, class_data); } // Get all capabilities except those related to retransformation. -jint OnLoad(JavaVM* vm, - char* options ATTRIBUTE_UNUSED, - void* reserved ATTRIBUTE_UNUSED) { - if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { - printf("Unable to get jvmti env!\n"); - return 1; - } - SetStandardCapabilities(jvmti_env); +extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) { jvmtiEventCallbacks cb; memset(&cb, 0, sizeof(cb)); cb.ClassFileLoadHook = CheckDexFileHook; - if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) { - printf("Unable to set class file load hook cb!\n"); - return 1; - } - return 0; + JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb))); } } // namespace Test983SourceTransformVerify diff --git a/test/983-source-transform-verify/source_transform.h b/test/983-source-transform-verify/source_transform.h index db9415aec1..2206498cc3 100644 --- a/test/983-source-transform-verify/source_transform.h +++ b/test/983-source-transform-verify/source_transform.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -22,7 +22,7 @@ namespace art { namespace Test983SourceTransformVerify { -jint OnLoad(JavaVM* vm, char* options, void* reserved); +void VerifyClassData(jint class_data_len, const unsigned char* class_data); } // namespace Test983SourceTransformVerify } // namespace art diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc new file mode 100644 index 0000000000..5353370ac6 --- /dev/null +++ b/test/983-source-transform-verify/source_transform_art.cc @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "source_transform.h" + +#include <inttypes.h> + +#include <memory> + +#include <android-base/logging.h> + +#include "dex/code_item_accessors-inl.h" +#include "dex/art_dex_file_loader.h" +#include "dex/dex_file.h" +#include "dex/dex_file_loader.h" +#include "dex/dex_instruction.h" + +namespace art { +namespace Test983SourceTransformVerify { + +// The hook we are using. +void VerifyClassData(jint class_data_len, const unsigned char* class_data) { + // Due to b/72402467 the class_data_len might just be an estimate. + CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header)); + const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data); + uint32_t header_file_size = header->file_size_; + CHECK_LE(static_cast<jint>(header_file_size), class_data_len); + class_data_len = static_cast<jint>(header_file_size); + + const ArtDexFileLoader dex_file_loader; + std::string error; + std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data, + class_data_len, + "fake_location.dex", + /*location_checksum*/ 0, + /*oat_dex_file*/ nullptr, + /*verify*/ true, + /*verify_checksum*/ true, + &error)); + CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error; + for (uint32_t i = 0; i < dex->NumClassDefs(); i++) { + const DexFile::ClassDef& def = dex->GetClassDef(i); + const uint8_t* data_item = dex->GetClassData(def); + if (data_item == nullptr) { + continue; + } + for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) { + if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) { + continue; + } + for (const DexInstructionPcPair& pair : + art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) { + const Instruction& inst = pair.Inst(); + int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly); + if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER || + (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) { + LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex()) + << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : " + << inst.DumpString(dex.get()) << std::endl; + } + } + } + } +} + +} // namespace Test983SourceTransformVerify +} // namespace art diff --git a/runtime/native/java_lang_Void.cc b/test/983-source-transform-verify/source_transform_slicer.cc index af83dd1a79..abf32e752e 100644 --- a/runtime/native/java_lang_Void.cc +++ b/test/983-source-transform-verify/source_transform_slicer.cc @@ -14,30 +14,28 @@ * limitations under the License. */ -#include "java_lang_Void.h" +#include "source_transform.h" -#include "nativehelper/jni_macros.h" +#pragma clang diagnostic push +// slicer defines its own CHECK. b/65422458 +#pragma push_macro("CHECK") +#undef CHECK -#include "class_linker-inl.h" -#include "jni_internal.h" -#include "native_util.h" -#include "runtime.h" -#include "scoped_fast_native_object_access-inl.h" +// Slicer's headers have code that triggers these warnings. b/65298177 +#pragma clang diagnostic ignored "-Wsign-compare" +#include "reader.h" -namespace art { - -static jclass Void_lookupType(JNIEnv* env, jclass) { - ScopedFastNativeObjectAccess soa(env); - return soa.AddLocalReference<jclass>( - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kPrimitiveVoid)); -} +#pragma pop_macro("CHECK") +#pragma clang diagnostic pop -static JNINativeMethod gMethods[] = { - FAST_NATIVE_METHOD(Void, lookupType, "()Ljava/lang/Class;"), -}; +namespace art { +namespace Test983SourceTransformVerify { -void register_java_lang_Void(JNIEnv* env) { - REGISTER_NATIVE_METHODS("java/lang/Void"); +// The hook we are using. +void VerifyClassData(jint class_data_len, const unsigned char* class_data) { + dex::Reader reader(class_data, class_data_len); + reader.CreateFullIr(); // This will verify all bytecode. } +} // namespace Test983SourceTransformVerify } // namespace art diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java index faae96aef6..7dc47ab06a 100644 --- a/test/983-source-transform-verify/src/art/Test983.java +++ b/test/983-source-transform-verify/src/art/Test983.java @@ -27,7 +27,15 @@ public class Test983 { doTest(); } + private native static void setupLoadHook(); + + /* called from JNI */ + public static void doPrintln(String str) { + System.out.println(str); + } + public static void doTest() { + setupLoadHook(); Redefinition.enableCommonRetransformation(true); Redefinition.doCommonClassRetransformation(Transform.class); Redefinition.doCommonClassRetransformation(Object.class); diff --git a/test/Android.bp b/test/Android.bp index 5f39ffefa9..9d44e09d36 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -62,7 +62,7 @@ art_cc_defaults { "libvixld-arm", "libvixld-arm64", "libart-gtest", - "libdexfile", + "libdexfiled", "libbase", "libicuuc", @@ -114,7 +114,7 @@ art_cc_defaults { shared_libs: [ "libartd", "libartd-compiler", - "libdexfile", + "libdexfiled", ], static_libs: [ "libgtest", @@ -151,7 +151,7 @@ art_cc_library { shared_libs: [ "libartd", "libartd-compiler", - "libdexfile", + "libdexfiled", "libbase", "libbacktrace", ], @@ -238,6 +238,7 @@ art_cc_defaults { "931-agent-thread/agent_thread.cc", "933-misc-events/misc_events.cc", "945-obsolete-native/obsolete_native.cc", + "983-source-transform-verify/source_transform.cc", "984-obsolete-invoke/obsolete_invoke.cc", "986-native-method-bind/native_bind.cc", "987-agent-bind/agent_bind.cc", @@ -288,20 +289,22 @@ art_cc_defaults { "909-attach-agent/attach.cc", "912-classes/classes_art.cc", "936-search-onload/search_onload.cc", - "983-source-transform-verify/source_transform.cc", + "983-source-transform-verify/source_transform_art.cc", "1940-ddms-ext/ddm_ext.cc", "1944-sudden-exit/sudden_exit.cc", ], shared_libs: [ "libbase", - "libdexfile", ], } art_cc_test_library { name: "libtiagent", defaults: ["libtiagent-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], } art_cc_test_library { @@ -310,24 +313,32 @@ art_cc_test_library { "art_debug_defaults", "libtiagent-defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } -art_cc_test_library { +cc_library_static { name: "libctstiagent", defaults: ["libtiagent-base-defaults"], + host_supported: false, + srcs: [ + "983-source-transform-verify/source_transform_slicer.cc", + ], whole_static_libs: [ - "libdexfile", - "libz", - "libziparchive", + "slicer", + "libz", // for slicer (using adler32). ], static_libs: [ "libbase", - "libcutils", - "libutils", ], - shared_libs: [ - "liblog", + header_libs: [ + // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are + // many problems with how we export headers that are making doing this the 'right' way + // difficult. + // TODO: move those headers to art/ rather than under runtime. + "libart_runtime_headers", ], export_include_dirs: ["ti-agent"], } @@ -413,7 +424,6 @@ cc_defaults { "708-jit-cache-churn/jit.cc", ], shared_libs: [ - "libdexfile", "libbacktrace", "libbase", "libnativehelper", @@ -423,7 +433,10 @@ cc_defaults { art_cc_test_library { name: "libarttest", defaults: ["libarttest-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], } art_cc_test_library { @@ -432,7 +445,10 @@ art_cc_test_library { "art_debug_defaults", "libarttest-defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } art_cc_test_library { diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index bb6ace1b06..b8427f491b 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -850,7 +850,7 @@ if [ "$HOST" = "n" ]; then fi # System libraries needed by libarttestd.so - PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so + PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so # Create a script with the command. The command can get longer than the longest # allowed adb command and there is no way to get the exit status from a adb shell diff --git a/test/knownfailures.json b/test/knownfailures.json index 8b5c63425c..ddf9098c64 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -377,12 +377,6 @@ "variant": "jvmti-stress & jit | redefine-stress & jit" }, { - "test_patterns": ["674-hiddenapi"], - "description": ["hiddenapi test is failing with redefine stress cdex"], - "bug": "http://b/72610009", - "variant": "redefine-stress & cdex-fast" - }, - { "test_patterns": ["616-cha"], "description": ["The test assumes a boot image exists."], "bug": "http://b/34193647", @@ -423,21 +417,13 @@ "variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile" }, { - "tests": [ - "714-invoke-custom-lambda-metafactory", - "950-redefine-intrinsic", - "951-threaded-obsolete", - "952-invoke-custom", - "952-invoke-custom-kinds", - "953-invoke-polymorphic-compiler", - "954-invoke-polymorphic-verifier", - "955-methodhandles-smali", - "956-methodhandles", - "957-methodhandle-transforms", - "958-methodhandle-stackframe", - "959-invoke-polymorphic-accessors", - "979-const-method-handle", - "990-method-handle-and-mr" + "test_patterns": [ + ".*invoke-custom.*", + ".*invoke-polymorphic.*", + ".*methodhandle.*", + ".*method-handle.*", + ".*varhandle.*", + ".*var-handle.*" ], "description": [ "Tests that use invoke-polymorphic/invoke-custom which is not yet supported by", @@ -460,9 +446,22 @@ }, { "tests": [ + "132-daemon-locks-shutdown", + "607-daemon-stress", + "602-deoptimizeable", + "121-simple-suspend-check", + "083-compiler-regressions" + ], + "description": ["Tests that have failed on redefine stress for unknown reasons"], + "bug": "b/73177368", + "variant": "redefine-stress" + }, + { + "tests": [ "097-duplicate-method", "138-duplicate-classes-check2", "159-app-image-fields", + "674-hiddenapi", "649-vdex-duplicate-method", "804-class-extends-itself", "921-hello-failure" @@ -481,6 +480,7 @@ "626-const-class-linking", "629-vdex-speed", "647-jni-get-field-id", + "674-hiddenapi", "944-transform-classloaders" ], "description": [ @@ -494,7 +494,7 @@ "004-ThreadStress" ], "description": "The thread stress test just takes too long with field-stress", - "variant": "jvmti-stress | field-stress | step-stress" + "variant": "jvmti-stress | field-stress | step-stress | redefine-stress" }, { "tests": [ @@ -653,11 +653,6 @@ "description": ["Test is designed to only check --compiler-filter=speed"] }, { - "test_patterns": [".*"], - "description": ["Tests are timing out for weeks now, disable to fix."], - "variant": "cdex-fast & redefine-stress" - }, - { "tests": "674-HelloWorld-Dm", "variant": "target", "description": ["Requires zip, which isn't available on device"] @@ -667,5 +662,11 @@ "variant": "speed-profile & debug & gcstress & target", "bug": "b/73275005", "description": ["Time out"] + }, + { + "tests": ["130-hprof"], + "env_vars": {"SANITIZE_HOST": "address"}, + "bug": "b/73060923", + "description": ["ASAN issue"] } ] diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py index 3d173f5571..4329ad4863 100755 --- a/test/testrunner/testrunner.py +++ b/test/testrunner/testrunner.py @@ -110,6 +110,7 @@ test_count = 0 total_test_count = 0 verbose = False dry_run = False +ignore_skips = False build = False gdb = False gdb_arg = '' @@ -710,6 +711,8 @@ def is_test_disabled(test, variant_set): return True if test in env.EXTRA_DISABLED_TESTS: return True + if ignore_skips: + return False variants_list = DISABLED_TEST_CONTAINER.get(test, {}) for variants in variants_list: variants_present = True @@ -878,6 +881,7 @@ def get_default_threads(target): def parse_option(): global verbose global dry_run + global ignore_skips global n_thread global build global gdb @@ -897,6 +901,8 @@ def parse_option(): parser.add_argument('--dry-run', action='store_true', dest='dry_run') parser.add_argument("--skip", action="append", dest="skips", default=[], help="Skip the given test in all circumstances.") + parser.add_argument("--no-skips", dest="ignore_skips", action="store_true", default=False, + help="Don't skip any run-test configurations listed in knownfailures.json.") parser.add_argument('--no-build-dependencies', action='store_false', dest='build', help="Don't build dependencies under any circumstances. This is the " + @@ -935,6 +941,7 @@ def parse_option(): verbose = True if options['n_thread']: n_thread = max(1, options['n_thread']) + ignore_skips = options['ignore_skips'] if options['dry_run']: dry_run = True verbose = True diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 9a7352e479..bfd165db10 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -28,7 +28,6 @@ #include "901-hello-ti-agent/basics.h" #include "909-attach-agent/attach.h" #include "936-search-onload/search_onload.h" -#include "983-source-transform-verify/source_transform.h" #include "1919-vminit-thread-start-timing/vminit.h" namespace art { @@ -83,7 +82,6 @@ static AgentLib agents[] = { { "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr }, { "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr }, { "943-private-recursive-jit", common_redefine::OnLoad, nullptr }, - { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr }, { "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr }, }; diff --git a/tools/amm/AmmTest/AndroidManifest.xml b/tools/amm/AmmTest/AndroidManifest.xml new file mode 100644 index 0000000000..16529bc054 --- /dev/null +++ b/tools/amm/AmmTest/AndroidManifest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.amm.test"> + + <application + android:label="AmmTest" + android:debuggable="true"> + + <activity android:name="com.android.amm.test.MainActivity"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/tools/amm/AmmTest/aahat.png b/tools/amm/AmmTest/aahat.png Binary files differnew file mode 100644 index 0000000000..01b92f4ebc --- /dev/null +++ b/tools/amm/AmmTest/aahat.png diff --git a/tools/amm/AmmTest/jni/ammtest.c b/tools/amm/AmmTest/jni/ammtest.c new file mode 100644 index 0000000000..9d4847526e --- /dev/null +++ b/tools/amm/AmmTest/jni/ammtest.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jni.h" + +// A large uninitialized array gets put in the .bss section: +char uninit[3 * 4096]; + +// A large initialized array gets put in the .data section: +char init[2 * 4096] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.." + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."; + +// A large constant initialized array gets put in the .rodata section: +const char cinit[1 * 4096] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.." + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."; + +JNIEXPORT jint JNICALL +Java_com_android_amm_test_SoCodeUse_nGetANumber(JNIEnv* env, jclass cls) { + (void) env; + (void) cls; + + uninit[4096] = init[123] + cinit[123]; + return 42; +} + diff --git a/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java new file mode 100644 index 0000000000..d8eba2ea20 --- /dev/null +++ b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.amm.test; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +/** + * Exercise loading of a bitmap. + */ +class BitmapUse { + + private Bitmap mBitmap; + + public BitmapUse() { + ClassLoader loader = BitmapUse.class.getClassLoader(); + mBitmap = BitmapFactory.decodeStream(loader.getResourceAsStream("aahat.png"), null, null); + } +} diff --git a/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java new file mode 100644 index 0000000000..4577f4b062 --- /dev/null +++ b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.amm.test; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.LinearLayout; + +public class MainActivity extends Activity { + + private BitmapUse mBitmapUse; + private SoCodeUse mSoCodeUse; + private TextureViewUse mTextureViewUse; + private SurfaceViewUse mSurfaceViewUse; + private ThreadedRendererUse mThreadedRendererUse; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mBitmapUse = new BitmapUse(); + mSoCodeUse = new SoCodeUse(); + + LinearLayout ll = new LinearLayout(this); + mTextureViewUse = new TextureViewUse(this, ll, 200, 500); + mSurfaceViewUse = new SurfaceViewUse(this, ll, 240, 250); + setContentView(ll); + + mThreadedRendererUse = new ThreadedRendererUse(this, 122, 152); + } +} + diff --git a/runtime/native/java_lang_Void.h b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java index 8777d8068c..9636c0f96c 100644 --- a/runtime/native/java_lang_Void.h +++ b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java @@ -14,15 +14,17 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ -#define ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ +package com.android.amm.test; -#include <jni.h> +class SoCodeUse { + private int value; -namespace art { + public SoCodeUse() { + // TODO: Figure out how to cause the native library to be unloaded when + // the SoCodeUse instance goes away? + System.loadLibrary("ammtestjni"); + value = nGetANumber(); + } -void register_java_lang_Void(JNIEnv* env); - -} // namespace art - -#endif // ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ + private static native int nGetANumber(); +} diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java new file mode 100644 index 0000000000..0c17c77c3f --- /dev/null +++ b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.amm.test; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.ViewGroup; + +class SurfaceViewUse { + + private SurfaceView mSurfaceView; + + /** + * Constructs a SurfaceView object with given dimensions. + * The surface view is added to the given ViewGroup object, which should be + * included in the main display. + */ + public SurfaceViewUse(Context context, ViewGroup vg, int width, int height) { + mSurfaceView = new SurfaceView(context); + vg.addView(mSurfaceView, width, height); + mSurfaceView.post(new CycleRunnable()); + } + + // To force as many graphics buffers as will ever be used to actually be + // used, we cycle the color of the surface view a handful of times right + // when things start up. + private class CycleRunnable implements Runnable { + private int mCycles = 0; + private int mRed = 255; + private int mGreen = 0; + private int mBlue = 255; + + public void run() { + if (mCycles < 10) { + mCycles++; + updateSurfaceView(); + mSurfaceView.post(this); + } + } + + private void updateSurfaceView() { + SurfaceHolder holder = mSurfaceView.getHolder(); + Canvas canvas = holder.lockHardwareCanvas(); + if (canvas != null) { + canvas.drawRGB(mRed, mGreen, mBlue); + int tmp = mRed; + holder.unlockCanvasAndPost(canvas); + mRed = mGreen; + mGreen = mBlue; + mBlue = tmp; + } + } + } +} + diff --git a/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java new file mode 100644 index 0000000000..51ffcd244f --- /dev/null +++ b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.amm.test; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.TextureView; +import android.view.ViewGroup; + +class TextureViewUse { + + private TextureView mTextureView; + + /** + * Constructs a TextureView object with given dimensions. + * The texture view is added to the given ViewGroup object, which should be + * included in the main display. + */ + public TextureViewUse(Context context, ViewGroup vg, int width, int height) { + mTextureView = new TextureView(context); + vg.addView(mTextureView, width, height); + mTextureView.post(new CycleRunnable()); + } + + // To force as many graphics buffers as will ever be used to actually be + // used, we cycle the color of the texture view a handful of times right + // when things start up. + private class CycleRunnable implements Runnable { + private int mCycles = 0; + private int mRed = 255; + private int mGreen = 255; + private int mBlue = 0; + + public void run() { + if (mCycles < 10) { + mCycles++; + updateTextureView(); + mTextureView.post(this); + } + } + + private void updateTextureView() { + Canvas canvas = mTextureView.lockCanvas(); + if (canvas != null) { + canvas.drawRGB(mRed, mGreen, mBlue); + int tmp = mRed; + mTextureView.unlockCanvasAndPost(canvas); + mRed = mGreen; + mGreen = mBlue; + mBlue = tmp; + } + } + } +} + diff --git a/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java new file mode 100644 index 0000000000..9c25612881 --- /dev/null +++ b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.amm.test; + +import android.content.Context; +import android.view.WindowManager; +import android.widget.TextView; + +class ThreadedRendererUse { + + private TextView mTextView; + + /** + * Cause a threaded renderer EGL allocation to be used, with given + * dimensions. + */ + public ThreadedRendererUse(Context context, int width, int height) { + mTextView = new TextView(context); + mTextView.setText("TRU"); + mTextView.setBackgroundColor(0xffff0000); + + // Adding a view to the WindowManager (as opposed to the app's root view + // hierarchy) causes a ThreadedRenderer and EGL allocations under the cover. + // We use a TextView here to trigger the use case, but we could use any + // other kind of view as well. + WindowManager wm = context.getSystemService(WindowManager.class); + WindowManager.LayoutParams layout = new WindowManager.LayoutParams(); + layout.width = width; + layout.height = height; + wm.addView(mTextView, layout); + + mTextView.post(new CycleRunnable()); + } + + // To force as many graphics buffers as will ever be used to actually be + // used, we cycle the text of the text view a handful of times right + // when things start up. + private class CycleRunnable implements Runnable { + private int mCycles = 0; + + public void run() { + if (mCycles < 10) { + mCycles++; + mTextView.setText("TRU " + mCycles); + mTextView.post(this); + } + } + } +} + diff --git a/tools/amm/Android.mk b/tools/amm/Android.mk new file mode 100644 index 0000000000..47030c5a7a --- /dev/null +++ b/tools/amm/Android.mk @@ -0,0 +1,34 @@ +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +# --- ammtestjni.so ------------- +include $(CLEAR_VARS) +LOCAL_MODULE := libammtestjni +LOCAL_SRC_FILES := $(call all-c-files-under, AmmTest/jni) +LOCAL_SDK_VERSION := current +include $(BUILD_SHARED_LIBRARY) + +# --- AmmTest.apk -------------- +include $(CLEAR_VARS) +LOCAL_PACKAGE_NAME := AmmTest +LOCAL_MODULE_TAGS := samples tests +LOCAL_SRC_FILES := $(call all-java-files-under, AmmTest/src) +LOCAL_SDK_VERSION := current +LOCAL_JNI_SHARED_LIBRARIES := libammtestjni +LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/AmmTest/aahat.png +LOCAL_MANIFEST_FILE := AmmTest/AndroidManifest.xml +include $(BUILD_PACKAGE) + diff --git a/tools/amm/README.md b/tools/amm/README.md new file mode 100644 index 0000000000..17f94a8d44 --- /dev/null +++ b/tools/amm/README.md @@ -0,0 +1,16 @@ +# Actionable Memory Metric + +The goal of the actionable memory metric (AMM) is to provide a view of an +application's memory use that application developers can track, understand, +and control. AMM can be thought of as a Java heap dump augmented with models +for non-Java allocations that app developers have some control of. + +There are two components of the actionable memory metric: +1. The value of the metric. +2. An actionable breakdown of the value of the metric. + +The metric is made up of a collection of separate models for different +categories of memory use. Each model contributes to the value and actionable +breakdown of the overall metric. + +See models/ for a list of models proposed for the actionable memory metric. diff --git a/tools/amm/models/Bitmap.md b/tools/amm/models/Bitmap.md new file mode 100644 index 0000000000..49a0b9d79a --- /dev/null +++ b/tools/amm/models/Bitmap.md @@ -0,0 +1,15 @@ +# Bitmap Model + +The value of the Bitmap model is the sum of bytes used for native pixel data +of instances of `android.graphics.Bitmap`. It is calculated by summing for +each instance `x` of `android.graphics.Bitmap`: + + x.getAllocationByteCount() + +The actionable breakdown of the Bitmap model is a breakdown by +`android.graphics.Bitmap` instance, including width, height, and ideally a +thumbnail image of each bitmap. + +For example, an 800 x 600 bitmap instance using the `ARGB_8888` pixel format +with native pixel data will be shown as an 800 x 600 bitmap instance taking up +1875 kB. diff --git a/tools/amm/models/DexCode.md b/tools/amm/models/DexCode.md new file mode 100644 index 0000000000..a907280db9 --- /dev/null +++ b/tools/amm/models/DexCode.md @@ -0,0 +1,17 @@ +# Dex Code Model + +The value of the Dex Code model is the sum of the original uncompressed file +sizes of all loaded dex files. It is calculated using the best approximation +of the dex file size available to us on device. On Android O, for example, +this can be approximated as the virtual size of the corresponding memory +mapped `.vdex` file read from `/proc/self/maps`. Different Android platform +versions and scenarios may require different approximations. + +The actionable breakdown of the dex code model is a breakdown by +`dalvik.system.DexFile` instance. Further breakdown of individual dex files +can be achieved using tools such as dexdump. + +For example, for an application `AmmTest.apk` that has a single `classes.dex` file +that is 500 KB uncompressed, the `DexFile` instance for +`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/base.apk` is shown as +Taking up 500 KB (or the best available approximation thereof). diff --git a/tools/amm/models/Graphics.md b/tools/amm/models/Graphics.md new file mode 100644 index 0000000000..b327961a64 --- /dev/null +++ b/tools/amm/models/Graphics.md @@ -0,0 +1,22 @@ +# Graphics Models + +There are three components to the graphics model, each modeling EGL memory +use: +1. For each `android.view.TextureView` instance: + 2 * (4 * width * height) + +2. For each `android.view.Surface$HwuiContext` instance: + 3 * (4 * width * height) + +3. For each initialized `android.view.ThreadedRenderer`: + 3 * (4 * width * height) + +Note: 4 is the number of bytes per pixel. 2 or 3 is the maximum number of +buffers that may be allocated. + +The actionable breakdown is the breakdown by `TextureView`, +`Surface$HwuiContext` and `ThreadedRenderer` instance, with further details +about the width and height associated with each instance. + +For example, an application with a single 64x256 `TextureView` instance will +be shown as taking up 128 KB. diff --git a/tools/amm/models/JavaHeap.md b/tools/amm/models/JavaHeap.md new file mode 100644 index 0000000000..c34c1865c0 --- /dev/null +++ b/tools/amm/models/JavaHeap.md @@ -0,0 +1,8 @@ +# Java Heap Model + +The value of the Java heap model is the sum of bytes of Java objects allocated +on the Java heap. It can be calculated using: + + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + +A Java heap dump is used for an actionable breakdown of the Java heap. diff --git a/tools/amm/models/SoCode.md b/tools/amm/models/SoCode.md new file mode 100644 index 0000000000..5d3184ebbf --- /dev/null +++ b/tools/amm/models/SoCode.md @@ -0,0 +1,17 @@ +# Shared Native Code Model + +The value of the Shared Native Code model is the sum of the virtual memory +sizes of all loaded `.so` files. It is calculated by reading `/proc/self/maps`. + +The actionable breakdown of the shared native code model is a breakdown by +library name. Unfortunately, due to technical limitations, this does not +include information about what caused a library to be loaded, whether the +library was loaded by the app or the platform, the library dependency graph, +or what is causing a library to remain loaded. Individual `.so` files can be +further broken down using tools such as `readelf`. + +For example, for an application `AmmTest.apk` that includes `libammtestjni.so` as a +native library that loads 36 KB worth of memory regions, `BaseClassLoader` will +be shown with library +`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/lib/arm64/libammtestjni.so` +taking up 36 KB. diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp index 57c9c095f8..f3342d39f6 100644 --- a/tools/cpp-define-generator/Android.bp +++ b/tools/cpp-define-generator/Android.bp @@ -28,7 +28,10 @@ cc_binary { // Do not use art_cc_binary because HOST_PREFER_32_BIT is incompatib "art_debug_defaults", "art_defaults", ], - include_dirs: ["art/runtime"], + include_dirs: [ + "art/libdexfile", + "art/runtime", + ], srcs: ["main.cc"], shared_libs: [ "libbase", diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp index f9824f1fa3..af87d31e53 100644 --- a/tools/hiddenapi/Android.bp +++ b/tools/hiddenapi/Android.bp @@ -30,7 +30,6 @@ cc_defaults { }, shared_libs: [ - "libdexfile", "libbase", ], } @@ -40,6 +39,7 @@ art_cc_binary { defaults: ["hiddenapi-defaults"], shared_libs: [ "libart", + "libdexfile", ], } @@ -51,6 +51,7 @@ art_cc_binary { ], shared_libs: [ "libartd", + "libdexfiled", ], } diff --git a/tools/public.libraries.buildbot.txt b/tools/public.libraries.buildbot.txt index 734fd1e50b..de636a813a 100644 --- a/tools/public.libraries.buildbot.txt +++ b/tools/public.libraries.buildbot.txt @@ -1,6 +1,7 @@ libart.so libartd.so libdexfile.so +libdexfiled.so libbacktrace.so libc.so libc++.so diff --git a/tools/titrace/Android.bp b/tools/titrace/Android.bp index 097622e756..21f266c087 100644 --- a/tools/titrace/Android.bp +++ b/tools/titrace/Android.bp @@ -40,9 +40,8 @@ cc_defaults { }, header_libs: [ "libopenjdkjvmti_headers", - "libart_runtime_headers", // for dex_instruction_list.h only - // "libbase_headers", ], + include_dirs: ["art/libdexfile"], // for dex_instruction_list.h only multilib: { lib32: { suffix: "32", |