summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--Android.mk5
-rw-r--r--benchmark/type-check/info.txt1
-rw-r--r--benchmark/type-check/src/TypeCheckBenchmark.java147
-rw-r--r--build/Android.gtest.mk9
-rw-r--r--compiler/Android.bp3
-rw-r--r--compiler/optimizing/instruction_builder.cc8
-rw-r--r--compiler/optimizing/nodes.h2
-rw-r--r--compiler/optimizing/reference_type_propagation.cc7
-rw-r--r--dex2oat/Android.bp4
-rw-r--r--dex2oat/linker/image_writer.cc2
-rw-r--r--dexdump/Android.bp1
-rw-r--r--dexdump/dexdump.cc54
-rw-r--r--dexlayout/Android.bp11
-rw-r--r--dexlist/dexlist.cc53
-rw-r--r--libdexfile/Android.bp125
-rw-r--r--libdexfile/dex/base64_test_util.h (renamed from runtime/dex/base64_test_util.h)9
-rw-r--r--libdexfile/dex/code_item_accessors-inl.h (renamed from runtime/dex/code_item_accessors-inl.h)6
-rw-r--r--libdexfile/dex/code_item_accessors.h (renamed from runtime/dex/code_item_accessors.h)7
-rw-r--r--libdexfile/dex/code_item_accessors_test.cc (renamed from runtime/dex/code_item_accessors_test.cc)0
-rw-r--r--libdexfile/dex/compact_dex_debug_info.cc (renamed from runtime/dex/compact_dex_debug_info.cc)0
-rw-r--r--libdexfile/dex/compact_dex_debug_info.h (renamed from runtime/dex/compact_dex_debug_info.h)6
-rw-r--r--libdexfile/dex/compact_dex_debug_info_test.cc (renamed from runtime/dex/compact_dex_debug_info_test.cc)4
-rw-r--r--libdexfile/dex/compact_dex_file.cc (renamed from runtime/dex/compact_dex_file.cc)0
-rw-r--r--libdexfile/dex/compact_dex_file.h (renamed from runtime/dex/compact_dex_file.h)6
-rw-r--r--libdexfile/dex/compact_dex_file_test.cc (renamed from runtime/dex/compact_dex_file_test.cc)0
-rw-r--r--libdexfile/dex/compact_dex_level.h (renamed from runtime/dex/compact_dex_level.h)7
-rw-r--r--libdexfile/dex/compact_dex_utils.h (renamed from runtime/dex/compact_dex_utils.h)6
-rw-r--r--libdexfile/dex/descriptors_names.cc (renamed from runtime/dex/descriptors_names.cc)0
-rw-r--r--libdexfile/dex/descriptors_names.h (renamed from runtime/dex/descriptors_names.h)6
-rw-r--r--libdexfile/dex/dex_cache_resolved_classes.h (renamed from runtime/dex_cache_resolved_classes.h)6
-rw-r--r--libdexfile/dex/dex_file-inl.h (renamed from runtime/dex/dex_file-inl.h)7
-rw-r--r--libdexfile/dex/dex_file.cc (renamed from runtime/dex/dex_file.cc)15
-rw-r--r--libdexfile/dex/dex_file.h (renamed from runtime/dex/dex_file.h)10
-rw-r--r--libdexfile/dex/dex_file_exception_helpers.cc (renamed from runtime/dex/dex_file_exception_helpers.cc)0
-rw-r--r--libdexfile/dex/dex_file_exception_helpers.h (renamed from runtime/dex/dex_file_exception_helpers.h)6
-rw-r--r--libdexfile/dex/dex_file_loader.cc (renamed from runtime/dex/dex_file_loader.cc)0
-rw-r--r--libdexfile/dex/dex_file_loader.h (renamed from runtime/dex/dex_file_loader.h)6
-rw-r--r--libdexfile/dex/dex_file_loader_test.cc (renamed from runtime/dex/dex_file_loader_test.cc)0
-rw-r--r--libdexfile/dex/dex_file_reference.h (renamed from runtime/dex/dex_file_reference.h)6
-rw-r--r--libdexfile/dex/dex_file_tracking_registrar.cc (renamed from runtime/dex/dex_file_tracking_registrar.cc)0
-rw-r--r--libdexfile/dex/dex_file_tracking_registrar.h (renamed from runtime/dex/dex_file_tracking_registrar.h)6
-rw-r--r--libdexfile/dex/dex_file_types.h (renamed from runtime/dex/dex_file_types.h)6
-rw-r--r--libdexfile/dex/dex_file_verifier.cc (renamed from runtime/dex/dex_file_verifier.cc)0
-rw-r--r--libdexfile/dex/dex_file_verifier.h (renamed from runtime/dex/dex_file_verifier.h)7
-rw-r--r--libdexfile/dex/dex_file_verifier_test.cc (renamed from runtime/dex/dex_file_verifier_test.cc)0
-rw-r--r--libdexfile/dex/dex_instruction-inl.h (renamed from runtime/dex/dex_instruction-inl.h)6
-rw-r--r--libdexfile/dex/dex_instruction.cc (renamed from runtime/dex/dex_instruction.cc)0
-rw-r--r--libdexfile/dex/dex_instruction.h (renamed from runtime/dex/dex_instruction.h)6
-rw-r--r--libdexfile/dex/dex_instruction_iterator.h (renamed from runtime/dex/dex_instruction_iterator.h)6
-rw-r--r--libdexfile/dex/dex_instruction_list.h (renamed from runtime/dex/dex_instruction_list.h)8
-rw-r--r--libdexfile/dex/dex_instruction_test.cc (renamed from runtime/dex/dex_instruction_test.cc)0
-rw-r--r--libdexfile/dex/dex_instruction_utils.h (renamed from runtime/dex/dex_instruction_utils.h)6
-rw-r--r--libdexfile/dex/invoke_type.h (renamed from runtime/dex/invoke_type.h)6
-rw-r--r--libdexfile/dex/modifiers.cc (renamed from runtime/dex/modifiers.cc)0
-rw-r--r--libdexfile/dex/modifiers.h (renamed from runtime/dex/modifiers.h)6
-rw-r--r--libdexfile/dex/standard_dex_file.cc (renamed from runtime/dex/standard_dex_file.cc)0
-rw-r--r--libdexfile/dex/standard_dex_file.h (renamed from runtime/dex/standard_dex_file.h)6
-rw-r--r--libdexfile/dex/utf-inl.h (renamed from runtime/dex/utf-inl.h)6
-rw-r--r--libdexfile/dex/utf.cc (renamed from runtime/dex/utf.cc)0
-rw-r--r--libdexfile/dex/utf.h (renamed from runtime/dex/utf.h)6
-rw-r--r--libdexfile/dex/utf_test.cc (renamed from runtime/dex/utf_test.cc)0
l---------libdexfile/generate-operator-out.py1
-rw-r--r--oatdump/Android.bp4
-rw-r--r--oatdump/oatdump.cc8
-rw-r--r--openjdkjvmti/Android.bp3
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc37
-rw-r--r--profman/Android.bp3
-rw-r--r--profman/profile_assistant_test.cc95
-rw-r--r--profman/profman.cc65
-rw-r--r--runtime/Android.bp94
-rw-r--r--runtime/base/stringpiece.cc7
-rw-r--r--runtime/base/stringpiece.h7
-rw-r--r--runtime/check_jni.cc31
-rw-r--r--runtime/class_linker-inl.h9
-rw-r--r--runtime/class_linker.cc61
-rw-r--r--runtime/class_linker.h9
-rw-r--r--runtime/dex/art_dex_file_loader.cc8
-rw-r--r--runtime/dex/art_dex_file_loader.h2
-rw-r--r--runtime/dex/art_dex_file_loader_test.cc13
-rw-r--r--runtime/dex/dex_file_annotations.cc2
-rw-r--r--runtime/dex/dex_file_annotations.h2
-rw-r--r--runtime/dex/dex_file_layout.cc3
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h3
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/instrumentation.cc15
-rw-r--r--runtime/interpreter/unstarted_runtime.cc20
-rw-r--r--runtime/interpreter/unstarted_runtime_list.h2
-rw-r--r--runtime/java_vm_ext.h2
-rw-r--r--runtime/jit/profile_compilation_info.cc55
-rw-r--r--runtime/jit/profile_compilation_info.h10
-rw-r--r--runtime/jit/profile_compilation_info_test.cc40
-rw-r--r--runtime/jit/profile_saver.cc2
-rw-r--r--runtime/jni_env_ext.h11
-rw-r--r--runtime/mirror/class-inl.h2
-rw-r--r--runtime/mirror/class.cc48
-rw-r--r--runtime/mirror/class.h6
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc13
-rw-r--r--runtime/native/java_lang_Class.cc7
-rw-r--r--runtime/runtime.cc2
-rw-r--r--runtime/subtype_check.h3
-rw-r--r--runtime/vdex_file.cc20
-rw-r--r--runtime/verifier/method_verifier.cc16
-rw-r--r--test/670-bitstring-type-check/build216
-rw-r--r--test/670-bitstring-type-check/expected.txt0
-rw-r--r--test/670-bitstring-type-check/info.txt1
-rw-r--r--test/912-classes/src-art/art/Test912.java1
-rw-r--r--test/983-source-transform-verify/source_transform.cc100
-rw-r--r--test/983-source-transform-verify/source_transform.h4
-rw-r--r--test/983-source-transform-verify/source_transform_art.cc80
-rw-r--r--test/983-source-transform-verify/source_transform_slicer.cc (renamed from runtime/native/java_lang_Void.cc)36
-rw-r--r--test/983-source-transform-verify/src/art/Test983.java8
-rw-r--r--test/Android.bp52
-rwxr-xr-xtest/etc/run-test-jar2
-rw-r--r--test/knownfailures.json55
-rwxr-xr-xtest/testrunner/testrunner.py7
-rw-r--r--test/ti-agent/common_load.cc2
-rw-r--r--tools/amm/AmmTest/AndroidManifest.xml17
-rw-r--r--tools/amm/AmmTest/aahat.pngbin0 -> 6904 bytes
-rw-r--r--tools/amm/AmmTest/jni/ammtest.c228
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java33
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java46
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java (renamed from runtime/native/java_lang_Void.h)20
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java71
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java69
-rw-r--r--tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java64
-rw-r--r--tools/amm/Android.mk34
-rw-r--r--tools/amm/README.md16
-rw-r--r--tools/amm/models/Bitmap.md15
-rw-r--r--tools/amm/models/DexCode.md17
-rw-r--r--tools/amm/models/Graphics.md22
-rw-r--r--tools/amm/models/JavaHeap.md8
-rw-r--r--tools/amm/models/SoCode.md17
-rw-r--r--tools/cpp-define-generator/Android.bp5
-rw-r--r--tools/hiddenapi/Android.bp3
-rw-r--r--tools/public.libraries.buildbot.txt1
-rw-r--r--tools/titrace/Android.bp3
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
new file mode 100644
index 0000000000..01b92f4ebc
--- /dev/null
+++ b/tools/amm/AmmTest/aahat.png
Binary files differ
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",