Merge "Make VariableHandleScope consistent between 32 & 64 bit"
diff --git a/Android.mk b/Android.mk
index ba131c6..1a5daff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -31,13 +31,8 @@
.PHONY: clean-oat-host
clean-oat-host:
find $(OUT_DIR) -name "*.oat" -o -name "*.odex" -o -name "*.art" -o -name '*.vdex' | xargs rm -f
-ifneq ($(TMPDIR),)
- rm -rf $(TMPDIR)/$(USER)/test-*/dalvik-cache/*
+ rm -rf $(TMPDIR)/*/test-*/dalvik-cache/*
rm -rf $(TMPDIR)/android-data/dalvik-cache/*
-else
- rm -rf /tmp/$(USER)/test-*/dalvik-cache/*
- rm -rf /tmp/android-data/dalvik-cache/*
-endif
.PHONY: clean-oat-target
clean-oat-target:
@@ -68,7 +63,6 @@
include $(art_path)/tools/amm/Android.mk
include $(art_path)/tools/dexfuzz/Android.mk
include $(art_path)/tools/veridex/Android.mk
-include $(art_path)/libart_fake/Android.mk
ART_HOST_DEPENDENCIES := \
$(ART_HOST_EXECUTABLES) \
@@ -393,9 +387,6 @@
profman \
libadbconnection \
-# For nosy apps, we provide a fake library that avoids namespace issues and gives some warnings.
-LOCAL_REQUIRED_MODULES += libart_fake
-
# Potentially add in debug variants:
#
# * We will never add them if PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD = false.
@@ -497,6 +488,22 @@
.PHONY: build-art-target-golem
# Also include libartbenchmark, we always include it when running golem.
# libstdc++ is needed when building for ART_TARGET_LINUX.
+#
+# Also include the bootstrap Bionic libraries (libc, libdl, libm).
+# These are required as the "main" libc, libdl, and libm have moved to
+# the Runtime APEX. This is a temporary change needed until Golem
+# fully supports the Runtime APEX.
+# TODO(b/121117762): Remove this when the ART Buildbot and Golem have
+# full support for the Runtime APEX.
+#
+# Also include a copy of the ICU .dat prebuilt files in
+# /system/etc/icu on target (see module `icu-data-art-test`), so that
+# it can found even if the Runtime APEX is not available, by setting
+# the environment variable `ART_TEST_ANDROID_RUNTIME_ROOT` to
+# "/system" on device. This is a temporary change needed until Golem
+# fully supports the Runtime APEX.
+# TODO(b/121117762): Remove this when the ART Buildbot and Golem have
+# full support for the Runtime APEX.
ART_TARGET_SHARED_LIBRARY_BENCHMARK := $(TARGET_OUT_SHARED_LIBRARIES)/libartbenchmark.so
build-art-target-golem: dex2oat dalvikvm linker libstdc++ \
$(TARGET_OUT_EXECUTABLES)/art \
@@ -505,7 +512,9 @@
$(ART_TARGET_SHARED_LIBRARY_DEPENDENCIES) \
$(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
$(TARGET_CORE_IMG_OUT_BASE).art \
- $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art
+ $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art \
+ libc.bootstrap libdl.bootstrap libm.bootstrap \
+ icu-data-art-test
# remove debug libraries from public.libraries.txt because golem builds
# won't have it.
sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 341df78..e28ce2b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 The Android Open Source Project
+# Copyright (C) 2014 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.
@@ -50,6 +50,9 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libart_*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libartd_*)
+# Old Android Runtime APEX package, before the introduction of "release" and "debug" packages.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.runtime.apex)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index c73b988..5208d64 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -74,8 +74,7 @@
TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art
# Modules to compile for core.art.
-# TODO: Move conscrypt from CORE_IMG_JARS to TEST_CORE_JARS and adjust scripts to fix Golem.
-CORE_IMG_JARS := core-oj core-libart core-simple okhttp bouncycastle apache-xml conscrypt
+CORE_IMG_JARS := core-oj core-libart core-simple okhttp bouncycastle apache-xml
HOST_CORE_IMG_JARS := $(addsuffix -hostdex,$(CORE_IMG_JARS))
TARGET_CORE_IMG_JARS := $(addsuffix -testdex,$(CORE_IMG_JARS))
HOST_CORE_IMG_DEX_LOCATIONS := $(foreach jar,$(HOST_CORE_IMG_JARS), $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
@@ -88,7 +87,7 @@
TARGET_CORE_IMG_DEX_FILES := $(foreach jar,$(TARGET_CORE_IMG_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
# Jar files for the boot class path for testing. Must start with CORE_IMG_JARS.
-TEST_CORE_JARS := $(CORE_IMG_JARS)
+TEST_CORE_JARS := $(CORE_IMG_JARS) conscrypt
HOST_TEST_CORE_JARS := $(addsuffix -hostdex,$(TEST_CORE_JARS))
TARGET_TEST_CORE_JARS := $(addsuffix -testdex,$(TEST_CORE_JARS))
HOST_CORE_DEX_LOCATIONS := $(foreach jar,$(HOST_TEST_CORE_JARS), $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index be1791b..12eae89 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -20,12 +20,8 @@
include art/build/Android.common_path.mk
# Directory used for temporary test files on the host.
-# Use a hash calculated from CWD and USER as one of the path
-# components for the test output. This should allow us to run tests from
-# multiple repositories at the same time.
-# We only take the first few characters to keep paths short.
-ART_TMPDIR := $(if $(TMPDIR),$(TMPDIR),/tmp)
-ART_HOST_TEST_DIR := $(ART_TMPDIR)/test-art-$(shell echo $$CWD-${USER} | $(MD5SUM) | cut -c-5)
+# TMPDIR is always provided by the build system as $OUT_DIR-unique temporary directory.
+ART_HOST_TEST_DIR := $(TMPDIR)/test-art
# List of known broken tests that we won't attempt to execute. The test name must be the full
# rule name such as test-art-host-oat-optimizing-HelloWorld64.
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a926d9a..f00da9c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -371,8 +371,8 @@
ART_TEST_MODULES := \
art_cmdline_tests \
- art_compiler_tests \
art_compiler_host_tests \
+ art_compiler_tests \
art_dex2oat_tests \
art_dexanalyze_tests \
art_dexdiag_tests \
@@ -383,12 +383,14 @@
art_hiddenapi_tests \
art_imgdiag_tests \
art_libartbase_tests \
+ art_libdexfile_external_tests \
+ art_libdexfile_support_tests \
art_libdexfile_tests \
art_libprofile_tests \
art_oatdump_tests \
art_profman_tests \
- art_runtime_tests \
art_runtime_compiler_tests \
+ art_runtime_tests \
art_sigchain_tests \
ART_TARGET_GTEST_FILES := $(foreach m,$(ART_TEST_MODULES),\
@@ -423,6 +425,9 @@
endif
ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := '/apex/com.android.runtime'
+ifneq ($(ART_TEST_ANDROID_RUNTIME_ROOT),)
+ ART_GTEST_TARGET_ANDROID_RUNTIME_ROOT := $(ART_TEST_ANDROID_RUNTIME_ROOT)
+endif
# Define a make rule for a target device gtest.
# $(1): gtest name - the name of the test we're building such as leb128_test.
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 193a3c1..47729c1 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -28,21 +28,7 @@
bionic_binaries_both = [
"linker",
]
-// - Fake library that avoids namespace issues and gives some warnings for nosy apps.
-art_runtime_fake_native_shared_libs = [
- // FIXME: Does not work as-is, because `libart_fake` is defined in libart_fake/Android.mk,
- // and because a module defined in a Blueprint file cannot depend on a module defined in a
- // Makefile. To support `libart_fake` as a dependency of this APEX module, we can either
- // (probably in that order of preference):
- // a. translate that logic into Blueprint; or
- // b. write the whole Android Runtime APEX generation logic in Android.mk; or
- // c. introduce an `art_apex` module type extending the `apex` module type and write the
- // corresponding Go logic to handle this extra dependency.
- //"libart_fake",
-]
// - Debug variants (binaries for which a 32-bit version is preferred).
-// FIXME: These modules are optional (the built product can decide to include them or not).
-// Should they be moved to another APEX file?
art_runtime_debug_binaries_prefer32 = [
"dex2oatd",
"dexoptanalyzerd",
@@ -55,14 +41,14 @@
"libopenjdkjvmd",
"libopenjdkjvmtid",
"libadbconnectiond",
- "libjavacrypto",
]
-// Files associated with bionic / managed core library time zone APIs.
-art_runtime_time_zone_prebuilts = [
+// Data files associated with bionic / managed core library APIs.
+art_runtime_data_file_prebuilts = [
"apex_tz_version",
"apex_tzdata",
"apex_tzlookup.xml",
+ "apex_icu.dat",
]
// Modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
@@ -72,13 +58,15 @@
"dexlist",
]
-art_tools_device_binaries = [
+// Device-only modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
+art_tools_device_only_binaries = [
+ // oatdump cannot link with host linux_bionic due to not using clang lld;
+ // TODO: Make it work with clang lld.
"oatdump",
]
// Host-only modules listed in LOCAL_REQUIRED_MODULES for module art-tools in art/Android.mk.
-// TODO: Include these modules in the future "host APEX".
-art_tools_host_binaries = [
+art_tools_host_only_binaries = [
// FIXME: Does not work as-is, because `ahat` is defined in tools/ahat/Android.mk
// (same issue as for `libart_fake` above).
//"ahat",
@@ -86,7 +74,8 @@
// ...
]
-art_tools_binaries = art_tools_common_binaries + art_tools_device_binaries
+art_tools_device_binaries = art_tools_common_binaries + art_tools_device_only_binaries
+art_tools_host_binaries = art_tools_common_binaries + art_tools_host_only_binaries
apex_key {
name: "com.android.runtime.key",
@@ -112,7 +101,6 @@
compile_multilib: "both",
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
- + art_runtime_fake_native_shared_libs
+ bionic_native_shared_libs,
multilib: {
both: {
@@ -128,7 +116,7 @@
binaries: [],
}
},
- prebuilts: art_runtime_time_zone_prebuilts
+ prebuilts: art_runtime_data_file_prebuilts
+ ["com.android.runtime.ld.config.txt"],
key: "com.android.runtime.key",
}
@@ -141,7 +129,6 @@
compile_multilib: "both",
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
- + art_runtime_fake_native_shared_libs
+ art_runtime_debug_native_shared_libs
+ bionic_native_shared_libs,
multilib: {
@@ -156,10 +143,10 @@
+ art_runtime_debug_binaries_prefer32,
},
first: {
- binaries: art_tools_binaries,
+ binaries: art_tools_device_binaries,
}
},
- prebuilts: art_runtime_time_zone_prebuilts
+ prebuilts: art_runtime_data_file_prebuilts
+ ["com.android.runtime.ld.config.txt"],
key: "com.android.runtime.key",
}
@@ -177,7 +164,6 @@
device_supported: false,
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
- + art_runtime_fake_native_shared_libs
+ art_runtime_debug_native_shared_libs,
multilib: {
both: {
@@ -186,8 +172,7 @@
binaries: art_runtime_base_binaries_both,
},
first: {
- // TODO: oatdump cannot link with host linux_bionic due to not using clang ld
- binaries: art_tools_common_binaries
+ binaries: art_tools_host_binaries
+ art_runtime_base_binaries_prefer32
+ art_runtime_debug_binaries_prefer32,
}
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
index 014b115..9e49d76 100644
--- a/build/apex/ld.config.txt
+++ b/build/apex/ld.config.txt
@@ -24,8 +24,7 @@
namespace.platform.isolated = true
namespace.platform.search.paths = /system/${LIB}
namespace.platform.links = default
-namespace.platform.link.default.shared_libs = libc.so:libdl.so:libm.so
-namespace.platform.link.default.shared_libs += libart.so:libartd.so
+namespace.platform.link.default.shared_libs = libart.so:libartd.so
namespace.platform.link.default.shared_libs += libnativebridge.so
namespace.platform.link.default.shared_libs += libnativehelper.so
namespace.platform.link.default.shared_libs += libnativeloader.so
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index b5e8d8b..9db325a 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -146,18 +146,19 @@
# TODO: Check for it when it is also built for host.
: check_binary oatdump
- # Check that the mounted image contains ART libraries.
+ # Check that the mounted image contains Android Runtime libraries.
check_library libart-compiler.so
+ check_library libart-dexlayout.so
check_library libart.so
+ check_library libartbase.so
+ check_library libdexfile.so
check_library libopenjdkjvm.so
check_library libopenjdkjvmti.so
- check_library libadbconnection.so
- # TODO: Should we check for these libraries too, even if they are not explicitly
- # listed as dependencies in the Android Runtime APEX module rule?
- check_library libartbase.so
- check_library libart-dexlayout.so
- check_library libdexfile.so
check_library libprofile.so
+ # Check that the mounted image contains Android Core libraries.
+ check_library libjavacrypto.so
+ # Check that the mounted image contains additional required libraries.
+ check_library libadbconnection.so
# TODO: Should we check for other libraries, such as:
#
@@ -186,19 +187,18 @@
check_binary dexoptanalyzerd
check_binary profmand
- # Check that the mounted image contains ART debug libraries.
+ # Check that the mounted image contains Android Runtime debug libraries.
+ check_library libartbased.so
check_library libartd-compiler.so
+ check_library libartd-dexlayout.so
check_library libartd.so
+ check_library libdexfiled.so
check_library libopenjdkd.so
check_library libopenjdkjvmd.so
check_library libopenjdkjvmtid.so
- check_library libadbconnectiond.so
- # TODO: Should we check for these libraries too, even if they are not explicitly
- # listed as dependencies in the Android Runtime APEX module rule?
- check_library libdexfiled.so
- check_library libartbased.so
- check_library libartd-dexlayout.so
check_library libprofiled.so
+ # Check that the mounted image contains additional required libraries.
+ check_library libadbconnectiond.so
}
# Testing target (device) APEX packages.
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 8b4bab7..42a4603 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "base/macros.h"
#include "handle_scope-inl.h"
#include "utils/arm/managed_register_arm.h"
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 4e6221e..4a6a754 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "handle_scope-inl.h"
#include "utils/arm64/managed_register_arm64.h"
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index ff814c8..f031b9b 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -18,6 +18,8 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
+
#ifdef ART_ENABLE_CODEGEN_arm
#include "jni/quick/arm/calling_convention_arm.h"
#endif
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index e256ce6..77a5d59 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -27,6 +27,8 @@
namespace art {
+enum class InstructionSet;
+
// Top-level abstraction for different calling conventions.
class CallingConvention : public DeletableArenaObject<kArenaAllocCallingConvention> {
public:
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
index d3d489e..c69854d 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ b/compiler/jni/quick/mips/calling_convention_mips.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "handle_scope-inl.h"
#include "utils/mips/managed_register_mips.h"
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.cc b/compiler/jni/quick/mips64/calling_convention_mips64.cc
index 3c7cee6..2c297b3 100644
--- a/compiler/jni/quick/mips64/calling_convention_mips64.cc
+++ b/compiler/jni/quick/mips64/calling_convention_mips64.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "handle_scope-inl.h"
#include "utils/mips64/managed_register_mips64.h"
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 71e6019..1f255e2 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "handle_scope-inl.h"
#include "utils/x86/managed_register_x86.h"
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index e5e96d0..9e77d6b 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/instruction_set.h"
#include "base/bit_utils.h"
#include "handle_scope-inl.h"
#include "utils/x86_64/managed_register_x86_64.h"
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index 3672cce..a5f78ca 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -315,8 +315,16 @@
CatchHandlerIterator iterator(handlers_ptr);
for (; iterator.HasNext(); iterator.Next()) {
uint32_t address = iterator.GetHandlerAddress();
- if (catch_blocks.find(address) != catch_blocks.end()) {
+ auto existing = catch_blocks.find(address);
+ if (existing != catch_blocks.end()) {
// Catch block already processed.
+ TryCatchInformation* info = existing->second->GetTryCatchInformation();
+ if (iterator.GetHandlerTypeIndex() != info->GetCatchTypeIndex()) {
+ // The handler is for multiple types. We could record all the types, but
+ // doing class resolution here isn't ideal, and it's unclear whether wasting
+ // the space in TryCatchInformation is worth it.
+ info->SetInvalidTypeIndex();
+ }
continue;
}
@@ -337,7 +345,7 @@
catch_blocks.Put(address, catch_block);
catch_block->SetTryCatchInformation(
- new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
+ new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
}
handlers_ptr = iterator.EndDataPointer();
}
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index ae1650e..ca790f6 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -3086,10 +3086,10 @@
void IntrinsicCodeGeneratorARM64::VisitCRC32UpdateBytes(HInvoke* invoke) {
DCHECK(codegen_->GetInstructionSetFeatures().HasCRC());
- auto masm = GetVIXLAssembler();
- auto locations = invoke->GetLocations();
+ MacroAssembler* masm = GetVIXLAssembler();
+ LocationSummary* locations = invoke->GetLocations();
- auto slow_path =
+ SlowPathCodeARM64* slow_path =
new (codegen_->GetScopedAllocator()) IntrinsicSlowPathARM64(invoke);
codegen_->AddSlowPath(slow_path);
@@ -3101,7 +3101,7 @@
mirror::Array::DataOffset(Primitive::kPrimByte).Uint32Value();
Register ptr = XRegisterFrom(locations->GetTemp(0));
Register array = XRegisterFrom(locations->InAt(1));
- auto offset = locations->InAt(2);
+ Location offset = locations->InAt(2);
if (offset.IsConstant()) {
int32_t offset_value = offset.GetConstant()->AsIntConstant()->GetValue();
__ Add(ptr, array, array_data_offset + offset_value);
@@ -3148,8 +3148,8 @@
void IntrinsicCodeGeneratorARM64::VisitCRC32UpdateByteBuffer(HInvoke* invoke) {
DCHECK(codegen_->GetInstructionSetFeatures().HasCRC());
- auto masm = GetVIXLAssembler();
- auto locations = invoke->GetLocations();
+ MacroAssembler* masm = GetVIXLAssembler();
+ LocationSummary* locations = invoke->GetLocations();
Register addr = XRegisterFrom(locations->InAt(1));
Register ptr = XRegisterFrom(locations->GetTemp(0));
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 686a2de..48fb611 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -895,7 +895,7 @@
explicit TryCatchInformation(const HTryBoundary& try_entry)
: try_entry_(&try_entry),
catch_dex_file_(nullptr),
- catch_type_index_(DexFile::kDexNoIndex16) {
+ catch_type_index_(dex::TypeIndex::Invalid()) {
DCHECK(try_entry_ != nullptr);
}
@@ -914,9 +914,9 @@
bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
- bool IsCatchAllTypeIndex() const {
+ bool IsValidTypeIndex() const {
DCHECK(IsCatchBlock());
- return !catch_type_index_.IsValid();
+ return catch_type_index_.IsValid();
}
dex::TypeIndex GetCatchTypeIndex() const {
@@ -929,6 +929,10 @@
return *catch_dex_file_;
}
+ void SetInvalidTypeIndex() {
+ catch_type_index_ = dex::TypeIndex::Invalid();
+ }
+
private:
// One of possibly several TryBoundary instructions entering the block's try.
// Only set for try blocks.
@@ -936,7 +940,7 @@
// Exception type information. Only set for catch blocks.
const DexFile* catch_dex_file_;
- const dex::TypeIndex catch_type_index_;
+ dex::TypeIndex catch_type_index_;
};
static constexpr size_t kNoLifetime = -1;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 61e7a60..4929e0a 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -699,14 +699,14 @@
DCHECK(instr->GetBlock()->IsCatchBlock());
TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation();
- if (catch_info->IsCatchAllTypeIndex()) {
- instr->SetReferenceTypeInfo(
- ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false));
- } else {
+ if (catch_info->IsValidTypeIndex()) {
UpdateReferenceTypeInfo(instr,
catch_info->GetCatchTypeIndex(),
catch_info->GetCatchDexFile(),
/* is_exact= */ false);
+ } else {
+ instr->SetReferenceTypeInfo(
+ ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false));
}
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index fd454f0..524bce0 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1011,6 +1011,10 @@
}
TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
+ // This test is frequently interrupted by timeout_dumper on host (x86);
+ // disable it while we investigate (b/121352534).
+ TEST_DISABLED_FOR_X86();
+
// The watchdog is independent of dex2oat and will not delete intermediates. It is possible
// that the compilation succeeds and the file is completely written by the time the watchdog
// kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 1331fc3..15ced72 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -49,6 +49,7 @@
#include "gc/heap-visit-objects-inl.h"
#include "gc/heap.h"
#include "gc/space/large_object_space.h"
+#include "gc/space/region_space.h"
#include "gc/space/space-inl.h"
#include "gc/verification.h"
#include "handle_scope-inl.h"
@@ -2423,10 +2424,33 @@
}
// Calculate bin slot offsets.
- for (ImageInfo& image_info : image_infos_) {
+ for (size_t oat_index = 0; oat_index < image_infos_.size(); ++oat_index) {
+ ImageInfo& image_info = image_infos_[oat_index];
size_t bin_offset = image_objects_offset_begin_;
+ // Need to visit the objects in bin order since alignment requirements might change the
+ // section sizes.
+ // Avoid using ObjPtr since VisitObjects invalidates. This is safe since concurrent GC can not
+ // occur during image writing.
+ using BinPair = std::pair<BinSlot, mirror::Object*>;
+ std::vector<BinPair> objects;
+ heap->VisitObjects([&](mirror::Object* obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Only visit the oat index for the current image.
+ if (IsImageObject(obj) && GetOatIndex(obj) == oat_index) {
+ objects.emplace_back(GetImageBinSlot(obj), obj);
+ }
+ });
+ std::sort(objects.begin(), objects.end(), [](const BinPair& a, const BinPair& b) -> bool {
+ if (a.first.GetBin() != b.first.GetBin()) {
+ return a.first.GetBin() < b.first.GetBin();
+ }
+ // Note that the index is really the relative offset in this case.
+ return a.first.GetIndex() < b.first.GetIndex();
+ });
+ auto it = objects.begin();
for (size_t i = 0; i != kNumberOfBins; ++i) {
- switch (static_cast<Bin>(i)) {
+ Bin bin = enum_cast<Bin>(i);
+ switch (bin) {
case Bin::kArtMethodClean:
case Bin::kArtMethodDirty: {
bin_offset = RoundUp(bin_offset, method_alignment);
@@ -2445,13 +2469,49 @@
}
}
image_info.bin_slot_offsets_[i] = bin_offset;
- bin_offset += image_info.bin_slot_sizes_[i];
+
+ // If the bin is for mirror objects, assign the offsets since we may need to change sizes
+ // from alignment requirements.
+ if (i < static_cast<size_t>(Bin::kMirrorCount)) {
+ const size_t start_offset = bin_offset;
+ // Visit and assign offsets for all objects of the bin type.
+ while (it != objects.end() && it->first.GetBin() == bin) {
+ ObjPtr<mirror::Object> obj(it->second);
+ const size_t object_size = RoundUp(obj->SizeOf(), kObjectAlignment);
+ // If the object spans region bondaries, add padding objects between.
+ // TODO: Instead of adding padding, we should consider reordering the bins to reduce
+ // wasted space.
+ if (region_size_ != 0u) {
+ const size_t offset_after_header = bin_offset - sizeof(ImageHeader);
+ const size_t next_region = RoundUp(offset_after_header, region_size_);
+ if (offset_after_header != next_region &&
+ offset_after_header + object_size > next_region) {
+ // Add padding objects until aligned.
+ while (bin_offset - sizeof(ImageHeader) < next_region) {
+ image_info.padding_object_offsets_.push_back(bin_offset);
+ bin_offset += kObjectAlignment;
+ region_alignment_wasted_ += kObjectAlignment;
+ image_info.image_end_ += kObjectAlignment;
+ }
+ CHECK_EQ(bin_offset - sizeof(ImageHeader), next_region);
+ }
+ }
+ SetImageOffset(obj.Ptr(), bin_offset);
+ bin_offset = bin_offset + object_size;
+ ++it;
+ }
+ image_info.bin_slot_sizes_[i] = bin_offset - start_offset;
+ } else {
+ bin_offset += image_info.bin_slot_sizes_[i];
+ }
}
// NOTE: There may be additional padding between the bin slots and the intern table.
DCHECK_EQ(image_info.image_end_,
image_info.GetBinSizeSum(Bin::kMirrorCount) + image_objects_offset_begin_);
}
+ VLOG(image) << "Space wasted for region alignment " << region_alignment_wasted_;
+
// Calculate image offsets.
size_t image_offset = 0;
for (ImageInfo& image_info : image_infos_) {
@@ -2462,17 +2522,6 @@
image_offset += image_info.image_size_;
}
- // Transform each object's bin slot into an offset which will be used to do the final copy.
- {
- auto unbin_objects_into_offset = [&](mirror::Object* obj)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (IsImageObject(obj)) {
- UnbinObjectsIntoOffset(obj);
- }
- };
- heap->VisitObjects(unbin_objects_into_offset);
- }
-
size_t i = 0;
for (ImageInfo& image_info : image_infos_) {
image_info.image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots[i].Get()));
@@ -2887,16 +2936,6 @@
}
}
-void ImageWriter::CopyAndFixupObjects() {
- auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(obj != nullptr);
- CopyAndFixupObject(obj);
- };
- Runtime::Current()->GetHeap()->VisitObjects(visitor);
- // We no longer need the hashcode map, values have already been copied to target objects.
- saved_hashcode_map_.clear();
-}
-
void ImageWriter::FixupPointerArray(mirror::Object* dst,
mirror::PointerArray* arr,
Bin array_type) {
@@ -2944,6 +2983,18 @@
image_info.image_bitmap_->Set(dst); // Mark the obj as live.
const size_t n = obj->SizeOf();
+
+ if (kIsDebugBuild && region_size_ != 0u) {
+ const size_t offset_after_header = offset - sizeof(ImageHeader);
+ const size_t next_region = RoundUp(offset_after_header, region_size_);
+ if (offset_after_header != next_region) {
+ // If the object is not on a region bondary, it must not be cross region.
+ CHECK_LT(offset_after_header, next_region)
+ << "offset_after_header=" << offset_after_header << " size=" << n;
+ CHECK_LE(offset_after_header + n, next_region)
+ << "offset_after_header=" << offset_after_header << " size=" << n;
+ }
+ }
DCHECK_LE(offset + n, image_info.image_.Size());
memcpy(dst, src, n);
@@ -2973,7 +3024,6 @@
const {}
void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
-
void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
ObjPtr<Object> ref = obj->GetFieldObject<Object, kVerifyNone>(offset);
@@ -2994,6 +3044,25 @@
mirror::Object* const copy_;
};
+void ImageWriter::CopyAndFixupObjects() {
+ auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(obj != nullptr);
+ CopyAndFixupObject(obj);
+ };
+ Runtime::Current()->GetHeap()->VisitObjects(visitor);
+ // Copy the padding objects since they are required for in order traversal of the image space.
+ for (const ImageInfo& image_info : image_infos_) {
+ for (const size_t offset : image_info.padding_object_offsets_) {
+ auto* dst = reinterpret_cast<Object*>(image_info.image_.Begin() + offset);
+ dst->SetClass<kVerifyNone>(GetImageAddress(GetClassRoot<mirror::Object>().Ptr()));
+ dst->SetLockWord<kVerifyNone>(LockWord::Default(), /*as_volatile=*/ false);
+ image_info.image_bitmap_->Set(dst); // Mark the obj as live.
+ }
+ }
+ // We no longer need the hashcode map, values have already been copied to target objects.
+ saved_hashcode_map_.clear();
+}
+
class ImageWriter::FixupClassVisitor final : public FixupVisitor {
public:
FixupClassVisitor(ImageWriter* image_writer, Object* copy)
@@ -3572,6 +3641,10 @@
CHECK_EQ(compiler_options.IsBootImage(),
Runtime::Current()->GetHeap()->GetBootImageSpaces().empty())
<< "Compiling a boot image should occur iff there are no boot image spaces loaded";
+ if (compiler_options_.IsAppImage()) {
+ // Make sure objects are not crossing region boundaries for app images.
+ region_size_ = gc::space::RegionSpace::kRegionSize;
+ }
}
ImageWriter::ImageInfo::ImageInfo()
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index b680265..8896e07 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -279,7 +279,7 @@
private:
// Must be the same size as LockWord, any larger and we would truncate the data.
- const uint32_t lockword_;
+ uint32_t lockword_;
};
struct ImageInfo {
@@ -397,6 +397,9 @@
// Class table associated with this image for serialization.
std::unique_ptr<ClassTable> class_table_;
+
+ // Padding objects to ensure region alignment (if required).
+ std::vector<size_t> padding_object_offsets_;
};
// We use the lock word to store the offset of the object in the image.
@@ -798,6 +801,12 @@
// Set of objects known to be dirty in the image. Can be nullptr if there are none.
const HashSet<std::string>* dirty_image_objects_;
+ // Objects are guaranteed to not cross the region size boundary.
+ size_t region_size_ = 0u;
+
+ // Region alignment bytes wasted.
+ size_t region_alignment_wasted_ = 0u;
+
class ImageFileGuard;
class FixupClassVisitor;
class FixupRootVisitor;
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index cc0e83a..48215bb 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <cstddef>
+#include <list>
#include <memory>
#include <vector>
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 24ee5f8..e914738 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -26,9 +26,33 @@
"dex_writer.cc",
],
export_include_dirs: ["."],
- shared_libs: [
- "libbase",
- ],
+ target: {
+ android: {
+ shared_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ not_windows: {
+ shared_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ windows: {
+ cflags: ["-Wno-thread-safety"],
+ static_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ },
static_libs: ["libz"],
}
@@ -46,18 +70,18 @@
"libart-dexlayout-defaults",
"dex2oat-pgo-defaults",
],
- shared_libs: [
- "libdexfile",
- "libartbase",
- "libprofile",
- ],
-
target: {
android: {
lto: {
thin: true,
},
},
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
},
}
@@ -118,6 +142,29 @@
}
art_cc_binary {
+ name: "dexlayouts",
+ defaults: [
+ "dexlayout-defaults",
+ "libart-dexlayout_static_defaults",
+ "libprofile_static_defaults",
+ "libdexfile_static_defaults",
+ "libartbase_static_defaults",
+ ],
+ srcs: ["dexlayout_main.cc"],
+ host_supported: true,
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ cflags: ["-Wno-thread-safety"],
+ },
+ },
+}
+
+art_cc_binary {
name: "dexlayoutd",
defaults: [
"art_debug_defaults",
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 32122eb..ef2c9e4 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -24,7 +24,6 @@
#include <inttypes.h>
#include <stdio.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <iostream>
#include <memory>
@@ -36,6 +35,7 @@
#include "base/logging.h" // For VLOG_IS_ON.
#include "base/hiddenapi_flags.h"
#include "base/mem_map.h"
+#include "base/mman.h" // For the PROT_* and MAP_* constants.
#include "base/os.h"
#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index 41b60da..2163f89 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -190,7 +190,12 @@
// Open profile file.
std::unique_ptr<ProfileCompilationInfo> profile_info;
if (options.profile_file_name_) {
- int profile_fd = open(options.profile_file_name_, O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
+ int flags = O_RDONLY | O_CLOEXEC;
+#endif
+ int profile_fd = open(options.profile_file_name_, flags);
if (profile_fd < 0) {
PLOG(ERROR) << "Can't open " << options.profile_file_name_;
return 1;
@@ -201,6 +206,7 @@
return 1;
}
}
+ PLOG(INFO) << "After opening profile file";
// Create DexLayout instance.
DexLayout dex_layout(options, profile_info.get(), out_file, /*header=*/ nullptr);
diff --git a/dexlist/Android.bp b/dexlist/Android.bp
index 217a024..356791c 100644
--- a/dexlist/Android.bp
+++ b/dexlist/Android.bp
@@ -24,6 +24,26 @@
],
}
+art_cc_binary {
+ name: "dexlists",
+ defaults: [
+ "art_defaults",
+ "libartbase_static_defaults",
+ "libdexfile_static_defaults",
+ ],
+ host_supported: true,
+ srcs: ["dexlist.cc"],
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
art_cc_test {
name: "art_dexlist_tests",
defaults: [
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index acf0f94..92850f7 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -202,11 +202,7 @@
Usage("Invalid --zip-fd %d", zip_fd_);
}
} else if (option.starts_with("--class-loader-context=")) {
- std::string context_str = option.substr(strlen("--class-loader-context=")).ToString();
- class_loader_context_ = ClassLoaderContext::Create(context_str);
- if (class_loader_context_ == nullptr) {
- Usage("Invalid --class-loader-context '%s'", context_str.c_str());
- }
+ context_str_ = option.substr(strlen("--class-loader-context=")).ToString();
} else {
Usage("Unknown argument '%s'", option.data());
}
@@ -264,6 +260,17 @@
}
std::unique_ptr<Runtime> runtime(Runtime::Current());
+ // Only when the runtime is created can we create the class loader context: the
+ // class loader context will open dex file and use the MemMap global lock that the
+ // runtime owns.
+ std::unique_ptr<ClassLoaderContext> class_loader_context;
+ if (!context_str_.empty()) {
+ class_loader_context = ClassLoaderContext::Create(context_str_);
+ if (class_loader_context == nullptr) {
+ Usage("Invalid --class-loader-context '%s'", context_str_.c_str());
+ }
+ }
+
std::unique_ptr<OatFileAssistant> oat_file_assistant;
oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(),
isa_,
@@ -279,7 +286,7 @@
}
int dexoptNeeded = oat_file_assistant->GetDexOptNeeded(
- compiler_filter_, assume_profile_changed_, downgrade_, class_loader_context_.get());
+ compiler_filter_, assume_profile_changed_, downgrade_, class_loader_context.get());
// Convert OatFileAssitant codes to dexoptanalyzer codes.
switch (dexoptNeeded) {
@@ -300,7 +307,7 @@
std::string dex_file_;
InstructionSet isa_;
CompilerFilter::Filter compiler_filter_;
- std::unique_ptr<ClassLoaderContext> class_loader_context_;
+ std::string context_str_;
bool assume_profile_changed_;
bool downgrade_;
std::string image_;
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index f6fd1fb..7b6b36c 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -36,7 +36,8 @@
int Analyze(const std::string& dex_file,
CompilerFilter::Filter compiler_filter,
- bool assume_profile_changed) {
+ bool assume_profile_changed,
+ const std::string& class_loader_context) {
std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
std::vector<std::string> argv_str;
argv_str.push_back(dexoptanalyzer_cmd);
@@ -52,6 +53,9 @@
argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
argv_str.push_back("--image=" + GetImageLocation());
argv_str.push_back("--android-data=" + android_data_);
+ if (!class_loader_context.empty()) {
+ argv_str.push_back("--class-loader-context=" + class_loader_context);
+ }
std::string error;
return ExecAndReturnCode(argv_str, &error);
@@ -74,8 +78,10 @@
void Verify(const std::string& dex_file,
CompilerFilter::Filter compiler_filter,
bool assume_profile_changed = false,
- bool downgrade = false) {
- int dexoptanalyzerResult = Analyze(dex_file, compiler_filter, assume_profile_changed);
+ bool downgrade = false,
+ const std::string& class_loader_context = "") {
+ int dexoptanalyzerResult = Analyze(
+ dex_file, compiler_filter, assume_profile_changed, class_loader_context);
dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable=*/ false);
int assistantResult = oat_file_assistant.GetDexOptNeeded(
@@ -305,4 +311,22 @@
Verify(dex_location, CompilerFilter::kSpeed);
}
+// Case: We have a DEX file and up-to-date OAT file for it, and we check with
+// a class loader context.
+TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
+ std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
+ std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
+ std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
+ Copy(GetDexSrc1(), dex_location1);
+ Copy(GetDexSrc2(), dex_location2);
+
+ std::string class_loader_context = "PCL[" + dex_location2 + "]";
+ std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";
+
+ // Generate the odex to get the class loader context also open the dex files.
+ GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
+
+ Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context);
+}
+
} // namespace art
diff --git a/libart_fake/Android.mk b/libart_fake/Android.mk
deleted file mode 100644
index 96e6a14..0000000
--- a/libart_fake/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libart_fake
-LOCAL_INSTALLED_MODULE_STEM := libart.so
-LOCAL_SDK_VERSION := 9
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := fake.cc
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_SHARED_LIBRARIES := liblog
-
-ifdef TARGET_2ND_ARCH
- LOCAL_MODULE_PATH_32 := $(TARGET_OUT)/fake-libs
- LOCAL_MODULE_PATH_64 := $(TARGET_OUT)/fake-libs64
-else
- LOCAL_MODULE_PATH := $(TARGET_OUT)/fake-libs
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libart_fake/README.md b/libart_fake/README.md
deleted file mode 100644
index 6e3621e..0000000
--- a/libart_fake/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-libart_fake
-====
-
-A fake libart made to satisfy some misbehaving apps that will attempt to link
-against libart.so.
diff --git a/libart_fake/fake.cc b/libart_fake/fake.cc
deleted file mode 100644
index 8842421..0000000
--- a/libart_fake/fake.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libart_fake"
-
-#include <android/log.h>
-
-#define LOGIT(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-namespace art {
-class Dbg {
- public:
- void SuspendVM();
- void ResumeVM();
-};
-
-class FaultManager {
- public:
- void EnsureArtActionInFrontOfSignalChain();
-};
-
-void Dbg::SuspendVM() {
- LOGIT("Linking to and calling into libart.so internal functions is not supported. "
- "This call to '%s' is being ignored.", __func__);
-}
-void Dbg::ResumeVM() {
- LOGIT("Linking to and calling into libart.so internal functions is not supported. "
- "This call to '%s' is being ignored.", __func__);
-}
-void FaultManager::EnsureArtActionInFrontOfSignalChain() {
- LOGIT("Linking to and calling into libart.so internal functions is not supported. "
- "This call to '%s' is being ignored.", __func__);
-}
-}; // namespace art
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 0fcd6a5..509b072 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -24,6 +24,7 @@
"base/arena_allocator.cc",
"base/arena_bit_vector.cc",
"base/bit_vector.cc",
+ "base/enums.cc",
"base/file_magic.cc",
"base/file_utils.cc",
"base/hex_dump.cc",
@@ -64,6 +65,7 @@
// For common macros.
"libbase",
],
+ export_shared_lib_headers: ["libbase"],
// Exclude the version script from Darwin host since it's not
// supported by the linker there. That means ASan checks on Darwin
// might trigger ODR violations.
@@ -82,12 +84,16 @@
// For common macros.
"libbase",
],
+ export_shared_lib_headers: ["libbase"],
},
linux_glibc: {
version_script: "libartbase.map",
},
windows: {
version_script: "libartbase.map",
+ srcs: [
+ "base/mem_map_windows.cc",
+ ],
static_libs: [
"libziparchive",
"libz",
@@ -97,6 +103,7 @@
// For common macros.
"libbase",
],
+ export_static_lib_headers: ["libbase"],
cflags: ["-Wno-thread-safety"],
},
},
@@ -115,7 +122,6 @@
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: ["libbase"],
}
cc_defaults {
@@ -148,7 +154,6 @@
srcs: [
"arch/instruction_set.h",
"base/allocator.h",
- "base/callee_save_type.h",
"base/unix_file/fd_file.h",
],
output_extension: "operator_out.cc",
diff --git a/libartbase/base/enums.cc b/libartbase/base/enums.cc
new file mode 100644
index 0000000..3f28232
--- /dev/null
+++ b/libartbase/base/enums.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "enums.h"
+
+#include <ostream>
+
+namespace art {
+
+std::ostream& operator<<(std::ostream& os, const PointerSize& rhs) {
+ switch (rhs) {
+ case PointerSize::k32: os << "k32"; break;
+ case PointerSize::k64: os << "k64"; break;
+ default: os << "PointerSize[" << static_cast<int>(rhs) << "]"; break;
+ }
+ return os;
+}
+
+} // namespace art
diff --git a/libartbase/base/enums.h b/libartbase/base/enums.h
index ad5578f..c5fb880 100644
--- a/libartbase/base/enums.h
+++ b/libartbase/base/enums.h
@@ -18,7 +18,7 @@
#define ART_LIBARTBASE_BASE_ENUMS_H_
#include <cstddef>
-#include <ostream>
+#include <iosfwd>
namespace art {
@@ -27,14 +27,7 @@
k64 = 8
};
-inline std::ostream& operator<<(std::ostream& os, const PointerSize& rhs) {
- switch (rhs) {
- case PointerSize::k32: os << "k32"; break;
- case PointerSize::k64: os << "k64"; break;
- default: os << "PointerSize[" << static_cast<int>(rhs) << "]"; break;
- }
- return os;
-}
+std::ostream& operator<<(std::ostream& os, const PointerSize& rhs);
static constexpr PointerSize kRuntimePointerSize = sizeof(void*) == 8U
? PointerSize::k64
diff --git a/libartbase/base/globals.h b/libartbase/base/globals.h
index 2a2a737..97eae63 100644
--- a/libartbase/base/globals.h
+++ b/libartbase/base/globals.h
@@ -38,20 +38,6 @@
// compile-time constant so the compiler can generate better code.
static constexpr int kPageSize = 4096;
-// Size of Dex virtual registers.
-static constexpr size_t kVRegSize = 4;
-
-// Returns whether the given memory offset can be used for generating
-// an implicit null check.
-static inline bool CanDoImplicitNullCheckOn(uintptr_t offset) {
- return offset < kPageSize;
-}
-
-// Required object alignment
-static constexpr size_t kObjectAlignmentShift = 3;
-static constexpr size_t kObjectAlignment = 1u << kObjectAlignmentShift;
-static constexpr size_t kLargeObjectAlignment = kPageSize;
-
// Clion, clang analyzer, etc can falsely believe that "if (kIsDebugBuild)" always
// returns the same value. By wrapping into a call to another constexpr function, we force it
// to realize that is not actually always evaluating to the same value.
@@ -117,48 +103,6 @@
static constexpr bool kHostStaticBuildEnabled = false;
#endif
-// Garbage collector constants.
-static constexpr bool kMovingCollector = true;
-static constexpr bool kMarkCompactSupport = false && kMovingCollector;
-// True if we allow moving classes.
-static constexpr bool kMovingClasses = !kMarkCompactSupport;
-// If true, enable generational collection when using the Concurrent Copying
-// (CC) collector, i.e. use sticky-bit CC for minor collections and (full) CC
-// for major collections.
-//
-// Generational CC collection is currently only compatible with Baker read
-// barriers.
-#if defined(ART_USE_GENERATIONAL_CC) && defined(ART_READ_BARRIER_TYPE_IS_BAKER)
-static constexpr bool kEnableGenerationalConcurrentCopyingCollection = true;
-#else
-static constexpr bool kEnableGenerationalConcurrentCopyingCollection = false;
-#endif
-
-// If true, enable the tlab allocator by default.
-#ifdef ART_USE_TLAB
-static constexpr bool kUseTlab = true;
-#else
-static constexpr bool kUseTlab = false;
-#endif
-
-// Kinds of tracing clocks.
-enum class TraceClockSource {
- kThreadCpu,
- kWall,
- kDual, // Both wall and thread CPU clocks.
-};
-
-#if defined(__linux__)
-static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kDual;
-#else
-static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kWall;
-#endif
-
-static constexpr bool kDefaultMustRelocate = true;
-
-// Size of a heap reference.
-static constexpr size_t kHeapReferenceSize = sizeof(uint32_t);
-
} // namespace art
#endif // ART_LIBARTBASE_BASE_GLOBALS_H_
diff --git a/libartbase/base/logging.h b/libartbase/base/logging.h
index 9ded082..484db87 100644
--- a/libartbase/base/logging.h
+++ b/libartbase/base/logging.h
@@ -17,9 +17,6 @@
#ifndef ART_LIBARTBASE_BASE_LOGGING_H_
#define ART_LIBARTBASE_BASE_LOGGING_H_
-#include <ostream>
-#include <sstream>
-
#include "android-base/logging.h"
#include "macros.h"
diff --git a/libartbase/base/mem_map_windows.cc b/libartbase/base/mem_map_windows.cc
new file mode 100644
index 0000000..84e14ea
--- /dev/null
+++ b/libartbase/base/mem_map_windows.cc
@@ -0,0 +1,140 @@
+/*
+ * 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 "mem_map.h"
+
+#include <windows.h>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "android-base/mapped_file.h"
+#ifdef PROT_READ
+#undef PROT_READ
+#endif
+#ifdef PROT_WRITE
+#undef PROT_WRITE
+#endif
+#include "mman.h"
+
+namespace art {
+
+using android::base::MappedFile;
+using android::base::StringPrintf;
+
+static off_t allocation_granularity;
+
+void MemMap::TargetMMapInit() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ allocation_granularity = si.dwAllocationGranularity;
+}
+
+void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
+ UNUSED(start);
+ size_t padding = fd_off % allocation_granularity;
+ off_t file_offset = fd_off - padding;
+ off_t map_length = len + padding;
+
+ // Only read and write permissions are supported.
+ if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
+ PLOG(ERROR) << "Protection or flag error was not supported.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ // Fixed is not currently supported either.
+ // TODO(sehr): add MAP_FIXED support.
+ if ((flags & MAP_FIXED) != 0) {
+ PLOG(ERROR) << "MAP_FIXED not supported.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
+ DWORD map_access = 0;
+ DWORD view_access = 0;
+ if ((prot & PROT_WRITE) != 0) {
+ map_access = PAGE_READWRITE;
+ if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
+ view_access = FILE_MAP_ALL_ACCESS;
+ } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
+ view_access = FILE_MAP_COPY | FILE_MAP_READ;
+ } else {
+ PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ } else {
+ map_access = PAGE_READONLY;
+ view_access = FILE_MAP_READ;
+ }
+
+ // MapViewOfFile does not like to see a size greater than the file size of the
+ // underlying file object, unless the underlying file object is writable. If
+ // the mapped region would go beyond the end of the underlying file, use zero,
+ // as this indicates the physical size.
+ HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ LARGE_INTEGER file_length;
+ if (!::GetFileSizeEx(file_handle, &file_length)) {
+ PLOG(ERROR) << "Couldn't get file size.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ if (((map_access & PAGE_READONLY) != 0) &&
+ file_offset + map_length > file_length.QuadPart) {
+ map_length = 0;
+ }
+
+ // Create a file mapping object that will be used to access the file.
+ HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
+ nullptr,
+ map_access,
+ 0,
+ 0,
+ nullptr);
+ if (handle == nullptr) {
+ DWORD error = ::GetLastError();
+ PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ // Map the file into the process address space.
+ DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
+#ifdef _WIN64
+ DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
+#else
+ DWORD offset_high = static_cast<DWORD>(0);
+#endif
+ void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
+ if (view_address == nullptr) {
+ DWORD error = ::GetLastError();
+ PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
+ ::CloseHandle(handle);
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ return view_address;
+}
+
+int MemMap::TargetMUnmap(void* start, size_t len) {
+ // TODO(sehr): implement unmap.
+ UNUSED(start);
+ UNUSED(len);
+ return 0;
+}
+
+} // namespace art
diff --git a/libartbase/base/mman.h b/libartbase/base/mman.h
index bd63f65..b56edfc 100644
--- a/libartbase/base/mman.h
+++ b/libartbase/base/mman.h
@@ -20,19 +20,18 @@
#ifdef _WIN32
// There is no sys/mman.h in mingw.
-// As these are just placeholders for the APIs, all values are stubbed out.
-#define PROT_READ 0 // 0x1
-#define PROT_WRITE 0 // 0x2
-#define PROT_EXEC 0 // 0x4
-#define PROT_NONE 0 // 0x0
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+#define PROT_NONE 0x0
-#define MAP_SHARED 0 // 0x01
-#define MAP_PRIVATE 0 // 0x02
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
-#define MAP_FAILED nullptr // ((void*) -1)
-#define MAP_FIXED 0 // 0x10
-#define MAP_ANONYMOUS 0 // 0x20
+#define MAP_FAILED ((void*) -1)
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
#else
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 9c48aa2..2f56a3d 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -176,6 +176,36 @@
},
}
+art_cc_test {
+ name: "art_libdexfile_tests",
+ defaults: [
+ "art_gtest_defaults",
+ ],
+ srcs: [
+ "dex/art_dex_file_loader_test.cc",
+ "dex/class_accessor_test.cc",
+ "dex/code_item_accessors_test.cc",
+ "dex/compact_dex_file_test.cc",
+ "dex/compact_offset_table_test.cc",
+ "dex/descriptors_names_test.cc",
+ "dex/test_dex_file_builder_test.cc",
+ "dex/dex_file_loader_test.cc",
+ "dex/dex_file_verifier_test.cc",
+ "dex/dex_instruction_test.cc",
+ "dex/primitive_test.cc",
+ "dex/string_reference_test.cc",
+ "dex/type_lookup_table_test.cc",
+ "dex/utf_test.cc",
+ ],
+ shared_libs: [
+ "libbacktrace",
+ "libziparchive",
+ ],
+ include_dirs: [
+ "external/zlib",
+ ],
+}
+
cc_library_headers {
name: "libdexfile_external_headers",
host_supported: true,
@@ -227,6 +257,16 @@
},
}
+art_cc_test {
+ name: "art_libdexfile_external_tests",
+ host_supported: true,
+ test_per_src: true, // For consistency with other ART gtests.
+ srcs: [
+ "external/dex_file_ext_c_test.c",
+ ],
+ header_libs: ["libdexfile_external_headers"],
+}
+
// Support library with a C++ API for accessing the libdexfile API for external
// (non-ART) users. They should link to their own instance of this (either
// statically or through linker namespaces).
@@ -242,31 +282,16 @@
}
art_cc_test {
- name: "art_libdexfile_tests",
- defaults: [
- "art_gtest_defaults",
- ],
+ name: "art_libdexfile_support_tests",
+ host_supported: true,
+ test_per_src: true, // For consistency with other ART gtests.
srcs: [
- "dex/art_dex_file_loader_test.cc",
- "dex/class_accessor_test.cc",
- "dex/code_item_accessors_test.cc",
- "dex/compact_dex_file_test.cc",
- "dex/compact_offset_table_test.cc",
- "dex/descriptors_names_test.cc",
- "dex/test_dex_file_builder_test.cc",
- "dex/dex_file_loader_test.cc",
- "dex/dex_file_verifier_test.cc",
- "dex/dex_instruction_test.cc",
- "dex/primitive_test.cc",
- "dex/string_reference_test.cc",
- "dex/type_lookup_table_test.cc",
- "dex/utf_test.cc",
+ "external/dex_file_supp_test.cc",
],
shared_libs: [
- "libbacktrace",
- "libziparchive",
- ],
- include_dirs: [
- "external/zlib",
+ "libartbase",
+ "libbase",
+ "libdexfile_external",
+ "libdexfile_support",
],
}
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 5c100e6..d3cdf13 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -23,6 +23,7 @@
#include <zlib.h>
#include <memory>
+#include <ostream>
#include <sstream>
#include <type_traits>
diff --git a/libdexfile/dex/dex_file_types.h b/libdexfile/dex/dex_file_types.h
index d4fb3de..ecc0482 100644
--- a/libdexfile/dex/dex_file_types.h
+++ b/libdexfile/dex/dex_file_types.h
@@ -17,8 +17,9 @@
#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
#define ART_LIBDEXFILE_DEX_DEX_FILE_TYPES_H_
+#include <iosfwd>
#include <limits>
-#include <ostream>
+#include <utility>
namespace art {
namespace dex {
diff --git a/libdexfile/external/dex_file_ext.cc b/libdexfile/external/dex_file_ext.cc
index 5c353b5..e1b7874 100644
--- a/libdexfile/external/dex_file_ext.cc
+++ b/libdexfile/external/dex_file_ext.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "art_api/dex_file_external.h"
+
#include <inttypes.h>
#include <stdint.h>
#include <sys/mman.h>
@@ -39,18 +41,9 @@
#include <dex/dex_file-inl.h>
#include <dex/dex_file_loader.h>
-#include "art_api/ext_dex_file.h"
-
-extern "C" class ExtDexFileString {
- public:
- const std::string str_;
-};
-
namespace art {
namespace {
-const ExtDexFileString empty_string{""};
-
struct MethodCacheEntry {
int32_t offset; // Offset relative to the start of the dex file header.
int32_t len;
@@ -77,11 +70,17 @@
extern "C" {
-const ExtDexFileString* ExtDexFileMakeString(const char* str) {
- if (str[0] == '\0') {
- return &art::empty_string;
+struct ExtDexFileString {
+ const std::string str_;
+};
+
+static const ExtDexFileString empty_string{""};
+
+const ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size) {
+ if (size == 0) {
+ return &empty_string;
}
- return new ExtDexFileString{str};
+ return new ExtDexFileString{std::string(str, size)};
}
const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size) {
@@ -92,14 +91,15 @@
void ExtDexFileFreeString(const ExtDexFileString* ext_string) {
DCHECK(ext_string != nullptr);
- if (ext_string != &art::empty_string) {
+ if (ext_string != &empty_string) {
delete (ext_string);
}
}
// Wraps DexFile to add the caching needed by the external interface. This is
// what gets passed over as ExtDexFile*.
-class ExtDexFile {
+struct ExtDexFile {
+ private:
// Method cache for GetMethodInfoForOffset. This is populated as we iterate
// sequentially through the class defs. MethodCacheEntry.name is only set for
// methods returned by GetMethodInfoForOffset.
@@ -226,7 +226,10 @@
if (length < offset + sizeof(art::DexFile::Header)) {
*ext_error_msg = new ExtDexFileString{android::base::StringPrintf(
- "Offset %" PRId64 " too large for '%s' of size %zu", int64_t{offset}, location, length)};
+ "Offset %" PRId64 " too large for '%s' of size %zu",
+ int64_t{offset},
+ location,
+ length)};
return false;
}
@@ -282,6 +285,7 @@
int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
int64_t dex_offset,
+ int with_signature,
/*out*/ ExtDexFileMethodInfo* method_info) {
if (!ext_dex_file->dex_file_->IsInDataSection(ext_dex_file->dex_file_->Begin() + dex_offset)) {
return false; // The DEX offset is not within the bytecode of this dex file.
@@ -304,7 +308,7 @@
method_info->offset = entry->offset;
method_info->len = entry->len;
method_info->name =
- new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, false)};
+ new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, with_signature)};
return true;
}
diff --git a/libdexfile/external/dex_file_ext_c_test.c b/libdexfile/external/dex_file_ext_c_test.c
new file mode 100644
index 0000000..c448a16
--- /dev/null
+++ b/libdexfile/external/dex_file_ext_c_test.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "art_api/dex_file_external.h"
+
+static const char gtest_output_arg[] = "--gtest_output=xml:";
+static const char gtest_output_xml[] = "\
+<?xml version=\"1.0\"?>\n\
+<testsuites tests=\"0\" failures=\"0\" disabled=\"0\" errors=\"0\" name=\"AllTests\">";
+
+/* Writes a dummy gtest xml report to the given path. */
+static int write_gtest_output_xml(char* gtest_output_path) {
+ FILE* output_fd = fopen(gtest_output_path, "w");
+ if (output_fd == NULL) {
+ fprintf(stderr, "Failed to open %s: %s\n", gtest_output_path, strerror(errno));
+ return 1;
+ }
+ if (fprintf(output_fd, gtest_output_xml) != sizeof(gtest_output_xml) - 1) {
+ fprintf(stderr, "Failed to write %s: %s\n", gtest_output_path, strerror(errno));
+ fclose(output_fd);
+ return 1;
+ }
+ if (fclose(output_fd) != 0) {
+ fprintf(stderr, "Failed to close %s: %s\n", gtest_output_path, strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ if (argc >= 2 && strncmp(argv[1], gtest_output_arg, sizeof(gtest_output_arg) - 1) == 0) {
+ /* The ART gtest framework expects all tests to understand --gtest_output. */
+ return write_gtest_output_xml(argv[1] + sizeof(gtest_output_arg) - 1);
+ }
+ return 0;
+}
diff --git a/libdexfile/external/dex_file_supp.cc b/libdexfile/external/dex_file_supp.cc
index 6514c8a..5bd25fc 100644
--- a/libdexfile/external/dex_file_supp.cc
+++ b/libdexfile/external/dex_file_supp.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "art_api/ext_dex_file.h"
+#include "art_api/dex_file_support.h"
namespace art_api {
namespace dex {
diff --git a/libdexfile/external/dex_file_supp_test.cc b/libdexfile/external/dex_file_supp_test.cc
new file mode 100644
index 0000000..2f7ad50
--- /dev/null
+++ b/libdexfile/external/dex_file_supp_test.cc
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 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 <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <string_view>
+
+#include <android-base/file.h>
+#include <dex/dex_file.h>
+#include <gtest/gtest.h>
+
+#include "art_api/dex_file_support.h"
+
+namespace art_api {
+namespace dex {
+
+static constexpr uint32_t kDexData[] = {
+ 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
+ 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
+ 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
+ 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
+ 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
+ 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
+ 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
+ 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
+ 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
+ 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
+ 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
+ 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
+ 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
+ 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
+ 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
+ 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
+ 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
+};
+
+TEST(DexStringTest, alloc_string) {
+ auto s = DexString("123");
+ EXPECT_EQ(std::string_view(s), "123");
+}
+
+TEST(DexStringTest, alloc_empty_string) {
+ auto s = DexString("");
+ EXPECT_TRUE(std::string_view(s).empty());
+}
+
+TEST(DexStringTest, move_construct) {
+ auto s1 = DexString("foo");
+ auto s2 = DexString(std::move(s1));
+ EXPECT_TRUE(std::string_view(s1).empty());
+ EXPECT_EQ(std::string_view(s2), "foo");
+}
+
+TEST(DexStringTest, move_assign) {
+ auto s1 = DexString("foo");
+ DexString s2;
+ EXPECT_TRUE(std::string_view(s2).empty());
+ s2 = std::move(s1);
+ EXPECT_TRUE(std::string_view(s1).empty());
+ EXPECT_EQ(std::string_view(s2), "foo");
+}
+
+TEST(DexStringTest, reassign) {
+ auto s = DexString("foo");
+ s = DexString("bar");
+ EXPECT_EQ(std::string_view(s), "bar");
+}
+
+TEST(DexStringTest, data_access) {
+ auto s = DexString("foo");
+ EXPECT_STREQ(s.data(), "foo");
+ EXPECT_STREQ(s.c_str(), "foo");
+}
+
+TEST(DexStringTest, size_access) {
+ auto s = DexString("foo");
+ EXPECT_EQ(s.size(), size_t{3});
+ EXPECT_EQ(s.length(), size_t{3});
+}
+
+TEST(DexStringTest, equality) {
+ auto s = DexString("foo");
+ EXPECT_EQ(s, DexString("foo"));
+ EXPECT_FALSE(s == DexString("bar"));
+}
+
+TEST(DexStringTest, equality_with_nul) {
+ auto s = DexString(std::string("foo\0bar", 7));
+ EXPECT_EQ(s.size(), size_t{7});
+ EXPECT_EQ(s, DexString(std::string("foo\0bar", 7)));
+ EXPECT_FALSE(s == DexString(std::string("foo\0baz", 7)));
+}
+
+TEST(DexFileTest, from_memory_header_too_small) {
+ size_t size = sizeof(art::DexFile::Header) - 1;
+ std::string error_msg;
+ EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+ EXPECT_EQ(size, sizeof(art::DexFile::Header));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_memory_file_too_small) {
+ size_t size = sizeof(art::DexFile::Header);
+ std::string error_msg;
+ EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+ EXPECT_EQ(size, sizeof(kDexData));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+static std::unique_ptr<DexFile> GetTestDexData() {
+ size_t size = sizeof(kDexData);
+ std::string error_msg;
+ std::unique_ptr<DexFile> dex_file = DexFile::OpenFromMemory(kDexData, &size, "", &error_msg);
+ EXPECT_TRUE(error_msg.empty());
+ return dex_file;
+}
+
+TEST(DexFileTest, from_memory) {
+ EXPECT_NE(GetTestDexData(), nullptr);
+}
+
+TEST(DexFileTest, from_fd_header_too_small) {
+ TemporaryFile tf;
+ ASSERT_NE(tf.fd, -1);
+ ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
+ static_cast<size_t>(
+ TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
+
+ std::string error_msg;
+ EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd_file_too_small) {
+ TemporaryFile tf;
+ ASSERT_NE(tf.fd, -1);
+ ASSERT_EQ(sizeof(art::DexFile::Header),
+ static_cast<size_t>(
+ TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)))));
+
+ std::string error_msg;
+ EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd) {
+ TemporaryFile tf;
+ ASSERT_NE(tf.fd, -1);
+ ASSERT_EQ(sizeof(kDexData),
+ static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
+
+ std::string error_msg;
+ EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, from_fd_non_zero_offset) {
+ TemporaryFile tf;
+ ASSERT_NE(tf.fd, -1);
+ ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
+ ASSERT_EQ(sizeof(kDexData),
+ static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
+
+ std::string error_msg;
+ EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0x100, tf.path, &error_msg), nullptr);
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(DexFileTest, get_method_info_for_offset_without_signature) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ EXPECT_EQ(info.len, int32_t{8});
+ EXPECT_STREQ(info.name.data(), "Main.<init>");
+
+ info = dex_file->GetMethodInfoForOffset(0x118, false);
+ EXPECT_EQ(info.offset, int32_t{0x118});
+ EXPECT_EQ(info.len, int32_t{2});
+ EXPECT_STREQ(info.name.data(), "Main.main");
+
+ // Retrieve a cached result.
+ info = dex_file->GetMethodInfoForOffset(0x104, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ EXPECT_EQ(info.len, int32_t{8});
+ EXPECT_STREQ(info.name.data(), "Main.<init>");
+}
+
+TEST(DexFileTest, get_method_info_for_offset_with_signature) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, true);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ EXPECT_EQ(info.len, int32_t{8});
+ EXPECT_STREQ(info.name.data(), "void Main.<init>()");
+
+ info = dex_file->GetMethodInfoForOffset(0x118, true);
+ EXPECT_EQ(info.offset, int32_t{0x118});
+ EXPECT_EQ(info.len, int32_t{2});
+ EXPECT_STREQ(info.name.data(), "void Main.main(java.lang.String[])");
+
+ // Retrieve a cached result.
+ info = dex_file->GetMethodInfoForOffset(0x104, true);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ EXPECT_EQ(info.len, int32_t{8});
+ EXPECT_STREQ(info.name.data(), "void Main.<init>()");
+
+ // with_signature doesn't affect the cache.
+ info = dex_file->GetMethodInfoForOffset(0x104, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ EXPECT_EQ(info.len, int32_t{8});
+ EXPECT_STREQ(info.name.data(), "Main.<init>");
+}
+
+TEST(DexFileTest, get_method_info_for_offset_boundaries) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ MethodInfo info = dex_file->GetMethodInfoForOffset(0x100000, false);
+ EXPECT_EQ(info.offset, int32_t{0});
+
+ info = dex_file->GetMethodInfoForOffset(0x99, false);
+ EXPECT_EQ(info.offset, int32_t{0});
+ info = dex_file->GetMethodInfoForOffset(0x100, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ info = dex_file->GetMethodInfoForOffset(0x107, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+ info = dex_file->GetMethodInfoForOffset(0x108, false);
+ EXPECT_EQ(info.offset, int32_t{0});
+
+ // Make sure that once the whole dex file has been cached, no problems occur.
+ info = dex_file->GetMethodInfoForOffset(0x98, false);
+ EXPECT_EQ(info.offset, int32_t{0});
+
+ // Choose a value that is in the cached map, but not in a valid method.
+ info = dex_file->GetMethodInfoForOffset(0x110, false);
+ EXPECT_EQ(info.offset, int32_t{0});
+}
+
+TEST(DexFileTest, get_all_method_infos_without_signature) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ std::vector<MethodInfo> infos;
+ infos.emplace_back(MethodInfo{0x100, 8, DexString("Main.<init>")});
+ infos.emplace_back(MethodInfo{0x118, 2, DexString("Main.main")});
+ ASSERT_EQ(dex_file->GetAllMethodInfos(false), infos);
+}
+
+TEST(DexFileTest, get_all_method_infos_with_signature) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ std::vector<MethodInfo> infos;
+ infos.emplace_back(MethodInfo{0x100, 8, DexString("void Main.<init>()")});
+ infos.emplace_back(MethodInfo{0x118, 2, DexString("void Main.main(java.lang.String[])")});
+ ASSERT_EQ(dex_file->GetAllMethodInfos(true), infos);
+}
+
+TEST(DexFileTest, move_construct) {
+ std::unique_ptr<DexFile> dex_file = GetTestDexData();
+ ASSERT_NE(dex_file, nullptr);
+
+ auto df1 = DexFile(std::move(*dex_file));
+ auto df2 = DexFile(std::move(df1));
+
+ MethodInfo info = df2.GetMethodInfoForOffset(0x100, false);
+ EXPECT_EQ(info.offset, int32_t{0x100});
+}
+
+} // namespace dex
+} // namespace art_api
diff --git a/libdexfile/external/include/art_api/dex_file_external.h b/libdexfile/external/include/art_api/dex_file_external.h
new file mode 100644
index 0000000..b29e759
--- /dev/null
+++ b/libdexfile/external/include/art_api/dex_file_external.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+
+// Dex file external API
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This is the stable C ABI that backs art_api::dex below. Structs and functions
+// may only be added here. C++ users should use dex_file_support.h instead.
+
+// Opaque wrapper for an std::string allocated in libdexfile which must be freed
+// using ExtDexFileFreeString.
+struct ExtDexFileString;
+
+// Returns an ExtDexFileString initialized to the given string.
+const struct ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size);
+
+// Returns a pointer to the underlying null-terminated character array and its
+// size for the given ExtDexFileString.
+const char* ExtDexFileGetString(const struct ExtDexFileString* ext_string, /*out*/ size_t* size);
+
+// Frees an ExtDexFileString.
+void ExtDexFileFreeString(const struct ExtDexFileString* ext_string);
+
+struct ExtDexFileMethodInfo {
+ int32_t offset;
+ int32_t len;
+ const struct ExtDexFileString* name;
+};
+
+struct ExtDexFile;
+
+// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
+int ExtDexFileOpenFromMemory(const void* addr,
+ /*inout*/ size_t* size,
+ const char* location,
+ /*out*/ const struct ExtDexFileString** error_msg,
+ /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
+int ExtDexFileOpenFromFd(int fd,
+ off_t offset,
+ const char* location,
+ /*out*/ const struct ExtDexFileString** error_msg,
+ /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
+int ExtDexFileGetMethodInfoForOffset(struct ExtDexFile* ext_dex_file,
+ int64_t dex_offset,
+ int with_signature,
+ /*out*/ struct ExtDexFileMethodInfo* method_info);
+
+typedef void ExtDexFileMethodInfoCallback(const struct ExtDexFileMethodInfo* ext_method_info,
+ void* user_data);
+
+// See art_api::dex::DexFile::GetAllMethodInfos.
+void ExtDexFileGetAllMethodInfos(struct ExtDexFile* ext_dex_file,
+ int with_signature,
+ ExtDexFileMethodInfoCallback* method_info_cb,
+ void* user_data);
+
+// Frees an ExtDexFile.
+void ExtDexFileFree(struct ExtDexFile* ext_dex_file);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
diff --git a/libdexfile/external/include/art_api/ext_dex_file.h b/libdexfile/external/include/art_api/dex_file_support.h
similarity index 62%
rename from libdexfile/external/include/art_api/ext_dex_file.h
rename to libdexfile/external/include/art_api/dex_file_support.h
index 4a52a2b..24222af 100644
--- a/libdexfile/external/include/art_api/ext_dex_file.h
+++ b/libdexfile/external/include/art_api/dex_file_support.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,83 +14,21 @@
* limitations under the License.
*/
-#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
-#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
+#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
+#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
-// Dex file external API
-
-#include <sys/types.h>
+// C++ wrapper for the dex file external API.
#include <cstring>
#include <memory>
#include <string>
#include <string_view>
+#include <utility>
#include <vector>
#include <android-base/macros.h>
-extern "C" {
-
-// This is the stable C ABI that backs art_api::dex below. Structs and functions
-// may only be added here.
-// TODO(b/120978655): Move this to a separate pure C header.
-//
-// Clients should use the C++ wrappers in art_api::dex instead.
-
-// Opaque wrapper for an std::string allocated in libdexfile which must be freed
-// using ExtDexFileFreeString.
-class ExtDexFileString;
-
-// Returns an ExtDexFileString initialized to the given string.
-const ExtDexFileString* ExtDexFileMakeString(const char* str);
-
-// Returns a pointer to the underlying null-terminated character array and its
-// size for the given ExtDexFileString.
-const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size);
-
-// Frees an ExtDexFileString.
-void ExtDexFileFreeString(const ExtDexFileString* ext_string);
-
-struct ExtDexFileMethodInfo {
- int32_t offset;
- int32_t len;
- const ExtDexFileString* name;
-};
-
-class ExtDexFile;
-
-// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
-int ExtDexFileOpenFromMemory(const void* addr,
- /*inout*/ size_t* size,
- const char* location,
- /*out*/ const ExtDexFileString** error_msg,
- /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
-int ExtDexFileOpenFromFd(int fd,
- off_t offset,
- const char* location,
- /*out*/ const ExtDexFileString** error_msg,
- /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
-int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
- int64_t dex_offset,
- /*out*/ ExtDexFileMethodInfo* method_info);
-
-typedef void ExtDexFileMethodInfoCallback(const ExtDexFileMethodInfo* ext_method_info,
- void* user_data);
-
-// See art_api::dex::DexFile::GetAllMethodInfos.
-void ExtDexFileGetAllMethodInfos(ExtDexFile* ext_dex_file,
- int with_signature,
- ExtDexFileMethodInfoCallback* method_info_cb,
- void* user_data);
-
-// Frees an ExtDexFile.
-void ExtDexFileFree(ExtDexFile* ext_dex_file);
-
-} // extern "C"
+#include "art_api/dex_file_external.h"
namespace art_api {
namespace dex {
@@ -98,12 +36,17 @@
// Minimal std::string look-alike for a string returned from libdexfile.
class DexString final {
public:
- DexString(DexString&& dex_str) noexcept { ReplaceExtString(std::move(dex_str)); }
- explicit DexString(const char* str = "") : ext_string_(ExtDexFileMakeString(str)) {}
+ DexString(DexString&& dex_str) noexcept : ext_string_(dex_str.ext_string_) {
+ dex_str.ext_string_ = ExtDexFileMakeString("", 0);
+ }
+ explicit DexString(const char* str = "")
+ : ext_string_(ExtDexFileMakeString(str, std::strlen(str))) {}
+ explicit DexString(std::string_view str)
+ : ext_string_(ExtDexFileMakeString(str.data(), str.size())) {}
~DexString() { ExtDexFileFreeString(ext_string_); }
DexString& operator=(DexString&& dex_str) noexcept {
- ReplaceExtString(std::move(dex_str));
+ std::swap(ext_string_, dex_str.ext_string_);
return *this;
}
@@ -132,11 +75,6 @@
explicit DexString(const ExtDexFileString* ext_string) : ext_string_(ext_string) {}
const ExtDexFileString* ext_string_; // Owned instance. Never nullptr.
- void ReplaceExtString(DexString&& dex_str) {
- ext_string_ = dex_str.ext_string_;
- dex_str.ext_string_ = ExtDexFileMakeString("");
- }
-
DISALLOW_COPY_AND_ASSIGN(DexString);
};
@@ -211,10 +149,15 @@
// Given an offset relative to the start of the dex file header, if there is a
// method whose instruction range includes that offset then returns info about
- // it, otherwise returns a struct with offset == 0.
- MethodInfo GetMethodInfoForOffset(int64_t dex_offset) {
+ // it, otherwise returns a struct with offset == 0. MethodInfo.name receives
+ // the full function signature if with_signature is set, otherwise it gets the
+ // class and method name only.
+ MethodInfo GetMethodInfoForOffset(int64_t dex_offset, bool with_signature) {
ExtDexFileMethodInfo ext_method_info;
- if (ExtDexFileGetMethodInfoForOffset(ext_dex_file_, dex_offset, &ext_method_info)) {
+ if (ExtDexFileGetMethodInfoForOffset(ext_dex_file_,
+ dex_offset,
+ with_signature,
+ &ext_method_info)) {
return AbsorbMethodInfo(ext_method_info);
}
return {/*offset=*/0, /*len=*/0, /*name=*/DexString()};
@@ -223,10 +166,12 @@
// Returns info structs about all methods in the dex file. MethodInfo.name
// receives the full function signature if with_signature is set, otherwise it
// gets the class and method name only.
- std::vector<MethodInfo> GetAllMethodInfos(bool with_signature = true) {
+ std::vector<MethodInfo> GetAllMethodInfos(bool with_signature) {
MethodInfoVector res;
- ExtDexFileGetAllMethodInfos(
- ext_dex_file_, with_signature, AddMethodInfoCallback, static_cast<void*>(&res));
+ ExtDexFileGetAllMethodInfos(ext_dex_file_,
+ with_signature,
+ AddMethodInfoCallback,
+ static_cast<void*>(&res));
return res;
}
@@ -245,4 +190,4 @@
} // namespace dex
} // namespace art_api
-#endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_EXT_DEX_FILE_H_
+#endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index a8d8b2f..fd32c5f 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -23,33 +23,55 @@
],
target: {
android: {
+ shared_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
+ "libbase",
+ ],
static_libs: [
// ZipArchive support, the order matters here to get all symbols.
"libziparchive",
"libz",
],
+ export_shared_lib_headers: ["libbase"],
},
- host: {
+ not_windows: {
shared_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
"libziparchive",
"libz",
+ "libbase",
],
+ export_shared_lib_headers: ["libbase"],
+ },
+ windows: {
+ cflags: ["-Wno-thread-safety"],
+ static_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
+ "libziparchive",
+ "libz",
+ "libbase",
+ ],
+ export_static_lib_headers: ["libbase"],
},
},
//generated_sources: ["art_libartbase_operator_srcs"],
cflags: ["-DBUILDING_LIBART=1"],
- shared_libs: [
- "libartbase",
- "libdexfile",
- "libartbase",
- // For atrace.
- "libcutils",
- ],
export_include_dirs: ["."],
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: ["libbase"],
}
cc_defaults {
@@ -95,6 +117,14 @@
"libziparchive",
],
export_shared_lib_headers: ["libbase"],
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ }
}
art_cc_library {
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 8b8569d..47b17ae 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -19,7 +19,6 @@
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/uio.h>
#include <unistd.h>
#include <zlib.h>
@@ -208,7 +207,11 @@
bool ProfileCompilationInfo::MergeWith(const std::string& filename) {
std::string error;
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
int flags = O_RDONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
ScopedFlock profile_file =
LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);
@@ -236,7 +239,11 @@
return kProfileLoadWouldOverwiteData;
}
+#ifdef _WIN32
+ int flags = O_RDWR;
+#else
int flags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
+#endif
// There's no need to fsync profile data right away. We get many chances
// to write it again in case something goes wrong. We can rely on a simple
// close(), no sync, and let to the kernel decide when to write to disk.
@@ -274,7 +281,11 @@
bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_written) {
ScopedTrace trace(__PRETTY_FUNCTION__);
std::string error;
+#ifdef _WIN32
+ int flags = O_WRONLY;
+#else
int flags = O_WRONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
// There's no need to fsync profile data right away. We get many chances
// to write it again in case something goes wrong. We can rely on a simple
// close(), no sync, and let to the kernel decide when to write to disk.
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
index bd5b598..7a2b638 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1552,7 +1552,7 @@
{
// Make sure we can deopt anything we need to.
- art::ScopedObjectAccess soa(art::Thread::Current());
+ art::ScopedSuspendAll ssa(__FUNCTION__);
gDeoptManager->FinishSetup();
}
diff --git a/openjdkjvmti/deopt_manager.h b/openjdkjvmti/deopt_manager.h
index d9f34a5..065baa7 100644
--- a/openjdkjvmti/deopt_manager.h
+++ b/openjdkjvmti/deopt_manager.h
@@ -107,7 +107,7 @@
void FinishSetup()
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
- REQUIRES_SHARED(art::Locks::mutator_lock_);
+ REQUIRES(art::Locks::mutator_lock_);
static DeoptManager* Get();
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index 7fb6a15..22c622a 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -34,6 +34,7 @@
#include <array>
#include <sys/time.h>
+#include "arch/context.h"
#include "art_field-inl.h"
#include "art_jvmti.h"
#include "art_method-inl.h"
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index 7d69c89..e88539f 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -33,6 +33,7 @@
#include <type_traits>
+#include "arch/context.h"
#include "art_jvmti.h"
#include "art_method-inl.h"
#include "base/enums.h"
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 4bcb7b2..3d175a8 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -188,7 +188,9 @@
if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
// We cannot ensure that the right dex file is used in inlined frames so we don't support
// redefining them.
- DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition";
+ DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
+ << old_method->PrettyMethod() << " is inlined into "
+ << GetOuterMethod()->PrettyMethod();
art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
if (new_obsolete_method == nullptr) {
// Create a new Obsolete Method and put it in the list.
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
index 4a3eac8..385ac45 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -36,6 +36,7 @@
#include <unordered_map>
#include <vector>
+#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "art_jvmti.h"
diff --git a/profman/Android.bp b/profman/Android.bp
index 89e1f7e..33cca02 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -40,7 +40,6 @@
name: "profman",
defaults: ["profman-defaults"],
shared_libs: [
- "libart",
"libprofile",
"libdexfile",
"libartbase",
@@ -54,13 +53,33 @@
"profman-defaults",
],
shared_libs: [
- "libartd",
"libprofiled",
"libdexfiled",
"libartbased",
],
}
+art_cc_binary {
+ name: "profmans",
+ defaults: [
+ "profman-defaults",
+ "libprofile_static_defaults",
+ "libdexfile_static_defaults",
+ "libartbase_static_defaults",
+ ],
+ host_supported: true,
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ cflags: ["-Wno-thread-safety"],
+ },
+ },
+}
+
art_cc_test {
name: "art_profman_tests",
defaults: [
diff --git a/profman/profman.cc b/profman/profman.cc
index 88c5c4e..82d9df0 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -467,6 +467,10 @@
// The methods reads the links from /proc/self/fd/ to find the original apk paths
// and puts them in the dex_locations_ vector.
bool ComputeDexLocationsFromApkFds() {
+#ifdef _WIN32
+ PLOG(ERROR) << "ComputeDexLocationsFromApkFds is unsupported on Windows.";
+ return false;
+#else
// We can't use a char array of PATH_MAX size without exceeding the frame size.
// So we use a vector as the buffer for the path.
std::vector<char> buffer(PATH_MAX, 0);
@@ -482,11 +486,17 @@
dex_locations_.push_back(buffer.data());
}
return true;
+#endif
}
std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename, int fd) {
if (!filename.empty()) {
- fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDWR;
+#else
+ int flags = O_RDWR | O_CLOEXEC;
+#endif
+ fd = open(filename.c_str(), flags);
if (fd < 0) {
LOG(ERROR) << "Cannot open " << filename << strerror(errno);
return nullptr;
@@ -650,7 +660,12 @@
bool GetClassNamesAndMethods(const std::string& profile_file,
std::vector<std::unique_ptr<const DexFile>>* dex_files,
std::set<std::string>* out_lines) {
- int fd = open(profile_file.c_str(), O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
+ int flags = O_RDONLY | O_CLOEXEC;
+#endif
+ int fd = open(profile_file.c_str(), flags);
if (!FdIsValid(fd)) {
LOG(ERROR) << "Cannot open " << profile_file << strerror(errno);
return false;
@@ -1031,7 +1046,12 @@
int fd = reference_profile_file_fd_;
if (!FdIsValid(fd)) {
CHECK(!reference_profile_file_.empty());
- fd = open(reference_profile_file_.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
+#ifdef _WIN32
+ int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+ int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+ fd = open(reference_profile_file_.c_str(), flags, 0644);
if (fd < 0) {
LOG(ERROR) << "Cannot open " << reference_profile_file_ << strerror(errno);
return kInvalidFd;
@@ -1164,9 +1184,12 @@
}
}
// ShouldGenerateTestProfile confirms !test_profile_.empty().
- int profile_test_fd = open(test_profile_.c_str(),
- O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
- 0644);
+#ifdef _WIN32
+ int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+ int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+ int profile_test_fd = open(test_profile_.c_str(), flags, 0644);
if (profile_test_fd < 0) {
LOG(ERROR) << "Cannot open " << test_profile_ << strerror(errno);
return -1;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 71c5b74..b89eb02 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -462,6 +462,7 @@
cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)",
tools: ["generate_operator_out"],
srcs: [
+ "base/callee_save_type.h",
"base/locks.h",
"class_loader_context.h",
"class_status.h",
diff --git a/runtime/arch/arm/callee_save_frame_arm.h b/runtime/arch/arm/callee_save_frame_arm.h
index 11eefb9..72ba3b7 100644
--- a/runtime/arch/arm/callee_save_frame_arm.h
+++ b/runtime/arch/arm/callee_save_frame_arm.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_arm.h"
+#include "runtime_globals.h"
namespace art {
namespace arm {
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index bb33a27..e186cd3 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -18,12 +18,13 @@
#include <sys/ucontext.h>
+#include "arch/instruction_set.h"
#include "art_method.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
+#include "runtime_globals.h"
#include "thread-current-inl.h"
//
diff --git a/runtime/arch/arm64/callee_save_frame_arm64.h b/runtime/arch/arm64/callee_save_frame_arm64.h
index a5aea2a..d3609f1 100644
--- a/runtime/arch/arm64/callee_save_frame_arm64.h
+++ b/runtime/arch/arm64/callee_save_frame_arm64.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_arm64.h"
+#include "runtime_globals.h"
namespace art {
namespace arm64 {
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index e8b4627..751c05b 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -18,13 +18,14 @@
#include <sys/ucontext.h>
+#include "arch/instruction_set.h"
#include "art_method.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
#include "registers_arm64.h"
+#include "runtime_globals.h"
#include "thread-current-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index 0c45bc9..886b40a 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -16,6 +16,9 @@
#include "instruction_set_features.h"
+#include <algorithm>
+#include <ostream>
+
#include "android-base/strings.h"
#include "base/casts.h"
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index c31c927..f910a41 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -17,8 +17,8 @@
#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
#define ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
+#include <iosfwd>
#include <memory>
-#include <ostream>
#include <vector>
#include "arch/instruction_set.h"
diff --git a/runtime/arch/mips/callee_save_frame_mips.h b/runtime/arch/mips/callee_save_frame_mips.h
index 6e88d08..84ce209 100644
--- a/runtime/arch/mips/callee_save_frame_mips.h
+++ b/runtime/arch/mips/callee_save_frame_mips.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_mips.h"
+#include "runtime_globals.h"
namespace art {
namespace mips {
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index 7c8ac28..0354f0c 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -17,14 +17,15 @@
#include <sys/ucontext.h>
#include "fault_handler.h"
+#include "arch/instruction_set.h"
#include "arch/mips/callee_save_frame_mips.h"
#include "art_method.h"
#include "base/callee_save_type.h"
-#include "base/globals.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
#include "registers_mips.h"
+#include "runtime_globals.h"
#include "thread-current-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips/registers_mips.h b/runtime/arch/mips/registers_mips.h
index 34f2f96..4900e41 100644
--- a/runtime/arch/mips/registers_mips.h
+++ b/runtime/arch/mips/registers_mips.h
@@ -19,9 +19,6 @@
#include <iosfwd>
-#include <android-base/logging.h>
-
-#include "base/globals.h"
#include "base/macros.h"
namespace art {
diff --git a/runtime/arch/mips64/callee_save_frame_mips64.h b/runtime/arch/mips64/callee_save_frame_mips64.h
index 59529a0..64d6bec 100644
--- a/runtime/arch/mips64/callee_save_frame_mips64.h
+++ b/runtime/arch/mips64/callee_save_frame_mips64.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_mips64.h"
+#include "runtime_globals.h"
namespace art {
namespace mips64 {
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index 85f3528..6255235 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -18,14 +18,15 @@
#include <sys/ucontext.h>
+#include "arch/instruction_set.h"
#include "arch/mips64/callee_save_frame_mips64.h"
#include "art_method.h"
#include "base/callee_save_type.h"
-#include "base/globals.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
#include "registers_mips64.h"
+#include "runtime_globals.h"
#include "thread-current-inl.h"
extern "C" void art_quick_throw_stack_overflow();
diff --git a/runtime/arch/mips64/registers_mips64.h b/runtime/arch/mips64/registers_mips64.h
index a3fa2ac4..1c22c07 100644
--- a/runtime/arch/mips64/registers_mips64.h
+++ b/runtime/arch/mips64/registers_mips64.h
@@ -19,9 +19,6 @@
#include <iosfwd>
-#include <android-base/logging.h>
-
-#include "base/globals.h"
#include "base/macros.h"
namespace art {
diff --git a/runtime/arch/x86/callee_save_frame_x86.h b/runtime/arch/x86/callee_save_frame_x86.h
index f336f43..2edcade 100644
--- a/runtime/arch/x86/callee_save_frame_x86.h
+++ b/runtime/arch/x86/callee_save_frame_x86.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_x86.h"
+#include "runtime_globals.h"
namespace art {
namespace x86 {
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 8b24334..26312fb 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -18,13 +18,14 @@
#include <sys/ucontext.h>
+#include "arch/instruction_set.h"
#include "art_method.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
#include "base/safe_copy.h"
+#include "runtime_globals.h"
#include "thread-current-inl.h"
#if defined(__APPLE__)
diff --git a/runtime/arch/x86/registers_x86.h b/runtime/arch/x86/registers_x86.h
index d3b959f..ff6c18f 100644
--- a/runtime/arch/x86/registers_x86.h
+++ b/runtime/arch/x86/registers_x86.h
@@ -19,9 +19,6 @@
#include <iosfwd>
-#include <android-base/logging.h>
-
-#include "base/globals.h"
#include "base/macros.h"
namespace art {
diff --git a/runtime/arch/x86_64/callee_save_frame_x86_64.h b/runtime/arch/x86_64/callee_save_frame_x86_64.h
index 228a902..d4f2da7 100644
--- a/runtime/arch/x86_64/callee_save_frame_x86_64.h
+++ b/runtime/arch/x86_64/callee_save_frame_x86_64.h
@@ -21,9 +21,9 @@
#include "base/bit_utils.h"
#include "base/callee_save_type.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "quick/quick_method_frame_info.h"
#include "registers_x86_64.h"
+#include "runtime_globals.h"
namespace art {
namespace x86_64 {
diff --git a/runtime/arch/x86_64/registers_x86_64.h b/runtime/arch/x86_64/registers_x86_64.h
index 66aea70..248c82b 100644
--- a/runtime/arch/x86_64/registers_x86_64.h
+++ b/runtime/arch/x86_64/registers_x86_64.h
@@ -19,9 +19,6 @@
#include <iosfwd>
-#include <android-base/logging.h>
-
-#include "base/globals.h"
#include "base/macros.h"
namespace art {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index aed9f62..aabd093 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -476,7 +476,7 @@
}
ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) {
- if (UNLIKELY(IsNative()) || UNLIKELY(IsProxyMethod())) {
+ if (UNLIKELY(IsNative() || IsProxyMethod() || !IsInvokable())) {
return nullptr;
}
return reinterpret_cast<ProfilingInfo*>(GetDataPtrSize(pointer_size));
diff --git a/libartbase/base/callee_save_type.h b/runtime/base/callee_save_type.h
similarity index 89%
rename from libartbase/base/callee_save_type.h
rename to runtime/base/callee_save_type.h
index 3e44a3a..e7cc7e6 100644
--- a/libartbase/base/callee_save_type.h
+++ b/runtime/base/callee_save_type.h
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#ifndef ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
-#define ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
+#ifndef ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
+#define ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
-#include <cstddef>
-#include <ostream>
+#include <cstdint>
+#include <iosfwd>
namespace art {
@@ -44,4 +44,4 @@
} // namespace art
-#endif // ART_LIBARTBASE_BASE_CALLEE_SAVE_TYPE_H_
+#endif // ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 41a47af..aaa1ee6 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -28,7 +28,7 @@
#include "base/aborting.h"
#include "base/atomic.h"
-#include "base/globals.h"
+#include "runtime_globals.h"
#include "base/macros.h"
#include "locks.h"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 5d1f20c..d29a6b7 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -229,7 +229,9 @@
}
}
-void ClassLinker::ThrowEarlierClassFailure(ObjPtr<mirror::Class> c, bool wrap_in_no_class_def) {
+void ClassLinker::ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
+ bool wrap_in_no_class_def,
+ bool log) {
// The class failed to initialize on a previous attempt, so we want to throw
// a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
// failed in verification, in which case v2 5.4.1 says we need to re-throw
@@ -245,8 +247,10 @@
extra = verify_error->AsThrowable()->Dump();
}
}
- LOG(INFO) << "Rejecting re-init on previously-failed class " << c->PrettyClass()
- << ": " << extra;
+ if (log) {
+ LOG(INFO) << "Rejecting re-init on previously-failed class " << c->PrettyClass()
+ << ": " << extra;
+ }
}
CHECK(c->IsErroneous()) << c->PrettyClass() << " " << c->GetStatus();
@@ -5044,7 +5048,7 @@
// Was the class already found to be erroneous? Done under the lock to match the JLS.
if (klass->IsErroneous()) {
- ThrowEarlierClassFailure(klass.Get(), true);
+ ThrowEarlierClassFailure(klass.Get(), true, /* log= */ true);
VlogClassInitializationFailure(klass);
return false;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index b9ac9ca..4f4cb4b 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_CLASS_LINKER_H_
#define ART_RUNTIME_CLASS_LINKER_H_
+#include <list>
#include <set>
#include <string>
#include <unordered_map>
@@ -89,6 +90,7 @@
class Runtime;
class ScopedObjectAccessAlreadyRunnable;
template<size_t kNumReferences> class PACKED(4) StackHandleScope;
+class Thread;
enum VisitRootFlags : uint8_t;
@@ -685,7 +687,9 @@
// Throw the class initialization failure recorded when first trying to initialize the given
// class.
- void ThrowEarlierClassFailure(ObjPtr<mirror::Class> c, bool wrap_in_no_class_def = false)
+ void ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
+ bool wrap_in_no_class_def = false,
+ bool log = false)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 29b7813..d7f6127 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -26,7 +26,6 @@
#include "arch/instruction_set.h"
#include "base/common_art_test.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/os.h"
#include "base/unix_file/fd_file.h"
@@ -34,6 +33,7 @@
#include "dex/compact_dex_level.h"
// TODO: Add inl file and avoid including inl.
#include "obj_ptr-inl.h"
+#include "runtime_globals.h"
#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/compiler_filter.cc b/runtime/compiler_filter.cc
index bda64eb..c086490 100644
--- a/runtime/compiler_filter.cc
+++ b/runtime/compiler_filter.cc
@@ -16,6 +16,8 @@
#include "compiler_filter.h"
+#include <ostream>
+
#include "base/utils.h"
namespace art {
diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h
index 012ebcb..c36e40f 100644
--- a/runtime/compiler_filter.h
+++ b/runtime/compiler_filter.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_COMPILER_FILTER_H_
#define ART_RUNTIME_COMPILER_FILTER_H_
-#include <ostream>
+#include <iosfwd>
#include <string>
#include <vector>
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index adf01c3..663af81 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -681,13 +681,13 @@
//
// The performance cost of this is non-negligible during native-debugging due to the
// forced JIT, so we keep the AOT code in that case in exchange for limited native debugging.
+ ScopedSuspendAll ssa(__FUNCTION__);
if (!runtime->IsJavaDebuggable() &&
!runtime->GetInstrumentation()->IsForcedInterpretOnly() &&
!runtime->IsNativeDebuggable()) {
runtime->DeoptimizeBootImage();
}
- ScopedSuspendAll ssa(__FUNCTION__);
if (RequiresDeoptimization()) {
runtime->GetInstrumentation()->EnableDeoptimization();
}
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 7f697d1..9c0ac8f 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -72,7 +72,8 @@
const std::string& oat_location,
CompilerFilter::Filter filter,
bool with_alternate_image,
- const char* compilation_reason) {
+ const char* compilation_reason,
+ const std::vector<std::string>& extra_args) {
std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA));
std::string dalvik_cache_tmp = dalvik_cache + ".redirected";
@@ -101,6 +102,8 @@
args.push_back("--compilation-reason=" + std::string(compilation_reason));
}
+ args.insert(args.end(), extra_args.begin(), extra_args.end());
+
std::string error_msg;
ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
@@ -136,12 +139,14 @@
void DexoptTest::GenerateOdexForTest(const std::string& dex_location,
const std::string& odex_location,
CompilerFilter::Filter filter,
- const char* compilation_reason) {
+ const char* compilation_reason,
+ const std::vector<std::string>& extra_args) {
GenerateOatForTest(dex_location,
odex_location,
filter,
/*with_alternate_image=*/ false,
- compilation_reason);
+ compilation_reason,
+ extra_args);
}
void DexoptTest::GenerateOatForTest(const char* dex_location,
diff --git a/runtime/dexopt_test.h b/runtime/dexopt_test.h
index efbdcba..026fe55 100644
--- a/runtime/dexopt_test.h
+++ b/runtime/dexopt_test.h
@@ -42,13 +42,15 @@
const std::string& oat_location,
CompilerFilter::Filter filter,
bool with_alternate_image,
- const char* compilation_reason = nullptr);
+ const char* compilation_reason = nullptr,
+ const std::vector<std::string>& extra_args = {});
// Generate an odex file for the purposes of test.
void GenerateOdexForTest(const std::string& dex_location,
const std::string& odex_location,
CompilerFilter::Filter filter,
- const char* compilation_reason = nullptr);
+ const char* compilation_reason = nullptr,
+ const std::vector<std::string>& extra_args = {});
// Generate an oat file for the given dex location in its oat location (under
// the dalvik cache).
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 2431bce..d06dbcb 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -16,7 +16,6 @@
#include "base/logging.h" // For VLOG_IS_ON.
#include "base/mutex.h"
-#include "base/systrace.h"
#include "callee_save_frame.h"
#include "interpreter/interpreter.h"
#include "obj_ptr-inl.h" // TODO: Find the other include that isn't complete, and clean this up.
@@ -41,13 +40,10 @@
self->AssertHasDeoptimizationContext();
QuickExceptionHandler exception_handler(self, true);
- {
- ScopedTrace trace(std::string("Deoptimization ") + GetDeoptimizationKindName(kind));
- if (single_frame) {
- exception_handler.DeoptimizeSingleFrame(kind);
- } else {
- exception_handler.DeoptimizeStack();
- }
+ if (single_frame) {
+ exception_handler.DeoptimizeSingleFrame(kind);
+ } else {
+ exception_handler.DeoptimizeStack();
}
uintptr_t return_pc = exception_handler.UpdateInstrumentationStack();
if (exception_handler.IsFullFragmentDone()) {
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index d3be51f..f6cf2d7 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -23,8 +23,8 @@
#include <vector>
-#include "base/globals.h" // For CanDoImplicitNullCheckOn.
#include "base/locks.h" // For annotalysis.
+#include "runtime_globals.h" // For CanDoImplicitNullCheckOn.
namespace art {
diff --git a/runtime/gc/accounting/bitmap.h b/runtime/gc/accounting/bitmap.h
index bdc686e..68f2d04 100644
--- a/runtime/gc/accounting/bitmap.h
+++ b/runtime/gc/accounting/bitmap.h
@@ -23,9 +23,9 @@
#include <set>
#include <vector>
-#include "base/globals.h"
#include "base/locks.h"
#include "base/mem_map.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/gc/accounting/card_table.h b/runtime/gc/accounting/card_table.h
index c99ed4b..30c4386 100644
--- a/runtime/gc/accounting/card_table.h
+++ b/runtime/gc/accounting/card_table.h
@@ -19,9 +19,9 @@
#include <memory>
-#include "base/globals.h"
#include "base/locks.h"
#include "base/mem_map.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 8c471bc..011e95c 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -18,12 +18,12 @@
#define ART_RUNTIME_GC_ACCOUNTING_MOD_UNION_TABLE_H_
#include "base/allocator.h"
-#include "base/globals.h"
#include "base/safe_map.h"
#include "base/tracking_safe_map.h"
#include "bitmap.h"
#include "card_table.h"
#include "mirror/object_reference.h"
+#include "runtime_globals.h"
#include <set>
#include <vector>
diff --git a/runtime/gc/accounting/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index 2e42f8d..44cdb5e 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -20,10 +20,10 @@
#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/mem_map.h"
#include "gc/space/space.h"
+#include "runtime_globals.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/remembered_set.h b/runtime/gc/accounting/remembered_set.h
index 469074f..3525667 100644
--- a/runtime/gc/accounting/remembered_set.h
+++ b/runtime/gc/accounting/remembered_set.h
@@ -18,9 +18,9 @@
#define ART_RUNTIME_GC_ACCOUNTING_REMEMBERED_SET_H_
#include "base/allocator.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/safe_map.h"
+#include "runtime_globals.h"
#include <set>
#include <vector>
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 8561f06..6ca254a 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -23,9 +23,9 @@
#include <set>
#include <vector>
-#include "base/globals.h"
#include "base/locks.h"
#include "base/mem_map.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/gc/accounting/space_bitmap_test.cc b/runtime/gc/accounting/space_bitmap_test.cc
index 22529b8..9f355e3 100644
--- a/runtime/gc/accounting/space_bitmap_test.cc
+++ b/runtime/gc/accounting/space_bitmap_test.cc
@@ -19,9 +19,9 @@
#include <stdint.h>
#include <memory>
-#include "base/globals.h"
#include "base/mutex.h"
#include "common_runtime_test.h"
+#include "runtime_globals.h"
#include "space_bitmap-inl.h"
namespace art {
diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index 11ad8a8..79d4fbf 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -60,8 +60,8 @@
#include <sys/mman.h>
-#include "base/globals.h"
#include "base/utils.h"
+#include "runtime_globals.h"
extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* arg) {
// Is this chunk in use?
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index bf26aea..0906295 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -30,9 +30,9 @@
#include "base/allocator.h"
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "base/mem_map.h"
#include "base/mutex.h"
+#include "runtime_globals.h"
#include "thread.h"
namespace art {
diff --git a/runtime/gc/gc_cause.cc b/runtime/gc/gc_cause.cc
index ee7ac7d..8b4bac2 100644
--- a/runtime/gc/gc_cause.cc
+++ b/runtime/gc/gc_cause.cc
@@ -18,8 +18,8 @@
#include <android-base/logging.h>
-#include "base/globals.h"
#include "base/macros.h"
+#include "runtime_globals.h"
#include <ostream>
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8d19cd0..d699da0 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3798,7 +3798,7 @@
if (!Runtime::Current()->IsShuttingDown(self)) {
// Wait for any GCs currently running to finish.
if (WaitForGcToComplete(cause, self) == collector::kGcTypeNone) {
- // If the we can't run the GC type we wanted to run, find the next appropriate one and try
+ // If we can't run the GC type we wanted to run, find the next appropriate one and try
// that instead. E.g. can't do partial, so do full instead.
collector::GcType next_gc_type = next_gc_type_;
// If forcing full and next gc type is sticky, override with a non-sticky type.
@@ -3977,8 +3977,13 @@
// If weighted java + native memory use exceeds our target by kStopForNativeFactor, and
// newly allocated memory exceeds kHugeNativeAlloc, we wait for GC to complete to avoid
// running out of memory.
-static constexpr float kStopForNativeFactor = 2.0;
-static constexpr size_t kHugeNativeAllocs = 200*1024*1024;
+static constexpr float kStopForNativeFactor = 4.0;
+// TODO: Allow this to be tuned. We want this much smaller for some apps, like Calculator.
+// But making it too small can cause jank in apps like launcher that intentionally allocate
+// large amounts of memory in rapid succession. (b/122099093)
+// For now, we punt, and use a value that should be easily large enough to disable this in all
+// questionable setting, but that is clearly too large to be effective for small memory devices.
+static constexpr size_t kHugeNativeAllocs = 1 * GB;
// Return the ratio of the weighted native + java allocated bytes to its target value.
// A return value > 1.0 means we should collect. Significantly larger values mean we're falling
@@ -3998,8 +4003,9 @@
size_t new_native_bytes = UnsignedDifference(current_native_bytes, old_native_bytes);
size_t weighted_native_bytes = new_native_bytes / kNewNativeDiscountFactor
+ old_native_bytes / kOldNativeDiscountFactor;
- size_t adj_start_bytes = concurrent_start_bytes_
- + NativeAllocationGcWatermark() / kNewNativeDiscountFactor;
+ size_t add_bytes_allowed = static_cast<size_t>(
+ NativeAllocationGcWatermark() * HeapGrowthMultiplier());
+ size_t adj_start_bytes = concurrent_start_bytes_ + add_bytes_allowed / kNewNativeDiscountFactor;
return static_cast<float>(GetBytesAllocated() + weighted_native_bytes)
/ static_cast<float>(adj_start_bytes);
}
@@ -4017,7 +4023,7 @@
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
LOG(INFO) << "Stopping for native allocation, urgency: " << gc_urgency;
}
- WaitForGcToComplete(kGcCauseForAlloc, self);
+ WaitForGcToComplete(kGcCauseForNativeAlloc, self);
}
} else {
CollectGarbageInternal(NonStickyGcType(), kGcCauseForNativeAlloc, false);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 6696cc1..52c9386 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -25,9 +25,7 @@
#include <android-base/logging.h>
#include "allocator_type.h"
-#include "arch/instruction_set.h"
#include "base/atomic.h"
-#include "base/globals.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "base/runtime_debug.h"
@@ -43,11 +41,13 @@
#include "offsets.h"
#include "process_state.h"
#include "read_barrier_config.h"
+#include "runtime_globals.h"
#include "verify_object.h"
namespace art {
class ConditionVariable;
+enum class InstructionSet;
class IsMarkedVisitor;
class Mutex;
class RootVisitor;
@@ -157,7 +157,12 @@
// Client should call NotifyNativeAllocation every kNotifyNativeInterval allocations.
// Should be chosen so that time_to_call_mallinfo / kNotifyNativeInterval is on the same order
// as object allocation time. time_to_call_mallinfo seems to be on the order of 1 usec.
+#ifdef __ANDROID__
static constexpr uint32_t kNotifyNativeInterval = 32;
+#else
+ // Some host mallinfo() implementations are slow. And memory is less scarce.
+ static constexpr uint32_t kNotifyNativeInterval = 128;
+#endif
// RegisterNativeAllocation checks immediately whether GC is needed if size exceeds the
// following. kCheckImmediatelyThreshold * kNotifyNativeInterval should be small enough to
@@ -436,6 +441,10 @@
return process_cpu_start_time_ns_;
}
+ uint64_t GetPostGCLastProcessCpuTime() const {
+ return post_gc_last_process_cpu_time_ns_;
+ }
+
// Set target ideal heap utilization ratio, implements
// dalvik.system.VMRuntime.setTargetHeapUtilization.
void SetTargetHeapUtilization(float target);
@@ -1140,15 +1149,9 @@
// collect. We collect when a weighted sum of Java memory plus native memory exceeds
// the similarly weighted sum of the Java heap size target and this value.
ALWAYS_INLINE size_t NativeAllocationGcWatermark() const {
- // It probably makes most sense to use a constant multiple of target_footprint_ .
- // This is a good indication of the live data size, together with the
- // intended space-time trade-off, as expressed by SetTargetHeapUtilization.
- // For a fixed target utilization, the amount of GC effort per native
- // allocated byte remains roughly constant as the Java heap size changes.
- // But we previously triggered on max_free_ native allocation which is often much
- // smaller. To avoid unexpected growth, we partially keep that limit in place for now.
- // TODO: Consider HeapGrowthMultiplier(). Maybe.
- return std::min(target_footprint_.load(std::memory_order_relaxed), 2 * max_free_);
+ // We keep the traditional limit of max_free_ in place for small heaps,
+ // but allow it to be adjusted upward for large heaps to limit GC overhead.
+ return target_footprint_.load(std::memory_order_relaxed) / 8 + max_free_;
}
ALWAYS_INLINE void IncrementNumberOfBytesFreedRevoke(size_t freed_bytes_revoke);
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 17b546a..c1c9a3c 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -17,10 +17,10 @@
#ifndef ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_
-#include "base/globals.h"
#include "base/locks.h"
#include "jni.h"
#include "reference_queue.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index 53518cc..90f0be7 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -22,12 +22,12 @@
#include <vector>
#include "base/atomic.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/timing_logger.h"
#include "jni.h"
#include "obj_ptr.h"
#include "offsets.h"
+#include "runtime_globals.h"
#include "thread_pool.h"
namespace art {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 64fd3cd..4a2dbf5 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -25,6 +25,7 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
+#include "arch/instruction_set.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/array_ref.h"
@@ -341,6 +342,10 @@
return address - source_ < length_;
}
+ bool InDest(const void* dest) const {
+ return InDest(reinterpret_cast<uintptr_t>(dest));
+ }
+
bool InDest(uintptr_t address) const {
return address - dest_ < length_;
}
@@ -381,11 +386,11 @@
<< reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
}
-template <PointerSize kPointerSize, typename ReferenceVisitor>
+template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
class ImageSpace::PatchObjectVisitor final {
public:
- explicit PatchObjectVisitor(ReferenceVisitor reference_visitor)
- : reference_visitor_(reference_visitor) {}
+ explicit PatchObjectVisitor(HeapVisitor heap_visitor, NativeVisitor native_visitor)
+ : heap_visitor_(heap_visitor), native_visitor_(native_visitor) {}
void VisitClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_) {
// A mirror::Class object consists of
@@ -445,12 +450,8 @@
}
template <typename T>
- T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED) const
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (ptr != nullptr) {
- ptr = reference_visitor_(ptr);
- }
- return ptr;
+ T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED) const {
+ return (ptr != nullptr) ? native_visitor_(ptr) : nullptr;
}
void VisitPointerArray(mirror::PointerArray* pointer_array)
@@ -526,7 +527,7 @@
T* old_value = root->template Read<kWithoutReadBarrier>();
DCHECK(kMayBeNull || old_value != nullptr);
if (!kMayBeNull || old_value != nullptr) {
- *root = GcRoot<T>(reference_visitor_(old_value));
+ *root = GcRoot<T>(heap_visitor_(old_value));
}
}
@@ -537,7 +538,7 @@
T* old_value = reinterpret_cast64<T*>(*raw_entry);
DCHECK(kMayBeNull || old_value != nullptr);
if (!kMayBeNull || old_value != nullptr) {
- T* new_value = reference_visitor_(old_value);
+ T* new_value = native_visitor_(old_value);
*raw_entry = reinterpret_cast64<uint64_t>(new_value);
}
} else {
@@ -545,7 +546,7 @@
T* old_value = reinterpret_cast32<T*>(*raw_entry);
DCHECK(kMayBeNull || old_value != nullptr);
if (!kMayBeNull || old_value != nullptr) {
- T* new_value = reference_visitor_(old_value);
+ T* new_value = native_visitor_(old_value);
*raw_entry = reinterpret_cast32<uint32_t>(new_value);
}
}
@@ -558,7 +559,7 @@
object->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
DCHECK(kMayBeNull || old_value != nullptr);
if (!kMayBeNull || old_value != nullptr) {
- mirror::Object* new_value = reference_visitor_(old_value);
+ mirror::Object* new_value = heap_visitor_(old_value);
object->SetFieldObjectWithoutWriteBarrier</*kTransactionActive=*/ false,
/*kCheckTransaction=*/ true,
kVerifyNone>(offset, new_value);
@@ -582,7 +583,7 @@
mirror::NativeDexCachePair<T> pair =
mirror::DexCache::GetNativePairPtrSize(array, index, kPointerSize);
if (pair.object != nullptr) {
- pair.object = reference_visitor_(pair.object);
+ pair.object = native_visitor_(pair.object);
mirror::DexCache::SetNativePairPtrSize(array, index, pair, kPointerSize);
}
}
@@ -605,7 +606,7 @@
reinterpret_cast64<EntryType*>(dex_cache->GetField64<kVerifyNone>(array_offset));
DCHECK_EQ(old_array != nullptr, size != 0u);
if (old_array != nullptr) {
- EntryType* new_array = reference_visitor_(old_array);
+ EntryType* new_array = native_visitor_(old_array);
dex_cache->SetField64<kVerifyNone>(array_offset, reinterpret_cast64<uint64_t>(new_array));
for (uint32_t i = 0; i != size; ++i) {
FixupDexCacheArrayEntry(new_array, i);
@@ -614,7 +615,11 @@
}
private:
- ReferenceVisitor reference_visitor_;
+ // Heap objects visitor.
+ HeapVisitor heap_visitor_;
+
+ // Native objects visitor.
+ NativeVisitor native_visitor_;
};
template <typename ObjectVisitor>
@@ -828,7 +833,7 @@
// GetImageBegin is the preferred address to map the image. If we manage to map the
// image at the image begin, the amount of fixup work required is minimized.
- // If it is pic we will retry with error_msg for the failure case. Pass a null error_msg to
+ // If it is pic we will retry with error_msg for the2 failure case. Pass a null error_msg to
// avoid reading proc maps for a mapping failure and slowing everything down.
// For the boot image, we have already reserved the memory and we load the image
// into the `image_reservation`.
@@ -981,12 +986,11 @@
auto function = [&](Thread*) {
const uint64_t start2 = NanoTime();
ScopedTrace trace("LZ4 decompress block");
- if (!block.Decompress(/*out_ptr=*/map.Begin(),
- /*in_ptr=*/temp_map.Begin(),
- error_msg)) {
- if (error_msg != nullptr) {
- *error_msg = "Failed to decompress image block " + *error_msg;
- }
+ bool result = block.Decompress(/*out_ptr=*/map.Begin(),
+ /*in_ptr=*/temp_map.Begin(),
+ error_msg);
+ if (!result && error_msg != nullptr) {
+ *error_msg = "Failed to decompress image block " + *error_msg;
}
VLOG(image) << "Decompress block " << block.GetDataSize() << " -> "
<< block.GetImageSize() << " in " << PrettyDuration(NanoTime() - start2);
@@ -1011,70 +1015,51 @@
return map;
}
- class FixupVisitor : public ValueObject {
+ class EmptyRange {
public:
- FixupVisitor(const RelocationRange& boot_image,
- const RelocationRange& app_image,
- const RelocationRange& app_oat)
- : boot_image_(boot_image),
- app_image_(app_image),
- app_oat_(app_oat) {}
+ ALWAYS_INLINE bool InSource(uintptr_t) const { return false; }
+ ALWAYS_INLINE bool InDest(uintptr_t) const { return false; }
+ ALWAYS_INLINE uintptr_t ToDest(uintptr_t) const { UNREACHABLE(); }
+ };
+
+ template <typename Range0, typename Range1 = EmptyRange, typename Range2 = EmptyRange>
+ class ForwardAddress {
+ public:
+ ForwardAddress(const Range0& range0 = Range0(),
+ const Range1& range1 = Range1(),
+ const Range2& range2 = Range2())
+ : range0_(range0), range1_(range1), range2_(range2) {}
// Return the relocated address of a heap object.
// Null checks must be performed in the caller (for performance reasons).
template <typename T>
- ALWAYS_INLINE T* ForwardObject(T* src) const {
+ ALWAYS_INLINE T* operator()(T* src) const {
DCHECK(src != nullptr);
const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
- if (boot_image_.InSource(uint_src)) {
- return reinterpret_cast<T*>(boot_image_.ToDest(uint_src));
+ if (range2_.InSource(uint_src)) {
+ return reinterpret_cast<T*>(range2_.ToDest(uint_src));
}
- // Since we are fixing up the app image, there should only be pointers to the app image and
- // boot image.
- DCHECK(app_image_.InSource(uint_src)) << reinterpret_cast<const void*>(src);
- return reinterpret_cast<T*>(app_image_.ToDest(uint_src));
- }
-
- // Return the relocated address of a code pointer (contained by an oat file).
- // Null checks must be performed in the caller (for performance reasons).
- ALWAYS_INLINE const void* ForwardCode(const void* src) const {
- DCHECK(src != nullptr);
- const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
- if (boot_image_.InSource(uint_src)) {
- return reinterpret_cast<const void*>(boot_image_.ToDest(uint_src));
+ if (range1_.InSource(uint_src)) {
+ return reinterpret_cast<T*>(range1_.ToDest(uint_src));
}
- DCHECK(app_oat_.InSource(uint_src)) << src;
- return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src));
+ CHECK(range0_.InSource(uint_src))
+ << reinterpret_cast<const void*>(src) << " not in "
+ << reinterpret_cast<const void*>(range0_.Source()) << "-"
+ << reinterpret_cast<const void*>(range0_.Source() + range0_.Length());
+ return reinterpret_cast<T*>(range0_.ToDest(uint_src));
}
- // Must be called on pointers that already have been relocated to the destination relocation.
- ALWAYS_INLINE bool IsInAppImage(mirror::Object* object) const {
- return app_image_.InDest(reinterpret_cast<uintptr_t>(object));
- }
-
- protected:
- // Source section.
- const RelocationRange boot_image_;
- const RelocationRange app_image_;
- const RelocationRange app_oat_;
+ private:
+ const Range0 range0_;
+ const Range1 range1_;
+ const Range2 range2_;
};
- // Adapt for mirror::Class::FixupNativePointers.
- class FixupObjectAdapter : public FixupVisitor {
+ template <typename Forward>
+ class FixupRootVisitor {
public:
template<typename... Args>
- explicit FixupObjectAdapter(Args... args) : FixupVisitor(args...) {}
-
- template <typename T>
- T* operator()(T* obj, void** dest_addr ATTRIBUTE_UNUSED = nullptr) const {
- return ForwardObject(obj);
- }
- };
-
- class FixupRootVisitor : public FixupVisitor {
- public:
- template<typename... Args>
- explicit FixupRootVisitor(Args... args) : FixupVisitor(args...) {}
+ explicit FixupRootVisitor(Args... args) : forward_(args...) {}
ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1086,19 +1071,22 @@
ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
REQUIRES_SHARED(Locks::mutator_lock_) {
mirror::Object* ref = root->AsMirrorPtr();
- mirror::Object* new_ref = ForwardObject(ref);
+ mirror::Object* new_ref = forward_(ref);
if (ref != new_ref) {
root->Assign(new_ref);
}
}
+
+ private:
+ Forward forward_;
};
- class FixupObjectVisitor : public FixupVisitor {
+ template <typename Forward>
+ class FixupObjectVisitor {
public:
- template<typename... Args>
- explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited, Args... args)
- : FixupVisitor(args...),
- visited_(visited) {}
+ explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited,
+ const Forward& forward)
+ : visited_(visited), forward_(forward) {}
// Fix up separately since we also need to fix up method entrypoints.
ALWAYS_INLINE void VisitRootIfNonNull(
@@ -1117,8 +1105,7 @@
if (ref != nullptr) {
// Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
// image.
- obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
- offset, ForwardObject(ref));
+ obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(offset, forward_(ref));
}
}
@@ -1130,7 +1117,7 @@
if (obj != nullptr) {
ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
mirror::Reference::ReferentOffset(),
- ForwardObject(obj));
+ forward_(obj));
}
}
@@ -1147,79 +1134,61 @@
private:
gc::accounting::ContinuousSpaceBitmap* const visited_;
+ Forward forward_;
};
- class ForwardObjectAdapter {
- public:
- ALWAYS_INLINE explicit ForwardObjectAdapter(const FixupVisitor* visitor) : visitor_(visitor) {}
-
- template <typename T>
- ALWAYS_INLINE T* operator()(T* src) const {
- return visitor_->ForwardObject(src);
- }
-
- private:
- const FixupVisitor* const visitor_;
- };
-
- class ForwardCodeAdapter {
- public:
- ALWAYS_INLINE explicit ForwardCodeAdapter(const FixupVisitor* visitor)
- : visitor_(visitor) {}
-
- template <typename T>
- ALWAYS_INLINE T* operator()(T* src) const {
- return visitor_->ForwardCode(src);
- }
-
- private:
- const FixupVisitor* const visitor_;
- };
-
- class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor {
+ template <typename ForwardObject, typename ForwardNative, typename ForwardCode>
+ class FixupArtMethodVisitor : public ArtMethodVisitor {
public:
template<typename... Args>
- explicit FixupArtMethodVisitor(bool fixup_heap_objects, PointerSize pointer_size, Args... args)
- : FixupVisitor(args...),
- fixup_heap_objects_(fixup_heap_objects),
- pointer_size_(pointer_size) {}
+ explicit FixupArtMethodVisitor(PointerSize pointer_size,
+ const ForwardObject& forward_object,
+ const ForwardNative& forward_native,
+ const ForwardCode& forward_code)
+ : pointer_size_(pointer_size),
+ forward_object_(forward_object),
+ forward_native_(forward_native),
+ forward_code_(forward_code) {}
void Visit(ArtMethod* method) override NO_THREAD_SAFETY_ANALYSIS {
// TODO: Separate visitor for runtime vs normal methods.
if (UNLIKELY(method->IsRuntimeMethod())) {
ImtConflictTable* table = method->GetImtConflictTable(pointer_size_);
if (table != nullptr) {
- ImtConflictTable* new_table = ForwardObject(table);
+ ImtConflictTable* new_table = forward_native_(table);
if (table != new_table) {
method->SetImtConflictTable(new_table, pointer_size_);
}
}
const void* old_code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
- const void* new_code = ForwardCode(old_code);
+ const void* new_code = forward_code_(old_code);
if (old_code != new_code) {
method->SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size_);
}
} else {
- if (fixup_heap_objects_) {
- method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
- }
- method->UpdateEntrypoints(ForwardCodeAdapter(this), pointer_size_);
+ method->UpdateObjectsForImageRelocation(forward_object_);
+ method->UpdateEntrypoints(forward_code_, pointer_size_);
}
}
private:
- const bool fixup_heap_objects_;
const PointerSize pointer_size_;
+ const ForwardObject forward_object_;
+ const ForwardNative forward_native_;
+ const ForwardCode forward_code_;
};
- class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor {
+ template <typename Forward>
+ class FixupArtFieldVisitor : public ArtFieldVisitor {
public:
- template<typename... Args>
- explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {}
+ explicit FixupArtFieldVisitor(Forward forward) : forward_(forward) {}
void Visit(ArtField* field) override NO_THREAD_SAFETY_ANALYSIS {
- field->UpdateObjects(ForwardObjectAdapter(this));
+ field->UpdateObjects(forward_);
}
+
+ private:
+ Forward forward_;
};
// Relocate an image space mapped at target_base which possibly used to be at a different base
@@ -1256,30 +1225,49 @@
static_cast<uint64_t>(image_header_boot_image_size));
return false;
}
+ const ImageSection& objects_section = image_header.GetObjectsSection();
+ // Where the app image objects are mapped to.
+ uint8_t* objects_location = target_base + objects_section.Offset();
TimingLogger logger(__FUNCTION__, true, false);
RelocationRange boot_image(image_header.GetBootImageBegin(),
boot_image_begin,
boot_image_size);
- RelocationRange app_image(reinterpret_cast<uintptr_t>(image_header.GetImageBegin()),
- reinterpret_cast<uintptr_t>(target_base),
- image_header.GetImageSize());
+ // Metadata is everything after the objects section, use exclusion to be safe.
+ RelocationRange app_image_metadata(
+ reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.End(),
+ reinterpret_cast<uintptr_t>(target_base) + objects_section.End(),
+ image_header.GetImageSize() - objects_section.End());
+ // App image heap objects, may be mapped in the heap.
+ RelocationRange app_image_objects(
+ reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.Offset(),
+ reinterpret_cast<uintptr_t>(objects_location),
+ objects_section.Size());
// Use the oat data section since this is where the OatFile::Begin is.
RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
// Not necessarily in low 4GB.
reinterpret_cast<uintptr_t>(app_oat_file->Begin()),
image_header.GetOatDataEnd() - image_header.GetOatDataBegin());
- VLOG(image) << "App image " << app_image;
+ VLOG(image) << "App image metadata " << app_image_metadata;
+ VLOG(image) << "App image objects " << app_image_objects;
VLOG(image) << "App oat " << app_oat;
VLOG(image) << "Boot image " << boot_image;
// True if we need to fixup any heap pointers.
- const bool fixup_image = boot_image.Delta() != 0 || app_image.Delta() != 0;
+ const bool fixup_image = boot_image.Delta() != 0 || app_image_metadata.Delta() != 0 ||
+ app_image_objects.Delta() != 0;
if (!fixup_image) {
// Nothing to fix up.
return true;
}
ScopedDebugDisallowReadBarriers sddrb(Thread::Current());
- FixupObjectAdapter fixup_adapter(boot_image, app_image, app_oat);
- PatchObjectVisitor<kPointerSize, FixupObjectAdapter> patch_object_visitor(fixup_adapter);
+
+ using ForwardObject = ForwardAddress<RelocationRange, RelocationRange>;
+ ForwardObject forward_object(boot_image, app_image_objects);
+ ForwardObject forward_metadata(boot_image, app_image_metadata);
+ using ForwardCode = ForwardAddress<RelocationRange, RelocationRange>;
+ ForwardCode forward_code(boot_image, app_oat);
+ PatchObjectVisitor<kPointerSize, ForwardObject, ForwardCode> patch_object_visitor(
+ forward_object,
+ forward_metadata);
if (fixup_image) {
// Two pass approach, fix up all classes first, then fix up non class-objects.
// The visited bitmap is used to ensure that pointer arrays are not forwarded twice.
@@ -1287,13 +1275,12 @@
gc::accounting::ContinuousSpaceBitmap::Create("Relocate bitmap",
target_base,
image_header.GetImageSize()));
- FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(), boot_image, app_image, app_oat);
{
TimingLogger::ScopedTiming timing("Fixup classes", &logger);
const auto& class_table_section = image_header.GetClassTableSection();
if (class_table_section.Size() > 0u) {
ScopedObjectAccess soa(Thread::Current());
- ClassTableVisitor class_table_visitor(fixup_adapter);
+ ClassTableVisitor class_table_visitor(forward_object);
size_t read_count = 0u;
const uint8_t* data = target_base + class_table_section.Offset();
// We avoid making a copy of the data since we want modifications to be propagated to the
@@ -1302,7 +1289,7 @@
for (ClassTable::TableSlot& slot : temp_set) {
slot.VisitRoot(class_table_visitor);
mirror::Class* klass = slot.Read<kWithoutReadBarrier>();
- if (!fixup_adapter.IsInAppImage(klass)) {
+ if (!app_image_objects.InDest(klass)) {
continue;
}
const bool already_marked = visited_bitmap->Set(klass);
@@ -1311,12 +1298,12 @@
// Then patch the non-embedded vtable and iftable.
mirror::PointerArray* vtable = klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
if (vtable != nullptr &&
- fixup_object_visitor.IsInAppImage(vtable) &&
+ app_image_objects.InDest(vtable) &&
!visited_bitmap->Set(vtable)) {
patch_object_visitor.VisitPointerArray(vtable);
}
auto* iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
- if (iftable != nullptr && fixup_object_visitor.IsInAppImage(iftable)) {
+ if (iftable != nullptr && app_image_objects.InDest(iftable)) {
// Avoid processing the fields of iftable since we will process them later anyways
// below.
int32_t ifcount = klass->GetIfTableCount<kVerifyNone>();
@@ -1325,9 +1312,8 @@
iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
if (unpatched_ifarray != nullptr) {
// The iftable has not been patched, so we need to explicitly adjust the pointer.
- mirror::PointerArray* ifarray = fixup_adapter(unpatched_ifarray);
- if (fixup_object_visitor.IsInAppImage(ifarray) &&
- !visited_bitmap->Set(ifarray)) {
+ mirror::PointerArray* ifarray = forward_object(unpatched_ifarray);
+ if (app_image_objects.InDest(ifarray) && !visited_bitmap->Set(ifarray)) {
patch_object_visitor.VisitPointerArray(ifarray);
}
}
@@ -1342,14 +1328,14 @@
TimingLogger::ScopedTiming timing("Fixup objects", &logger);
ScopedObjectAccess soa(Thread::Current());
// Need to update the image to be at the target base.
- const ImageSection& objects_section = image_header.GetObjectsSection();
uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset());
uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End());
+ FixupObjectVisitor<ForwardObject> fixup_object_visitor(visited_bitmap.get(), forward_object);
bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
// Fixup image roots.
- CHECK(app_image.InSource(reinterpret_cast<uintptr_t>(
+ CHECK(app_image_objects.InSource(reinterpret_cast<uintptr_t>(
image_header.GetImageRoots<kWithoutReadBarrier>().Ptr())));
- image_header.RelocateImageObjects(app_image.Delta());
+ image_header.RelocateImageObjects(app_image_objects.Delta());
CHECK_EQ(image_header.GetImageBegin(), target_base);
// Fix up dex cache DexFile pointers.
auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)->
@@ -1363,27 +1349,26 @@
{
// Only touches objects in the app image, no need for mutator lock.
TimingLogger::ScopedTiming timing("Fixup methods", &logger);
- FixupArtMethodVisitor method_visitor(fixup_image,
- kPointerSize,
- boot_image,
- app_image,
- app_oat);
+ FixupArtMethodVisitor method_visitor(kPointerSize,
+ forward_object,
+ forward_metadata,
+ forward_code);
image_header.VisitPackedArtMethods(&method_visitor, target_base, kPointerSize);
}
if (fixup_image) {
{
// Only touches objects in the app image, no need for mutator lock.
TimingLogger::ScopedTiming timing("Fixup fields", &logger);
- FixupArtFieldVisitor field_visitor(boot_image, app_image, app_oat);
+ FixupArtFieldVisitor field_visitor(forward_object);
image_header.VisitPackedArtFields(&field_visitor, target_base);
}
{
TimingLogger::ScopedTiming timing("Fixup imt", &logger);
- image_header.VisitPackedImTables(fixup_adapter, target_base, kPointerSize);
+ image_header.VisitPackedImTables(forward_metadata, target_base, kPointerSize);
}
{
TimingLogger::ScopedTiming timing("Fixup conflict tables", &logger);
- image_header.VisitPackedImtConflictTables(fixup_adapter, target_base, kPointerSize);
+ image_header.VisitPackedImtConflictTables(forward_metadata, target_base, kPointerSize);
}
// In the app image case, the image methods are actually in the boot image.
image_header.RelocateImageMethods(boot_image.Delta());
@@ -1396,12 +1381,11 @@
InternTable temp_intern_table;
// Note that we require that ReadFromMemory does not make an internal copy of the elements
// so that the VisitRoots() will update the memory directly rather than the copies.
- FixupRootVisitor root_visitor(boot_image, app_image, app_oat);
temp_intern_table.AddTableFromMemory(target_base + intern_table_section.Offset(),
[&](InternTable::UnorderedSet& strings)
REQUIRES_SHARED(Locks::mutator_lock_) {
for (GcRoot<mirror::String>& root : strings) {
- root = GcRoot<mirror::String>(fixup_adapter(root.Read<kWithoutReadBarrier>()));
+ root = GcRoot<mirror::String>(forward_object(root.Read<kWithoutReadBarrier>()));
}
}, /*is_boot_image=*/ false);
}
@@ -1618,9 +1602,9 @@
"Marked objects",
spaces.front()->Begin(),
spaces.back()->End() - spaces.front()->Begin()));
- using PatchRelocateVisitor = PatchObjectVisitor<kPointerSize, RelocateVisitor>;
+ using PatchRelocateVisitor = PatchObjectVisitor<kPointerSize, RelocateVisitor, RelocateVisitor>;
RelocateVisitor relocate_visitor(diff);
- PatchRelocateVisitor patch_object_visitor(relocate_visitor);
+ PatchRelocateVisitor patch_object_visitor(relocate_visitor, relocate_visitor);
mirror::Class* dcheck_class_class = nullptr; // Used only for a DCHECK().
for (size_t s = 0u, size = spaces.size(); s != size; ++s) {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 14e364a..bb19097 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -17,7 +17,6 @@
#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
-#include "arch/instruction_set.h"
#include "gc/accounting/space_bitmap.h"
#include "image.h"
#include "space.h"
@@ -26,6 +25,7 @@
template <typename T> class ArrayRef;
class DexFile;
+enum class InstructionSet;
class OatFile;
namespace gc {
@@ -216,7 +216,7 @@
class PatchArtFieldVisitor;
template <PointerSize kPointerSize, typename PatchObjectVisitor, typename PatchCodeVisitor>
class PatchArtMethodVisitor;
- template <PointerSize kPointerSize, typename ReferenceVisitor>
+ template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
class PatchObjectVisitor;
DISALLOW_COPY_AND_ASSIGN(ImageSpace);
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index 14deb6f..262c6e0 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -23,13 +23,13 @@
#include "android-base/stringprintf.h"
#include "base/file_utils.h"
-#include "base/globals.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "runtime.h"
+#include "runtime_globals.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index b5e6b62..474231b 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -16,6 +16,8 @@
#include "malloc_space.h"
+#include <ostream>
+
#include "android-base/stringprintf.h"
#include "base/logging.h" // For VLOG
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 7d28516..9a90dfd 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -19,7 +19,8 @@
#include "space.h"
-#include <ostream>
+#include <iosfwd>
+
#include "base/memory_tool.h"
#include "base/mutex.h"
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index dd5451b..903263f 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -21,12 +21,12 @@
#include <string>
#include "base/atomic.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/mem_map.h"
#include "gc/accounting/space_bitmap.h"
#include "gc/collector/object_byte_pair.h"
+#include "runtime_globals.h"
namespace art {
namespace mirror {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 1b111e3..7fbd0b5 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -20,13 +20,13 @@
#include <stdint.h>
#include <memory>
-#include "base/globals.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "mirror/array-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
+#include "runtime_globals.h"
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "zygote_space.h"
diff --git a/runtime/gc/task_processor.h b/runtime/gc/task_processor.h
index 6db3c37..86e36ab 100644
--- a/runtime/gc/task_processor.h
+++ b/runtime/gc/task_processor.h
@@ -20,8 +20,8 @@
#include <memory>
#include <set>
-#include "base/globals.h"
#include "base/mutex.h"
+#include "runtime_globals.h"
#include "thread_pool.h"
namespace art {
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index f61c700..765ed7d 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -21,6 +21,7 @@
#include "base/mutex.h"
#include "handle.h"
+#include "handle_wrapper.h"
#include "obj_ptr-inl.h"
#include "thread-current-inl.h"
#include "verify_object.h"
@@ -106,6 +107,15 @@
handle_scope_entry <= &GetReferences()[number_of_references_ - 1];
}
+template <typename Visitor>
+inline void HandleScope::VisitRoots(Visitor& visitor) {
+ for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
+ // GetReference returns a pointer to the stack reference within the handle scope. If this
+ // needs to be updated, it will be done by the root visitor.
+ visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
+ }
+}
+
template<size_t kNumReferences> template<class T>
inline MutableHandle<T> FixedSizeHandleScope<kNumReferences>::NewHandle(T* object) {
SetReference(pos_, object);
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 6667aa3..ec1d166 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -24,13 +24,16 @@
#include "base/enums.h"
#include "base/locks.h"
#include "base/macros.h"
-#include "handle.h"
#include "stack_reference.h"
#include "verify_object.h"
namespace art {
+template<class T> class Handle;
class HandleScope;
+template<class T> class HandleWrapper;
+template<class T> class HandleWrapperObjPtr;
+template<class T> class MutableHandle;
template<class MirrorType> class ObjPtr;
class Thread;
class VariableSizedHandleScope;
@@ -144,13 +147,7 @@
}
template <typename Visitor>
- void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
- for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
- // GetReference returns a pointer to the stack reference within the handle scope. If this
- // needs to be updated, it will be done by the root visitor.
- visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
- }
- }
+ ALWAYS_INLINE void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
protected:
// Return backing storage used for references.
@@ -172,44 +169,6 @@
DISALLOW_COPY_AND_ASSIGN(HandleScope);
};
-// A wrapper which wraps around Object** and restores the pointer in the destructor.
-// TODO: Delete
-template<class T>
-class HandleWrapper : public MutableHandle<T> {
- public:
- HandleWrapper(T** obj, const MutableHandle<T>& handle)
- : MutableHandle<T>(handle), obj_(obj) {
- }
-
- HandleWrapper(const HandleWrapper&) = default;
-
- ~HandleWrapper() {
- *obj_ = MutableHandle<T>::Get();
- }
-
- private:
- T** const obj_;
-};
-
-
-// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
-// TODO: Add more functionality.
-template<class T>
-class HandleWrapperObjPtr : public MutableHandle<T> {
- public:
- HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
- : MutableHandle<T>(handle), obj_(obj) {}
-
- HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
-
- ~HandleWrapperObjPtr() {
- *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
- }
-
- private:
- ObjPtr<T>* const obj_;
-};
-
// Fixed size handle scope that is not necessarily linked in the thread.
template<size_t kNumReferences>
class PACKED(4) FixedSizeHandleScope : public HandleScope {
diff --git a/runtime/handle_wrapper.h b/runtime/handle_wrapper.h
new file mode 100644
index 0000000..01252c7
--- /dev/null
+++ b/runtime/handle_wrapper.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_HANDLE_WRAPPER_H_
+#define ART_RUNTIME_HANDLE_WRAPPER_H_
+
+#include "handle.h"
+#include "obj_ptr.h"
+
+namespace art {
+
+// A wrapper which wraps around Object** and restores the pointer in the destructor.
+// TODO: Delete
+template<class T>
+class HandleWrapper : public MutableHandle<T> {
+ public:
+ HandleWrapper(T** obj, const MutableHandle<T>& handle)
+ : MutableHandle<T>(handle), obj_(obj) {
+ }
+
+ HandleWrapper(const HandleWrapper&) = default;
+
+ ~HandleWrapper() {
+ *obj_ = MutableHandle<T>::Get();
+ }
+
+ private:
+ T** const obj_;
+};
+
+
+// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
+// TODO: Add more functionality.
+template<class T>
+class HandleWrapperObjPtr : public MutableHandle<T> {
+ public:
+ HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
+ : MutableHandle<T>(handle), obj_(obj) {}
+
+ HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
+
+ ~HandleWrapperObjPtr() {
+ *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
+ }
+
+ private:
+ ObjPtr<T>* const obj_;
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_HANDLE_WRAPPER_H_
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index c146daa..2d3493d 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -361,9 +361,11 @@
hiddenapi::ApiList api_list,
AccessMethod access_method) {
DCHECK(member != nullptr);
-
Runtime* runtime = Runtime::Current();
+
EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
+ DCHECK(policy != EnforcementPolicy::kDisabled)
+ << "Should never enter this function when access checks are completely disabled";
const bool deny_access =
(policy == EnforcementPolicy::kEnabled) &&
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index a0eeae2..1a5e010 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -311,6 +311,11 @@
return false;
}
+ // Exit early if access checks are completely disabled.
+ if (Runtime::Current()->GetHiddenApiEnforcementPolicy() == EnforcementPolicy::kDisabled) {
+ return false;
+ }
+
// Check if caller is exempted from access checks.
// This can be *very* expensive. Save it for last.
if (fn_get_access_context().IsTrusted()) {
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index 595f077..1f83c05 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -100,13 +100,6 @@
TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) {
ScopedObjectAccess soa(self_);
- runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
- ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
- ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
- ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
- ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
- ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), false);
-
runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kJustWarn);
ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 3abe4c5..34f645b 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -42,7 +42,6 @@
#include "art_method-inl.h"
#include "base/array_ref.h"
#include "base/file_utils.h"
-#include "base/globals.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "base/os.h"
@@ -66,6 +65,7 @@
#include "mirror/class-inl.h"
#include "mirror/class.h"
#include "mirror/object-refvisitor-inl.h"
+#include "runtime_globals.h"
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
diff --git a/runtime/image.h b/runtime/image.h
index 140f504..6578287 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -20,9 +20,9 @@
#include <string.h>
#include "base/enums.h"
-#include "base/globals.h"
#include "base/iteration_range.h"
#include "mirror/object.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 27c47bc..36f7b3d 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -848,7 +848,7 @@
new_quick_code = GetQuickInstrumentationEntryPoint();
if (!method->IsNative() && Runtime::Current()->GetJit() != nullptr) {
// Native methods use trampoline entrypoints during interpreter tracing.
- DCHECK(!Runtime::Current()->GetJit()->GetCodeCache()->GetGarbageCollectCode());
+ DCHECK(!Runtime::Current()->GetJit()->GetCodeCache()->GetGarbageCollectCodeUnsafe());
ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
// Tracing will look at the saved entry point in the profiling info to know the actual
// entrypoint, so we store it here.
@@ -1050,14 +1050,6 @@
level = InstrumentationLevel::kInstrumentWithInterpreter;
} else {
level = InstrumentationLevel::kInstrumentWithInstrumentationStubs;
- if (Runtime::Current()->GetJit() != nullptr) {
- // TODO b/110263880 It would be better if we didn't need to do this.
- // Since we need to hold the method entrypoint across a suspend to ensure instrumentation
- // hooks are called correctly we have to disable jit-gc to ensure that the entrypoint doesn't
- // go away. Furthermore we need to leave this off permanently since one could get the same
- // effect by causing this to be toggled on and off.
- Runtime::Current()->GetJit()->GetCodeCache()->SetGarbageCollectCode(false);
- }
}
ConfigureStubs(key, level);
}
diff --git a/runtime/jdwp_provider.h b/runtime/jdwp_provider.h
index 9579513..29fbc3f 100644
--- a/runtime/jdwp_provider.h
+++ b/runtime/jdwp_provider.h
@@ -19,7 +19,7 @@
#include <ios>
-#include "base/globals.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index d976fec..c1b9a1a 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -390,7 +390,7 @@
// Zygote should never collect code to share the memory with the children.
if (is_zygote) {
- jit_code_cache->SetGarbageCollectCode(false);
+ jit_code_cache->garbage_collect_code_ = false;
}
if (!jit_code_cache->InitializeMappings(rwx_memory_allowed, is_zygote, error_msg)) {
@@ -1247,6 +1247,24 @@
}
}
+void JitCodeCache::ClearEntryPointsInZygoteExecSpace() {
+ MutexLock mu(Thread::Current(), lock_);
+ // Iterate over profiling infos to know which methods may have been JITted. Note that
+ // to be JITted, a method must have a profiling info.
+ for (ProfilingInfo* info : profiling_infos_) {
+ ArtMethod* method = info->GetMethod();
+ if (IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode())) {
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ }
+ // If zygote does method tracing, or in some configuration where
+ // the JIT zygote does GC, we also need to clear the saved entry point
+ // in the profiling info.
+ if (IsInZygoteExecSpace(info->GetSavedEntryPoint())) {
+ info->SetSavedEntryPoint(nullptr);
+ }
+ }
+}
+
size_t JitCodeCache::CodeCacheSizeLocked() {
return used_memory_for_code_;
}
@@ -1437,17 +1455,14 @@
void JitCodeCache::GarbageCollectCache(Thread* self) {
ScopedTrace trace(__FUNCTION__);
- if (!garbage_collect_code_) {
- MutexLock mu(self, lock_);
- IncreaseCodeCacheCapacity();
- return;
- }
-
// Wait for an existing collection, or let everyone know we are starting one.
{
ScopedThreadSuspension sts(self, kSuspended);
MutexLock mu(self, lock_);
- if (WaitForPotentialCollectionToComplete(self)) {
+ if (!garbage_collect_code_) {
+ IncreaseCodeCacheCapacity();
+ return;
+ } else if (WaitForPotentialCollectionToComplete(self)) {
return;
} else {
number_of_collections_++;
@@ -1573,6 +1588,29 @@
FreeAllMethodHeaders(method_headers);
}
+bool JitCodeCache::GetGarbageCollectCode() {
+ MutexLock mu(Thread::Current(), lock_);
+ return garbage_collect_code_;
+}
+
+void JitCodeCache::SetGarbageCollectCode(bool value) {
+ Thread* self = Thread::Current();
+ MutexLock mu(self, lock_);
+ if (garbage_collect_code_ != value) {
+ if (garbage_collect_code_) {
+ // When dynamically disabling the garbage collection, we neee
+ // to make sure that a potential current collection is finished, and also
+ // clear the saved entry point in profiling infos to avoid dangling pointers.
+ WaitForPotentialCollectionToComplete(self);
+ for (ProfilingInfo* info : profiling_infos_) {
+ info->SetSavedEntryPoint(nullptr);
+ }
+ }
+ // Update the flag while holding the lock to ensure no thread will try to GC.
+ garbage_collect_code_ = value;
+ }
+}
+
void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
ScopedTrace trace(__FUNCTION__);
{
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index e2f3357..8a6cebe 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -246,13 +246,13 @@
void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method)
REQUIRES(!lock_) REQUIRES(Locks::mutator_lock_);
- // Dynamically change whether we want to garbage collect code. Should only be used during JIT
- // initialization or by tests.
- void SetGarbageCollectCode(bool value) {
- garbage_collect_code_ = value;
- }
+ // Dynamically change whether we want to garbage collect code.
+ void SetGarbageCollectCode(bool value) REQUIRES(!lock_);
- bool GetGarbageCollectCode() const {
+ bool GetGarbageCollectCode() REQUIRES(!lock_);
+
+ // Unsafe variant for debug checks.
+ bool GetGarbageCollectCodeUnsafe() const NO_THREAD_SAFETY_ANALYSIS {
return garbage_collect_code_;
}
@@ -264,6 +264,11 @@
void PostForkChildAction(bool is_system_server, bool is_zygote);
+ // Clear the entrypoints of JIT compiled methods that belong in the zygote space.
+ // This is used for removing non-debuggable JIT code at the point we realize the runtime
+ // is debuggable.
+ void ClearEntryPointsInZygoteExecSpace() REQUIRES(!lock_) REQUIRES(Locks::mutator_lock_);
+
private:
JitCodeCache();
@@ -451,7 +456,7 @@
bool last_collection_increased_code_cache_ GUARDED_BY(lock_);
// Whether we can do garbage collection. Not 'const' as tests may override this.
- bool garbage_collect_code_;
+ bool garbage_collect_code_ GUARDED_BY(lock_);
// The size in bytes of used memory for the data portion of the code cache.
size_t used_memory_for_data_ GUARDED_BY(lock_);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 40c7d30..fe49813 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -39,6 +39,7 @@
#include "runtime.h"
#include "string.h"
#include "subtype_check.h"
+#include "thread-current-inl.h"
namespace art {
namespace mirror {
@@ -1117,6 +1118,18 @@
}
}
+inline void Class::SetRecursivelyInitialized() {
+ DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
+ uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
+ SetAccessFlags(flags | kAccRecursivelyInitialized);
+}
+
+inline void Class::SetHasDefaultMethods() {
+ DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
+ uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
+ SetAccessFlags(flags | kAccHasDefaultMethod);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index f7a41f7..d35d526 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -30,7 +30,6 @@
#include "object.h"
#include "object_array.h"
#include "read_barrier_option.h"
-#include "thread-current-inl.h"
namespace art {
@@ -52,6 +51,7 @@
class Signature;
class StringPiece;
template<size_t kNumReferences> class PACKED(4) StackHandleScope;
+class Thread;
namespace mirror {
@@ -223,17 +223,9 @@
SetAccessFlags(flags | kAccSkipHiddenapiChecks);
}
- ALWAYS_INLINE void SetRecursivelyInitialized() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
- uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
- SetAccessFlags(flags | kAccRecursivelyInitialized);
- }
+ ALWAYS_INLINE void SetRecursivelyInitialized() REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE void SetHasDefaultMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
- uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
- SetAccessFlags(flags | kAccHasDefaultMethod);
- }
+ ALWAYS_INLINE void SetHasDefaultMethods() REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE void SetFinalizable() REQUIRES_SHARED(Locks::mutator_lock_) {
uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 8d2b838..7e79ebe 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -17,7 +17,6 @@
#include "dex_cache-inl.h"
#include "art_method-inl.h"
-#include "base/globals.h"
#include "class_linker.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
@@ -27,6 +26,7 @@
#include "object.h"
#include "object_array-inl.h"
#include "runtime.h"
+#include "runtime_globals.h"
#include "string.h"
#include "thread.h"
#include "utils/dex_cache_arrays_layout-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index bca7511..ba222f6 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -20,13 +20,13 @@
#include "base/atomic.h"
#include "base/casts.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "dex/primitive.h"
#include "obj_ptr.h"
#include "object_reference.h"
#include "offsets.h"
#include "read_barrier_config.h"
#include "read_barrier_option.h"
+#include "runtime_globals.h"
#include "verify_object.h"
namespace art {
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index 8636928..e19e165 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -18,10 +18,10 @@
#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
#include "base/atomic.h"
-#include "base/globals.h"
#include "base/locks.h" // For Locks::mutator_lock_.
#include "heap_poisoning.h"
#include "obj_ptr.h"
+#include "runtime_globals.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/string-alloc-inl.h b/runtime/mirror/string-alloc-inl.h
index c31eccf..4c4e2af 100644
--- a/runtime/mirror/string-alloc-inl.h
+++ b/runtime/mirror/string-alloc-inl.h
@@ -22,11 +22,11 @@
#include "array.h"
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "class.h"
#include "class_root.h"
#include "gc/heap-inl.h"
#include "runtime.h"
+#include "runtime_globals.h"
#include "thread.h"
namespace art {
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index e11906a..f04a8aa 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -20,10 +20,10 @@
#include "android-base/stringprintf.h"
-#include "base/globals.h"
#include "class-inl.h"
#include "common_throws.h"
#include "dex/utf.h"
+#include "runtime_globals.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index b32db08..c367957 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -18,10 +18,10 @@
#define ART_RUNTIME_MIRROR_STRING_H_
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "gc/allocator_type.h"
#include "class.h"
#include "object.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 9ce4749..26fc5e9 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -203,8 +203,11 @@
runtime->AddCompilerOption("--debuggable");
runtime_flags |= DEBUG_GENERATE_MINI_DEBUG_INFO;
runtime->SetJavaDebuggable(true);
- // Deoptimize the boot image as it may be non-debuggable.
- runtime->DeoptimizeBootImage();
+ {
+ // Deoptimize the boot image as it may be non-debuggable.
+ ScopedSuspendAll ssa(__FUNCTION__);
+ runtime->DeoptimizeBootImage();
+ }
runtime_flags &= ~DEBUG_JAVA_DEBUGGABLE;
needs_non_debuggable_classes = true;
}
diff --git a/runtime/oat.cc b/runtime/oat.cc
index d7c968f..c6a963a 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -20,6 +20,7 @@
#include "android-base/stringprintf.h"
+#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
#include "base/bit_utils.h"
#include "base/strlcpy.h"
diff --git a/runtime/oat.h b/runtime/oat.h
index ded1489..88238d9 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -19,13 +19,13 @@
#include <vector>
-#include "arch/instruction_set.h"
#include "base/macros.h"
#include "base/safe_map.h"
#include "compiler_filter.h"
namespace art {
+enum class InstructionSet;
class InstructionSetFeatures;
class PACKED(4) OatHeader {
diff --git a/runtime/obj_ptr-inl.h b/runtime/obj_ptr-inl.h
index b949c96..f096445 100644
--- a/runtime/obj_ptr-inl.h
+++ b/runtime/obj_ptr-inl.h
@@ -17,6 +17,8 @@
#ifndef ART_RUNTIME_OBJ_PTR_INL_H_
#define ART_RUNTIME_OBJ_PTR_INL_H_
+#include <ostream>
+
#include "base/bit_utils.h"
#include "obj_ptr.h"
#include "thread-current-inl.h"
diff --git a/runtime/obj_ptr.h b/runtime/obj_ptr.h
index 9e2ee29..b0f24da 100644
--- a/runtime/obj_ptr.h
+++ b/runtime/obj_ptr.h
@@ -17,12 +17,12 @@
#ifndef ART_RUNTIME_OBJ_PTR_H_
#define ART_RUNTIME_OBJ_PTR_H_
-#include <ostream>
+#include <iosfwd>
#include <type_traits>
-#include "base/globals.h"
#include "base/locks.h" // For Locks::mutator_lock_.
#include "base/macros.h"
+#include "runtime_globals.h"
// Always inline ObjPtr methods even in debug builds.
#define OBJPTR_INLINE __attribute__ ((always_inline))
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 372b821..6d1a8e0 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -17,10 +17,10 @@
#ifndef ART_RUNTIME_OFFSETS_H_
#define ART_RUNTIME_OFFSETS_H_
-#include <ostream>
+#include <iosfwd>
#include "base/enums.h"
-#include "base/globals.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 8c77d39..095d66e 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -23,10 +23,10 @@
#include <jni.h>
#include "arch/instruction_set.h"
-#include "base/globals.h"
#include "gc/collector_type.h"
#include "gc/space/large_object_space.h"
// #include "jit/profile_saver_options.h"
+#include "runtime_globals.h"
#include "runtime_options.h"
namespace art {
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 0d570c3..3bc718b 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -20,6 +20,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "base/logging.h" // For VLOG_IS_ON.
+#include "base/systrace.h"
#include "dex/dex_file_types.h"
#include "dex/dex_instruction.h"
#include "entrypoints/entrypoint_utils.h"
@@ -592,6 +593,10 @@
// Compiled code made an explicit deoptimization.
ArtMethod* deopt_method = visitor.GetSingleFrameDeoptMethod();
+ SCOPED_TRACE << "Deoptimizing "
+ << deopt_method->PrettyMethod()
+ << ": " << GetDeoptimizationKindName(kind);
+
DCHECK(deopt_method != nullptr);
if (VLOG_IS_ON(deopt) || kDebugExceptionDelivery) {
LOG(INFO) << "Single-frame deopting: "
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index dfd7e64..dbf40f6 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -33,6 +33,7 @@
#include "nth_caller_visitor.h"
#include "scoped_thread_state_change-inl.h"
#include "stack_reference.h"
+#include "thread-inl.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f30ba0c..d79793b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -42,6 +42,7 @@
#include "aot_class_linker.h"
#include "arch/arm/registers_arm.h"
#include "arch/arm64/registers_arm64.h"
+#include "arch/context.h"
#include "arch/instruction_set_features.h"
#include "arch/mips/registers_mips.h"
#include "arch/mips64/registers_mips64.h"
@@ -323,7 +324,6 @@
if (dump_gc_performance_on_shutdown_) {
heap_->CalculatePreGcWeightedAllocatedBytes();
- heap_->CalculatePostGcWeightedAllocatedBytes();
uint64_t process_cpu_end_time = ProcessCpuNanoTime();
ScopedLogSeverity sls(LogSeverity::INFO);
// This can't be called from the Heap destructor below because it
@@ -340,8 +340,12 @@
<< "\n";
double pre_gc_weighted_allocated_bytes =
heap_->GetPreGcWeightedAllocatedBytes() / process_cpu_time;
+ // Here we don't use process_cpu_time for normalization, because VM shutdown is not a real
+ // GC. Both numerator and denominator take into account until the end of the last GC,
+ // instead of the whole process life time like pre_gc_weighted_allocated_bytes.
double post_gc_weighted_allocated_bytes =
- heap_->GetPostGcWeightedAllocatedBytes() / process_cpu_time;
+ heap_->GetPostGcWeightedAllocatedBytes() /
+ (heap_->GetPostGCLastProcessCpuTime() - heap_->GetProcessCpuStartTime());
LOG_STREAM(INFO) << "Average bytes allocated at GC start, weighted by CPU time between GCs: "
<< static_cast<uint64_t>(pre_gc_weighted_allocated_bytes)
@@ -1472,6 +1476,8 @@
if (IsJavaDebuggable()) {
// Now that we have loaded the boot image, deoptimize its methods if we are running
// debuggable, as the code may have been compiled non-debuggable.
+ ScopedThreadSuspension sts(self, ThreadState::kNative);
+ ScopedSuspendAll ssa(__FUNCTION__);
DeoptimizeBootImage();
}
} else {
@@ -1571,10 +1577,14 @@
// Runtime initialization is largely done now.
// We load plugins first since that can modify the runtime state slightly.
// Load all plugins
- for (auto& plugin : plugins_) {
- std::string err;
- if (!plugin.Load(&err)) {
- LOG(FATAL) << plugin << " failed to load: " << err;
+ {
+ // The init method of plugins expect the state of the thread to be non runnable.
+ ScopedThreadSuspension sts(self, ThreadState::kNative);
+ for (auto& plugin : plugins_) {
+ std::string err;
+ if (!plugin.Load(&err)) {
+ LOG(FATAL) << plugin << " failed to load: " << err;
+ }
}
}
@@ -2647,6 +2657,7 @@
: instrumentation_(instrumentation) {}
bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES(Locks::mutator_lock_) {
+ DCHECK(Locks::mutator_lock_->IsExclusiveHeld(Thread::Current()));
auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
for (auto& m : klass->GetMethods(pointer_size)) {
const void* code = m.GetEntryPointFromQuickCompiledCode();
@@ -2673,9 +2684,13 @@
// we patch entry points of methods in boot image to interpreter bridge, as
// boot image code may be AOT compiled as not debuggable.
if (!GetInstrumentation()->IsForcedInterpretOnly()) {
- ScopedObjectAccess soa(Thread::Current());
UpdateEntryPointsClassVisitor visitor(GetInstrumentation());
GetClassLinker()->VisitClasses(&visitor);
+ jit::Jit* jit = GetJit();
+ if (jit != nullptr) {
+ // Code JITted by the zygote is not compiled debuggable.
+ jit->GetCodeCache()->ClearEntryPointsInZygoteExecSpace();
+ }
}
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index a2d519d..1acb75b 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -27,7 +27,6 @@
#include <memory>
#include <vector>
-#include "arch/instruction_set.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/mem_map.h"
@@ -84,6 +83,7 @@
class ClassLinker;
class CompilerCallbacks;
class DexFile;
+enum class InstructionSet;
class InternTable;
class IsMarkedVisitor;
class JavaVMExt;
@@ -634,7 +634,7 @@
void SetJavaDebuggable(bool value);
// Deoptimize the boot image, called for Java debuggable apps.
- void DeoptimizeBootImage();
+ void DeoptimizeBootImage() REQUIRES(Locks::mutator_lock_);
bool IsNativeDebuggable() const {
return is_native_debuggable_;
diff --git a/runtime/runtime_globals.h b/runtime/runtime_globals.h
new file mode 100644
index 0000000..793291a
--- /dev/null
+++ b/runtime/runtime_globals.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_RUNTIME_GLOBALS_H_
+#define ART_RUNTIME_RUNTIME_GLOBALS_H_
+
+#include "base/globals.h"
+
+namespace art {
+
+// Size of Dex virtual registers.
+static constexpr size_t kVRegSize = 4;
+
+// Returns whether the given memory offset can be used for generating
+// an implicit null check.
+static inline bool CanDoImplicitNullCheckOn(uintptr_t offset) {
+ return offset < kPageSize;
+}
+
+// Required object alignment
+static constexpr size_t kObjectAlignmentShift = 3;
+static constexpr size_t kObjectAlignment = 1u << kObjectAlignmentShift;
+static constexpr size_t kLargeObjectAlignment = kPageSize;
+
+// Garbage collector constants.
+static constexpr bool kMovingCollector = true;
+static constexpr bool kMarkCompactSupport = false && kMovingCollector;
+// True if we allow moving classes.
+static constexpr bool kMovingClasses = !kMarkCompactSupport;
+// If true, enable generational collection when using the Concurrent Copying
+// (CC) collector, i.e. use sticky-bit CC for minor collections and (full) CC
+// for major collections.
+//
+// Generational CC collection is currently only compatible with Baker read
+// barriers.
+#if defined(ART_USE_GENERATIONAL_CC) && defined(ART_READ_BARRIER_TYPE_IS_BAKER)
+static constexpr bool kEnableGenerationalConcurrentCopyingCollection = true;
+#else
+static constexpr bool kEnableGenerationalConcurrentCopyingCollection = false;
+#endif
+
+// If true, enable the tlab allocator by default.
+#ifdef ART_USE_TLAB
+static constexpr bool kUseTlab = true;
+#else
+static constexpr bool kUseTlab = false;
+#endif
+
+// Kinds of tracing clocks.
+enum class TraceClockSource {
+ kThreadCpu,
+ kWall,
+ kDual, // Both wall and thread CPU clocks.
+};
+
+#if defined(__linux__)
+static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kDual;
+#else
+static constexpr TraceClockSource kDefaultTraceClockSource = TraceClockSource::kWall;
+#endif
+
+static constexpr bool kDefaultMustRelocate = true;
+
+// Size of a heap reference.
+static constexpr size_t kHeapReferenceSize = sizeof(uint32_t);
+
+} // namespace art
+
+#endif // ART_RUNTIME_RUNTIME_GLOBALS_H_
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 25939d2..9a677de 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -568,7 +568,9 @@
cur_shadow_frame_->SetMethod(method);
} else {
DCHECK(cur_quick_frame_ != nullptr);
- CHECK(!IsInInlinedFrame()) << "We do not support setting inlined method's ArtMethod!";
+ CHECK(!IsInInlinedFrame()) << "We do not support setting inlined method's ArtMethod: "
+ << GetMethod()->PrettyMethod() << " is inlined into "
+ << GetOuterMethod()->PrettyMethod();
*cur_quick_frame_ = method;
}
}
diff --git a/runtime/suspend_reason.h b/runtime/suspend_reason.h
index 289a1a4..af2be10 100644
--- a/runtime/suspend_reason.h
+++ b/runtime/suspend_reason.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_SUSPEND_REASON_H_
#define ART_RUNTIME_SUSPEND_REASON_H_
-#include <ostream>
+#include <iosfwd>
namespace art {
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 0c00fb9..00f882e 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -19,6 +19,7 @@
#include "thread.h"
+#include "arch/instruction_set.h"
#include "base/aborting.h"
#include "base/casts.h"
#include "base/mutex-inl.h"
@@ -393,6 +394,26 @@
return tlsPtr_.managed_stack.PopShadowFrame();
}
+inline uint8_t* Thread::GetStackEndForInterpreter(bool implicit_overflow_check) const {
+ uint8_t* end = tlsPtr_.stack_end + (implicit_overflow_check
+ ? GetStackOverflowReservedBytes(kRuntimeISA)
+ : 0);
+ if (kIsDebugBuild) {
+ // In a debuggable build, but especially under ASAN, the access-checks interpreter has a
+ // potentially humongous stack size. We don't want to take too much of the stack regularly,
+ // so do not increase the regular reserved size (for compiled code etc) and only report the
+ // virtually smaller stack to the interpreter here.
+ end += GetStackOverflowReservedBytes(kRuntimeISA);
+ }
+ return end;
+}
+
+inline void Thread::ResetDefaultStackEnd() {
+ // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room
+ // to throw a StackOverflowError.
+ tlsPtr_.stack_end = tlsPtr_.stack_begin + GetStackOverflowReservedBytes(kRuntimeISA);
+}
+
} // namespace art
#endif // ART_RUNTIME_THREAD_INL_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7c050a4..309c04e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -48,6 +48,7 @@
#include "base/atomic.h"
#include "base/bit_utils.h"
#include "base/casts.h"
+#include "arch/context.h"
#include "base/file_utils.h"
#include "base/memory_tool.h"
#include "base/mutex.h"
@@ -4232,4 +4233,17 @@
Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
}
+void Thread::ReleaseLongJumpContextInternal() {
+ // Each QuickExceptionHandler gets a long jump context and uses
+ // it for doing the long jump, after finding catch blocks/doing deoptimization.
+ // Both finding catch blocks and deoptimization can trigger another
+ // exception such as a result of class loading. So there can be nested
+ // cases of exception handling and multiple contexts being used.
+ // ReleaseLongJumpContext tries to save the context in tlsPtr_.long_jump_context
+ // for reuse so there is no need to always allocate a new one each time when
+ // getting a context. Since we only keep one context for reuse, delete the
+ // existing one since the passed in context is yet to be used for longjump.
+ delete tlsPtr_.long_jump_context;
+}
+
} // namespace art
diff --git a/runtime/thread.h b/runtime/thread.h
index ad69ecf..7a14fd7 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -25,14 +25,12 @@
#include <memory>
#include <string>
-#include "arch/context.h"
-#include "arch/instruction_set.h"
#include "base/atomic.h"
#include "base/enums.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/safe_map.h"
+#include "base/value_object.h"
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "handle_scope.h"
@@ -41,6 +39,7 @@
#include "managed_stack.h"
#include "offsets.h"
#include "read_barrier_config.h"
+#include "runtime_globals.h"
#include "runtime_stats.h"
#include "suspend_reason.h"
#include "thread_state.h"
@@ -471,16 +470,7 @@
Context* GetLongJumpContext();
void ReleaseLongJumpContext(Context* context) {
if (tlsPtr_.long_jump_context != nullptr) {
- // Each QuickExceptionHandler gets a long jump context and uses
- // it for doing the long jump, after finding catch blocks/doing deoptimization.
- // Both finding catch blocks and deoptimization can trigger another
- // exception such as a result of class loading. So there can be nested
- // cases of exception handling and multiple contexts being used.
- // ReleaseLongJumpContext tries to save the context in tlsPtr_.long_jump_context
- // for reuse so there is no need to always allocate a new one each time when
- // getting a context. Since we only keep one context for reuse, delete the
- // existing one since the passed in context is yet to be used for longjump.
- delete tlsPtr_.long_jump_context;
+ ReleaseLongJumpContextInternal();
}
tlsPtr_.long_jump_context = context;
}
@@ -819,19 +809,7 @@
return tlsPtr_.stack_size - (tlsPtr_.stack_end - tlsPtr_.stack_begin);
}
- uint8_t* GetStackEndForInterpreter(bool implicit_overflow_check) const {
- uint8_t* end = tlsPtr_.stack_end + (implicit_overflow_check
- ? GetStackOverflowReservedBytes(kRuntimeISA)
- : 0);
- if (kIsDebugBuild) {
- // In a debuggable build, but especially under ASAN, the access-checks interpreter has a
- // potentially humongous stack size. We don't want to take too much of the stack regularly,
- // so do not increase the regular reserved size (for compiled code etc) and only report the
- // virtually smaller stack to the interpreter here.
- end += GetStackOverflowReservedBytes(kRuntimeISA);
- }
- return end;
- }
+ ALWAYS_INLINE uint8_t* GetStackEndForInterpreter(bool implicit_overflow_check) const;
uint8_t* GetStackEnd() const {
return tlsPtr_.stack_end;
@@ -841,11 +819,7 @@
void SetStackEndForStackOverflow() REQUIRES_SHARED(Locks::mutator_lock_);
// Set the stack end to that to be used during regular execution
- void ResetDefaultStackEnd() {
- // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room
- // to throw a StackOverflowError.
- tlsPtr_.stack_end = tlsPtr_.stack_begin + GetStackOverflowReservedBytes(kRuntimeISA);
- }
+ ALWAYS_INLINE void ResetDefaultStackEnd();
bool IsHandlingStackOverflow() const {
return tlsPtr_.stack_end == tlsPtr_.stack_begin;
@@ -1425,6 +1399,8 @@
static bool IsAotCompiler();
+ void ReleaseLongJumpContextInternal();
+
// 32 bits of atomically changed state and flags. Keeping as 32 bits allows and atomic CAS to
// change from being Suspended to Runnable without a suspend request occurring.
union PACKED(4) StateAndFlags {
diff --git a/runtime/thread_state.h b/runtime/thread_state.h
index 8edfeec..e57a040 100644
--- a/runtime/thread_state.h
+++ b/runtime/thread_state.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_THREAD_STATE_H_
#define ART_RUNTIME_THREAD_STATE_H_
-#include <ostream>
+#include <iosfwd>
namespace art {
diff --git a/runtime/trace.cc b/runtime/trace.cc
index ce955d8..074e846 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -38,6 +38,8 @@
#include "entrypoints/quick/quick_entrypoints.h"
#include "gc/scoped_gc_critical_section.h"
#include "instrumentation.h"
+#include "jit/jit.h"
+#include "jit/jit_code_cache.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
@@ -390,6 +392,15 @@
// Enable count of allocs if specified in the flags.
bool enable_stats = false;
+ if (runtime->GetJit() != nullptr) {
+ // TODO b/110263880 It would be better if we didn't need to do this.
+ // Since we need to hold the method entrypoint across a suspend to ensure instrumentation
+ // hooks are called correctly we have to disable jit-gc to ensure that the entrypoint doesn't
+ // go away. Furthermore we need to leave this off permanently since one could get the same
+ // effect by causing this to be toggled on and off.
+ runtime->GetJit()->GetCodeCache()->SetGarbageCollectCode(false);
+ }
+
// Create Trace object.
{
// Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes.
diff --git a/runtime/trace.h b/runtime/trace.h
index 582f756..567f6ed 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -27,12 +27,12 @@
#include <vector>
#include "base/atomic.h"
-#include "base/globals.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/os.h"
#include "base/safe_map.h"
#include "instrumentation.h"
+#include "runtime_globals.h"
namespace unix_file {
class FdFile;
diff --git a/runtime/utils/dex_cache_arrays_layout-inl.h b/runtime/utils/dex_cache_arrays_layout-inl.h
index c0ea6be..3512efe 100644
--- a/runtime/utils/dex_cache_arrays_layout-inl.h
+++ b/runtime/utils/dex_cache_arrays_layout-inl.h
@@ -22,10 +22,10 @@
#include <android-base/logging.h>
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "dex/primitive.h"
#include "gc_root.h"
#include "mirror/dex_cache.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1679821..91eba21 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2654,6 +2654,7 @@
// See if instance-of was preceded by a move-object operation, common due to the small
// register encoding space of instance-of, and propagate type information to the source
// of the move-object.
+ // Note: this is only valid if the move source was not clobbered.
uint32_t move_idx = instance_of_idx - 1;
while (0 != move_idx && !GetInstructionFlags(move_idx).IsOpcode()) {
move_idx--;
@@ -2663,28 +2664,25 @@
work_insn_idx_)) {
break;
}
+ auto maybe_update_fn = [&instance_of_inst, update_line, this, &cast_type](
+ uint16_t move_src,
+ uint16_t move_trg)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (move_trg == instance_of_inst.VRegB_22c() &&
+ move_src != instance_of_inst.VRegA_22c()) {
+ update_line->SetRegisterType<LockOp::kKeep>(this, move_src, cast_type);
+ }
+ };
const Instruction& move_inst = code_item_accessor_.InstructionAt(move_idx);
switch (move_inst.Opcode()) {
case Instruction::MOVE_OBJECT:
- if (move_inst.VRegA_12x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_12x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_12x(), move_inst.VRegA_12x());
break;
case Instruction::MOVE_OBJECT_FROM16:
- if (move_inst.VRegA_22x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_22x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_22x(), move_inst.VRegA_22x());
break;
case Instruction::MOVE_OBJECT_16:
- if (move_inst.VRegA_32x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_32x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_32x(), move_inst.VRegA_32x());
break;
default:
break;
diff --git a/runtime/verify_object.cc b/runtime/verify_object.cc
index 70ca13f..2b8c7da 100644
--- a/runtime/verify_object.cc
+++ b/runtime/verify_object.cc
@@ -17,11 +17,11 @@
#include "verify_object-inl.h"
#include "base/bit_utils.h"
-#include "base/globals.h"
#include "gc/heap.h"
#include "mirror/object-inl.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
+#include "runtime_globals.h"
namespace art {
diff --git a/test/1001-app-image-regions/app_image_regions.cc b/test/1001-app-image-regions/app_image_regions.cc
new file mode 100644
index 0000000..dc16a84
--- /dev/null
+++ b/test/1001-app-image-regions/app_image_regions.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 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"
+
+#include "gc/heap.h"
+#include "gc/space/image_space.h"
+#include "gc/space/space-inl.h"
+#include "gc/space/region_space.h"
+#include "image.h"
+#include "mirror/class.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+
+namespace art {
+
+namespace {
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getRegionSize(JNIEnv*, jclass) {
+ return gc::space::RegionSpace::kRegionSize;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_checkAppImageSectionSize(JNIEnv*, jclass, jclass c) {
+ ScopedObjectAccess soa(Thread::Current());
+ ObjPtr<mirror::Class> klass_ptr = soa.Decode<mirror::Class>(c);
+ for (auto* space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) {
+ if (space->IsImageSpace()) {
+ auto* image_space = space->AsImageSpace();
+ const auto& image_header = image_space->GetImageHeader();
+ if (image_header.IsAppImage() && image_space->HasAddress(klass_ptr.Ptr())) {
+ return image_header.GetObjectsSection().Size();
+ }
+ }
+ }
+ return 0;
+}
+
+} // namespace
+
+} // namespace art
diff --git a/test/1001-app-image-regions/build b/test/1001-app-image-regions/build
new file mode 100755
index 0000000..16c3a5b
--- /dev/null
+++ b/test/1001-app-image-regions/build
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright 2019 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.
+
+# make us exit on a failure
+set -e
+
+count=10000
+echo "LMain;" >> profile
+for i in $(seq 1 "$count"); do
+ echo "LOther\$Inner${i};" >> "profile"
+done
+
+# Generate the other class.
+other_file="src/Other.java"
+echo "class Other {" >> "${other_file}"
+for i in $(seq 1 "$count"); do
+ echo " static class Inner${i} { void test(){} }" >> "${other_file}"
+done
+echo "}" >> "${other_file}"
+
+./default-build "$@"
diff --git a/test/1001-app-image-regions/expected.txt b/test/1001-app-image-regions/expected.txt
new file mode 100644
index 0000000..9fd87ca
--- /dev/null
+++ b/test/1001-app-image-regions/expected.txt
@@ -0,0 +1,4 @@
+JNI_OnLoad called
+App image loaded true
+Region size 262144
+App image section size large enough true
diff --git a/test/1001-app-image-regions/info.txt b/test/1001-app-image-regions/info.txt
new file mode 100644
index 0000000..b13f276
--- /dev/null
+++ b/test/1001-app-image-regions/info.txt
@@ -0,0 +1 @@
+Tests that an app image with many classes is generated and loaded correctly.
diff --git a/test/1001-app-image-regions/run b/test/1001-app-image-regions/run
new file mode 100644
index 0000000..128aa2e
--- /dev/null
+++ b/test/1001-app-image-regions/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+exec ${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile
diff --git a/test/1001-app-image-regions/src/Main.java b/test/1001-app-image-regions/src/Main.java
new file mode 100644
index 0000000..c41a606
--- /dev/null
+++ b/test/1001-app-image-regions/src/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 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.
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+class Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+ System.out.println("App image loaded " + checkAppImageLoaded());
+ int regionSize = getRegionSize();
+ int objectsSectionSize = checkAppImageSectionSize(Main.class);
+ System.out.println("Region size " + regionSize);
+ System.out.println("App image section size large enough " + (objectsSectionSize > regionSize));
+ if (objectsSectionSize <= regionSize) {
+ System.out.println("Section size " + objectsSectionSize);
+ }
+ }
+
+ public static native boolean checkAppImageLoaded();
+ public static native int getRegionSize();
+ public static native int checkAppImageSectionSize(Class c);
+}
diff --git a/test/689-multi-catch/expected.txt b/test/689-multi-catch/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/689-multi-catch/expected.txt
diff --git a/test/689-multi-catch/info.txt b/test/689-multi-catch/info.txt
new file mode 100644
index 0000000..0778ea8
--- /dev/null
+++ b/test/689-multi-catch/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimizing compiler which used
+to wrongly type an exception in a multi-catch handler.
diff --git a/test/689-multi-catch/src/Main.java b/test/689-multi-catch/src/Main.java
new file mode 100644
index 0000000..18a17f9
--- /dev/null
+++ b/test/689-multi-catch/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 Main {
+ public static void main(String[] args) {
+ try {
+ willThrow();
+ } catch (IllegalStateException | NullPointerException e) {
+ if (e instanceof NullPointerException) {
+ return;
+ }
+ throw new Error("Expected NullPointerException");
+ }
+ }
+
+ public static void willThrow() {
+ throw new NullPointerException();
+ }
+}
diff --git a/test/689-zygote-jit-deopt/expected.txt b/test/689-zygote-jit-deopt/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/689-zygote-jit-deopt/info.txt b/test/689-zygote-jit-deopt/info.txt
new file mode 100644
index 0000000..100032e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/info.txt
@@ -0,0 +1,2 @@
+Regression test for debuggable apps that need to deoptimize
+methods JIT-compiled by the zygote.
diff --git a/test/689-zygote-jit-deopt/src/Main.java b/test/689-zygote-jit-deopt/src/Main.java
new file mode 100644
index 0000000..330663e
--- /dev/null
+++ b/test/689-zygote-jit-deopt/src/Main.java
@@ -0,0 +1,36 @@
+/*
+ * 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 Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+ if (!hasJit()) {
+ return;
+ }
+ ensureJitCompiled(Object.class, "toString");
+ transitionJitFromZygote();
+ deoptimizeBootImage();
+ if (hasJitCompiledEntrypoint(Object.class, "toString")) {
+ throw new Error("Expected Object.toString to be deoptimized");
+ }
+ }
+
+ private static native boolean hasJit();
+ private static native void ensureJitCompiled(Class<?> cls, String name);
+ private static native boolean hasJitCompiledEntrypoint(Class<?> cls, String name);
+ private static native void deoptimizeBootImage();
+ private static native void transitionJitFromZygote();
+}
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index f3c3f03..291de72 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -73,4 +73,5 @@
b/30458218
b/31313170
ConstClassAliasing
+b/121191566
Done!
diff --git a/test/800-smali/smali/b_121191566.smali b/test/800-smali/smali/b_121191566.smali
new file mode 100644
index 0000000..bcf9ef5
--- /dev/null
+++ b/test/800-smali/smali/b_121191566.smali
@@ -0,0 +1,26 @@
+.class public LB121191566;
+.super Ljava/lang/Object;
+
+
+.method public constructor <init>()V
+.registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public static run(Ljava/lang/Object;)Z
+.registers 5
+ move-object v3, v4
+ instance-of v4, v3, Ljava/lang/String;
+ if-eqz v4, :Branch
+ # The peephole must not overwrite v4 (from the move-object). Use an integral move
+ # to check.
+ move v0, v4
+ goto :End
+:Branch
+ # See above.
+ move v0, v4
+:End
+ # Triple-check: the merge should be consistent.
+ return v0
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 9b06e9e..d7979e1 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -193,6 +193,8 @@
testCases.add(new TestCase("b/31313170", "B31313170", "run", null, null, 0));
testCases.add(new TestCase("ConstClassAliasing", "ConstClassAliasing", "run", null, null,
null, true));
+ testCases.add(new TestCase("b/121191566", "B121191566", "run", new Object[] { "a" }, null,
+ true, false));
}
public void runTests() {
diff --git a/test/Android.bp b/test/Android.bp
index 57fcd86..467a717 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -495,6 +495,7 @@
"708-jit-cache-churn/jit.cc",
"800-smali/jni.cc",
"909-attach-agent/disallow_debugging.cc",
+ "1001-app-image-regions/app_image_regions.cc",
"1947-breakpoint-redefine-deopt/check_deopt.cc",
"common/runtime_state.cc",
"common/stack_inspect.cc",
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 55631a9..bbc3039 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -161,6 +161,19 @@
return !interpreter;
}
+static ArtMethod* GetMethod(ScopedObjectAccess& soa, jclass cls, const ScopedUtfChars& chars)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ CHECK(chars.c_str() != nullptr);
+ ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
+ chars.c_str(), kRuntimePointerSize);
+ if (method == nullptr) {
+ method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
+ chars.c_str(), kRuntimePointerSize);
+ }
+ DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str();
+ return method;
+}
+
extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledEntrypoint(JNIEnv* env,
jclass,
jclass cls,
@@ -172,9 +185,7 @@
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
ScopedUtfChars chars(env, method_name);
- CHECK(chars.c_str() != nullptr);
- ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
- chars.c_str(), kRuntimePointerSize);
+ ArtMethod* method = GetMethod(soa, cls, chars);
ScopedAssertNoThreadSuspension sants(__FUNCTION__);
return jit->GetCodeCache()->ContainsPc(
Runtime::Current()->GetInstrumentation()->GetCodeForInvoke(method));
@@ -191,9 +202,7 @@
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
ScopedUtfChars chars(env, method_name);
- CHECK(chars.c_str() != nullptr);
- ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
- chars.c_str(), kRuntimePointerSize);
+ ArtMethod* method = GetMethod(soa, cls, chars);
return jit->GetCodeCache()->ContainsMethod(method);
}
@@ -262,14 +271,7 @@
ScopedObjectAccess soa(self);
ScopedUtfChars chars(env, method_name);
- CHECK(chars.c_str() != nullptr);
- method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
- chars.c_str(), kRuntimePointerSize);
- if (method == nullptr) {
- method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
- chars.c_str(), kRuntimePointerSize);
- }
- DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str();
+ method = GetMethod(soa, cls, chars);
}
ForceJitCompiled(self, method);
}
@@ -353,4 +355,20 @@
return (jit != nullptr) ? jit->HotMethodThreshold() : 0;
}
+extern "C" JNIEXPORT void JNICALL Java_Main_transitionJitFromZygote(JNIEnv*, jclass) {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit == nullptr) {
+ return;
+ }
+ // Mimic the transition behavior a zygote fork would have.
+ jit->PreZygoteFork();
+ jit->GetCodeCache()->PostForkChildAction(/*is_system_server=*/ false, /*is_zygote=*/ false);
+ jit->PostForkChildAction(/*is_zygote=*/ false);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_deoptimizeBootImage(JNIEnv*, jclass) {
+ ScopedSuspendAll ssa(__FUNCTION__);
+ Runtime::Current()->DeoptimizeBootImage();
+}
+
} // namespace art
diff --git a/test/common/stack_inspect.cc b/test/common/stack_inspect.cc
index 393e773..cb011a8 100644
--- a/test/common/stack_inspect.cc
+++ b/test/common/stack_inspect.cc
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
+#include "arch/context.h"
#include "base/mutex.h"
#include "dex/dex_file-inl.h"
#include "jni/jni_internal.h"
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 25b8b4b..3074763 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -319,6 +319,10 @@
shift
ANDROID_ROOT="$1"
shift
+ elif [ "x$1" = "x--android-runtime-root" ]; then
+ shift
+ ANDROID_RUNTIME_ROOT="$1"
+ shift
elif [ "x$1" = "x--instruction-set-features" ]; then
shift
INSTRUCTION_SET_FEATURES="$1"
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 983c16a..9c01ba9 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -81,11 +81,13 @@
"variant": "no-prebuild"
},
{
- "tests": ["118-noimage-dex2oat"],
+ "tests": ["118-noimage-dex2oat",
+ "1001-app-image-regions"],
"variant": "no-relocate",
"description": ["118-noimage-dex2oat is not broken per-se it just ",
"doesn't work (and isn't meant to) without --prebuild ",
- "--relocate"]
+ "--relocate. 1001-app-image-regions is disabled since it",
+ "doesn't have the app image loaded for no-relocate"]
},
{
"tests" : "629-vdex-speed",
@@ -1085,6 +1087,7 @@
"688-shared-library",
"999-redefine-hiddenapi",
"1000-non-moving-space-stress",
+ "1001-app-image-regions",
"1951-monitor-enter-no-suspend",
"1957-error-ext"],
"variant": "jvm",
diff --git a/test/run-test b/test/run-test
index 83c726e..67bcce7 100755
--- a/test/run-test
+++ b/test/run-test
@@ -386,6 +386,15 @@
android_root="$1"
run_args="${run_args} --android-root $1"
shift
+ elif [ "x$1" = "x--android-runtime-root" ]; then
+ shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --android-runtime-root" 1>&2
+ usage="yes"
+ break
+ fi
+ run_args="${run_args} --android-runtime-root $1"
+ shift
elif [ "x$1" = "x--update" ]; then
update_mode="yes"
shift
@@ -758,6 +767,9 @@
echo " --never-clean Keep the test files even if the test succeeds."
echo " --chroot [newroot] Run with root directory set to newroot."
echo " --android-root [path] The path on target for the android root. (/system by default)."
+ echo " --android-runtime-root [path]"
+ echo " The path on target for the Android Runtime root."
+ echo " (/apex/com.android.runtime by default)."
echo " --dex2oat-swap Use a dex2oat swap file."
echo " --instruction-set-features [string]"
echo " Set instruction-set-features for compilation."
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 1f4b829..c2d5e7d 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -89,8 +89,8 @@
HOST_2ND_ARCH_PREFIX + 'DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
ART_TEST_CHROOT = _env.get('ART_TEST_CHROOT')
-
ART_TEST_ANDROID_ROOT = _env.get('ART_TEST_ANDROID_ROOT')
+ART_TEST_ANDROID_RUNTIME_ROOT = _env.get('ART_TEST_ANDROID_RUNTIME_ROOT')
ART_TEST_WITH_STRACE = _getEnvBoolean('ART_TEST_DEBUG_GC', False)
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 4e873c1..0456fdb 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -400,12 +400,15 @@
elif target == 'jvm':
options_test += ' --jvm'
- # Honor ART_TEST_CHROOT and ART_TEST_ANDROID_ROOT, but only for target tests.
+ # Honor ART_TEST_CHROOT, ART_TEST_ANDROID_ROOT and ART_TEST_ANDROID_RUNTIME_ROOT,
+ # but only for target tests.
if target == 'target':
if env.ART_TEST_CHROOT:
options_test += ' --chroot ' + env.ART_TEST_CHROOT
if env.ART_TEST_ANDROID_ROOT:
options_test += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
+ if env.ART_TEST_ANDROID_RUNTIME_ROOT:
+ options_test += ' --android-runtime-root ' + env.ART_TEST_ANDROID_RUNTIME_ROOT
if run == 'ndebug':
options_test += ' -O'
diff --git a/tools/art b/tools/art
index eeb7c68..2c28807 100644
--- a/tools/art
+++ b/tools/art
@@ -199,6 +199,7 @@
# (see run_art function)
verbose_run ANDROID_DATA=$ANDROID_DATA \
ANDROID_ROOT=$ANDROID_ROOT \
+ ANDROID_RUNTIME_ROOT=$ANDROID_RUNTIME_ROOT \
LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
PATH=$ANDROID_ROOT/bin:$PATH \
LD_USE_LOAD_BIAS=1 \
@@ -222,6 +223,8 @@
# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
+# -Xbootclasspath argument is stored in DEX2OAT_BCP
+# -Xbootclasspath-locations argument is stored in DEX2OAT_BCP_LOCS
function extract_dex2oat_flags() {
while [ $# -gt 0 ]; do
case $1 in
@@ -234,6 +237,16 @@
# Remove '-Ximage:' from the argument.
DEX2OAT_BOOT_IMAGE=${DEX2OAT_BOOT_IMAGE##-Ximage:}
;;
+ -Xbootclasspath:*)
+ DEX2OAT_BCP=$1
+ # Remove '-Xbootclasspath:' from the argument.
+ DEX2OAT_BCP=${DEX2OAT_BCP##-Xbootclasspath:}
+ ;;
+ -Xbootclasspath-locations:*)
+ DEX2OAT_BCP_LOCS=$1
+ # Remove '-Xbootclasspath-locations:' from the argument.
+ DEX2OAT_BCP_LOCS=${DEX2OAT_BCP_LOCS##-Xbootclasspath-locations:}
+ ;;
-cp)
# Reset any previously parsed classpath, just like dalvikvm
# only supports one -cp argument.
@@ -386,8 +399,42 @@
done
PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-ANDROID_ROOT=$PROG_DIR/..
-ANDROID_RUNTIME_ROOT=$ANDROID_ROOT/com.android.runtime
+ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
+
+# If ANDROID_RUNTIME_ROOT is not set, try to detect whether we are running on
+# target or host and set that environment variable to the usual default value.
+if [ -z "$ANDROID_RUNTIME_ROOT" ]; then
+ # This script is used on host and target (device). However, the (expected)
+ # default value `ANDROID_RUNTIME_ROOT` is not the same on host and target:
+ # - on host, `ANDROID_RUNTIME_ROOT` is expected to be "$ANDROID_ROOT/com.android.apex";
+ # - on target, `ANDROID_RUNTIME_ROOT` is expected to be "$ANDROID_ROOT/../apex/com.android.apex".
+ #
+ # We use the presence/absence of the `$ANDROID_ROOT/../apex` directory to
+ # determine whether we are on target or host (this is brittle, but simple).
+ if [ -d "$ANDROID_ROOT/../apex" ]; then
+ # Target case.
+ #
+ # We should be setting `ANDROID_RUNTIME_ROOT` to
+ # "$ANDROID_ROOT/../apex/com.android.runtime" here. However, the Runtime APEX
+ # is not (yet) supported by the ART Buildbot setup (see b/121117762); and yet
+ # ICU code depends on `ANDROID_RUNTIME_ROOT` to find ICU .dat files.
+ #
+ # As a temporary workaround, we:
+ # - make the ART Buildbot build script (art/tools/buildbot-build.sh) also
+ # generate the ICU .dat files in `/system/etc/icu` on device (these files
+ # are normally only put in the Runtime APEX on device);
+ # - set `ANDROID_RUNTIME_ROOT` to `$ANDROID_ROOT` (i.e. "/system") here.
+ #
+ # TODO(b/121117762): Set `ANDROID_RUNTIME_ROOT` to
+ # "$ANDROID_ROOT/../apex/com.android.runtime" when the Runtime APEX is fully
+ # supported on the ART Buildbot and Golem.
+ ANDROID_RUNTIME_ROOT=$ANDROID_ROOT
+ else
+ # Host case.
+ ANDROID_RUNTIME_ROOT="$ANDROID_ROOT/com.android.runtime"
+ fi
+fi
+
ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
if [ ! -x "$ART_BINARY_PATH" ]; then
@@ -422,7 +469,7 @@
# Extract the dex2oat flags from the list of arguments.
# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array
# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH
-# -Ximage argument is stored in DEX2OAT_BOOTIMAGE
+# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE
extract_dex2oat_flags "$@"
# If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own,
@@ -439,6 +486,55 @@
DELETE_ANDROID_DATA="yes"
fi
+if [[ "$DEX2OAT_BCP" = "" && "$DEX2OAT_BCP_LOCS" != "" ]]; then
+ echo "Cannot use -Xbootclasspath-locations without -Xbootclasspath"
+ exit 1
+fi
+
+if [[ "$DEX2OAT_BOOT_IMAGE" = *core*.art && "$DEX2OAT_BCP" = "" ]]; then
+ # Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
+ # because that's what we use for compiling the core.art image.
+ # It may contain additional modules from TEST_CORE_JARS.
+ core_jars_list="core-oj core-libart core-simple okhttp bouncycastle apache-xml conscrypt"
+ core_jars_suffix=
+ if [[ -e $ANDROID_ROOT/framework/core-oj-hostdex.jar ]]; then
+ core_jars_suffix=-hostdex
+ core_locations_dir=$ANDROID_ROOT/framework
+ prefix=$PWD/
+ if [[ ${core_locations_dir:0:${#prefix}} = $prefix ]]; then
+ core_locations_dir="${core_locations_dir##$prefix}"
+ fi
+ elif [[ -e $ANDROID_ROOT/framework/core-oj-testdex.jar ]]; then
+ core_jars_suffix=-testdex
+ core_locations_dir=/system/framework
+ fi
+ if [[ $core_jars_suffix != "" ]]; then
+ boot_separator=""
+ for boot_module in ${core_jars_list}; do
+ DEX_FILENAME="$boot_module$core_jars_suffix.jar"
+ DEX2OAT_BCP+="$boot_separator$ANDROID_ROOT/framework/${DEX_FILENAME}"
+ DEX2OAT_BCP_LOCS+="$boot_separator$core_locations_dir/${DEX_FILENAME}"
+ boot_separator=":"
+ done
+ if [ "$VERBOSE" = "yes" ]; then
+ echo "Using predefined -Xbootclasspath for image $DEX2OAT_BOOT_IMAGE:"
+ echo DEX2OAT_BOOT_IMAGE=$DEX2OAT_BOOT_IMAGE
+ echo DEX2OAT_BCP=$DEX2OAT_BCP
+ echo DEX2OAT_BCP_LOCS=$DEX2OAT_BCP_LOCS
+ fi
+ fi
+fi
+
+if [ "$DEX2OAT_BCP" != "" ]; then
+ EXTRA_OPTIONS+=("-Xbootclasspath:$DEX2OAT_BCP")
+ DEX2OAT_FLAGS+=("--runtime-arg" "-Xbootclasspath:$DEX2OAT_BCP")
+ if [ "$DEX2OAT_BCP_LOCS" != "" ]; then
+ EXTRA_OPTIONS+=("-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
+ DEX2OAT_FLAGS+=("--runtime-arg" \
+ "-Xbootclasspath-locations:$DEX2OAT_BCP_LOCS")
+ fi
+fi
+
if [ "$PERF" != "" ]; then
LAUNCH_WRAPPER="perf record -g --call-graph dwarf -F 10000 -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER"
DEX2OAT_FLAGS+=(--generate-debug-info)
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index da463d5..755104b 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -73,7 +73,7 @@
exit 1
fi
make_command="make $j_arg $extra_args $showcommands build-art-target-tests $common_targets"
- make_command+=" libjavacrypto-target libnetd_client-target linker toybox toolbox sh"
+ make_command+=" libjavacrypto-target libnetd_client-target linker toybox toolbox sh unzip"
make_command+=" debuggerd su"
make_command+=" libstdc++ "
make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt"
@@ -81,8 +81,25 @@
# These targets are needed for the chroot environment.
make_command+=" crash_dump event-log-tags"
fi
- # Build the Runtime APEX.
- make_command+=" com.android.runtime"
+ # Build the Debug Runtime APEX (which is a superset of the Release Runtime APEX).
+ make_command+=" com.android.runtime.debug"
+ # Build the bootstrap Bionic libraries (libc, libdl, libm). These are required
+ # as the "main" libc, libdl, and libm have moved to the Runtime APEX. This is
+ # a temporary change needed until both the ART Buildbot and Golem fully
+ # support the Runtime APEX.
+ #
+ # TODO(b/121117762): Remove this when the ART Buildbot and Golem have full
+ # support for the Runtime APEX.
+ make_command+=" libc.bootstrap libdl.bootstrap libm.bootstrap"
+ # Create a copy of the ICU .dat prebuilt files in /system/etc/icu on target,
+ # so that it can found even if the Runtime APEX is not available, by setting
+ # the environment variable `ART_TEST_ANDROID_RUNTIME_ROOT` to "/system" on
+ # device. This is a temporary change needed until both the ART Buildbot and
+ # Golem fully support the Runtime APEX.
+ #
+ # TODO(b/121117762): Remove this when the ART Buildbot and Golem have full
+ # support for the Runtime APEX.
+ make_command+=" icu-data-art-test"
mode_suffix="-target"
fi
diff --git a/tools/cpp-define-generator/globals.def b/tools/cpp-define-generator/globals.def
index 6443a0c..1054262 100644
--- a/tools/cpp-define-generator/globals.def
+++ b/tools/cpp-define-generator/globals.def
@@ -26,6 +26,7 @@
#include "jit/jit.h"
#include "mirror/object.h"
#include "mirror/object_reference.h"
+#include "runtime_globals.h"
#include "stack.h"
#endif
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 6af822d..86e5f54 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -34,6 +34,8 @@
namespace art {
+const char kErrorHelp[] = "\nSee go/hiddenapi-error for help.";
+
static int original_argc;
static char** original_argv;
@@ -983,16 +985,27 @@
std::map<std::string, hiddenapi::ApiList> api_flag_map;
- for (std::string line; std::getline(api_file, line);) {
+ int line_number = 1;
+ for (std::string line; std::getline(api_file, line); line_number++) {
std::vector<std::string> values = android::base::Split(line, ",");
- CHECK_EQ(values.size(), 2u) << "Currently only signature and one flag are supported";
-
+ CHECK_GT(values.size(), 1u) << path << ":" << line_number << ": No flags found"
+ << kErrorHelp;
const std::string& signature = values[0];
- CHECK(api_flag_map.find(signature) == api_flag_map.end()) << "Duplicate entry: " << signature;
+
+ CHECK(api_flag_map.find(signature) == api_flag_map.end()) << "Duplicate entry in " << path
+ << ": " << signature << kErrorHelp;
+
+ int numFlags = values.size() - 1;
+
+ CHECK_EQ(numFlags, 1) << "\n" << path << ":" << line_number << "\n"
+ << signature << ": Expected one flag, found " << numFlags << ":\n"
+ << ::android::base::Join(std::vector<std::string>(values.begin() + 1, values.end()), ",")
+ << kErrorHelp;
const std::string& flag_str = values[1];
hiddenapi::ApiList membership = hiddenapi::ApiList::FromName(flag_str);
- CHECK(membership.IsValid()) << "Unknown ApiList name: " << flag_str;
+ CHECK(membership.IsValid()) << path << ":" << line_number << ": Unknown ApiList name: "
+ << flag_str << kErrorHelp;
api_flag_map.emplace(signature, membership);
}
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 3c65b01..7ef20bd 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -17,13 +17,13 @@
{
description: "Differences between vogar and cts in user directory",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
name: "libcore.java.lang.SystemTest#testSystemProperties_mutable"
},
{
description: "Differences between vogar and cts. Passes with --mode activity",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.java.lang.OldSystemTest#test_getProperties"]
},
{
@@ -32,7 +32,7 @@
(--invoke-with \"su root\"). Does not pass after setting chmod
777 all directories on path to socket (on device without su).",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.libcore.io.OsTest#testUnixDomainSockets_in_file_system"]
},
{
@@ -47,7 +47,7 @@
{
description: "Issue with incorrect device time (1970)",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.java.util.TimeZoneTest#testDisplayNames",
"libcore.java.util.TimeZoneTest#test_useDaylightTime_Taiwan",
"org.apache.harmony.tests.java.util.TimeZoneTest#test_hasSameRules_Ljava_util_TimeZone"],
@@ -57,13 +57,13 @@
description: "Issue with incorrect device time (1970). Test assumes that DateTime.now()
is greater then a date in 1998.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["org.apache.harmony.tests.java.util.DateTest#test_Constructor"]
},
{
description: "Failing due to a locale problem on hammerhead.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.icu.DateIntervalFormatTest#test10089890",
"libcore.icu.DateIntervalFormatTest#test10209343_when_not_this_year",
"libcore.icu.DateIntervalFormatTest#test10560853_for_single_day_events",
@@ -80,7 +80,7 @@
{
description: "Failing due to missing localhost on hammerhead and volantis.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.javax.crypto.CipherTest#testCipherInitWithCertificate",
"libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithFtpURLConnection",
"libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithJarFtpURLConnection",
@@ -95,13 +95,13 @@
{
description: "Test timeouts",
result: EXEC_TIMEOUT,
- modes: [device],
+ modes: [device_testdex],
names: ["org.apache.harmony.tests.java.util.ScannerTest#testPerformance"]
},
{
description: "Needs the newest cat version on the device",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getErrorStream"]
},
{
@@ -117,7 +117,7 @@
},
{
description: "Linker issues in chrooted environment",
- modes: [device],
+ modes: [device_testdex],
result: EXEC_FAILED,
names: ["org.apache.harmony.tests.java.lang.ProcessManagerTest#testEnvironment"]
},
@@ -130,14 +130,14 @@
{
description: "test_xattr fails on arm64 on the buildbots only: needs investigation",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.libcore.io.OsTest#test_xattr"],
bug: 22258911
},
{
description: "fails on L builds: needs investigation",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["org.apache.harmony.tests.java.lang.ClassTest#test_forNameLjava_lang_String"]
},
{
@@ -163,7 +163,7 @@
description: "Flaky test",
result: EXEC_FAILED,
bug: 30107038,
- modes: [device],
+ modes: [device_testdex],
names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_destroyForcibly"]
},
{
@@ -171,7 +171,7 @@
Unclear if this relates to the tests running sh as a child process.",
result: EXEC_FAILED,
bug: 30657148,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.java.lang.ProcessBuilderTest#testRedirectInherit",
"libcore.java.lang.ProcessBuilderTest#testRedirect_nullStreams"]
},
@@ -195,7 +195,7 @@
{
description: "Timeout on heap-poisoning target builds",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
bug: 116446372,
names: ["libcore.libcore.io.FdsanTest#testSocket"]
},
@@ -223,5 +223,17 @@
"libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[8]",
"libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[9]"
]
+},
+{
+ description: "Apex related",
+ result: EXEC_FAILED,
+ modes: [device_testdex],
+ bug: 122642227,
+ names: [
+ "libcore.java.lang.SystemTest#testSystemProperties_mutable",
+ "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDataVersion",
+ "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDebugInfo",
+ "libcore.libcore.icu.TimeZoneIntegrationTest#testTzDataSetVersions"
+ ]
}
]
diff --git a/tools/libcore_gcstress_debug_failures.txt b/tools/libcore_gcstress_debug_failures.txt
index 23533af..25a4c82 100644
--- a/tools/libcore_gcstress_debug_failures.txt
+++ b/tools/libcore_gcstress_debug_failures.txt
@@ -7,7 +7,7 @@
{
description: "Timeouts on target with gcstress and debug.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["jsr166.CompletableFutureTest#testCompleteOnTimeout_completed",
"jsr166.CompletableFutureTest#testDelayedExecutor",
"jsr166.ExecutorsTest#testTimedCallable",
diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt
index eec45fa..34ede69 100644
--- a/tools/libcore_gcstress_failures.txt
+++ b/tools/libcore_gcstress_failures.txt
@@ -7,7 +7,7 @@
{
description: "Timeouts on target with gcstress.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["libcore.javax.crypto.CipherBasicsTest#testGcmEncryption"]
},
{
@@ -26,7 +26,7 @@
{
description: "Timeouts.",
result: EXEC_FAILED,
- modes: [device],
+ modes: [device_testdex],
names: ["jsr166.TimeUnitTest#testConvert",
"libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence",
"libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing",
diff --git a/tools/mount-buildbot-apexes.sh b/tools/mount-buildbot-apexes.sh
new file mode 100755
index 0000000..778d634
--- /dev/null
+++ b/tools/mount-buildbot-apexes.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+# Mount Android Runtime and Core Libraries APEX packages required in the chroot directory.
+# This script emulates some the actions performed by `apexd`.
+
+green='\033[0;32m'
+nc='\033[0m'
+
+# Setup as root, as some actions performed here require it.
+adb root
+adb wait-for-device
+
+# Exit early if there is no chroot.
+[[ -n "$ART_TEST_CHROOT" ]] || exit
+
+# Check that ART_TEST_CHROOT is correctly defined.
+[[ "$ART_TEST_CHROOT" = /* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
+
+# Check that the "$ART_TEST_CHROOT/apex" directory exists.
+adb shell test -d "$ART_TEST_CHROOT/apex" \
+ || { echo "$ART_TEST_CHROOT/apex does not exist or is not a directory"; exit 1; }
+
+# Create a directory where we extract APEX packages' payloads (ext4 images)
+# under the chroot directory.
+apex_image_dir="/tmp/apex"
+adb shell mkdir -p "$ART_TEST_CHROOT$apex_image_dir"
+
+# activate_system_package APEX_PACKAGE APEX_NAME
+# ----------------------------------------------
+# Extract payload (ext4 image) from system APEX_PACKAGE and mount it as
+# APEX_NAME in `/apex` under the chroot directory.
+activate_system_package() {
+ local apex_package=$1
+ local apex_name=$2
+ local apex_package_path="/system/apex/$apex_package"
+ local abs_mount_point="$ART_TEST_CHROOT/apex/$apex_name"
+ local abs_image_filename="$ART_TEST_CHROOT$apex_image_dir/$apex_name.img"
+
+ # Make sure that the (absolute) path to the mounted ext4 image is less than
+ # 64 characters, which is a hard limit set in the kernel for loop device
+ # filenames (otherwise, we would get an error message from `losetup`, used
+ # by `mount` to manage the loop device).
+ [[ "${#abs_image_filename}" -ge 64 ]] \
+ && { echo "Filename $abs_image_filename is too long to be used with a loop device"; exit 1; }
+
+ echo -e "${green}Activating package $apex_package as $apex_name${nc}"
+
+ # Extract payload (ext4 image). As standard Android builds do not contain
+ # `unzip`, we use the one we built and sync'd to the chroot directory instead.
+ local payload_filename="apex_payload.img"
+ adb shell chroot "$ART_TEST_CHROOT" \
+ /system/bin/unzip -q "$apex_package_path" "$payload_filename" -d "$apex_image_dir"
+ # Rename the extracted payload to have its name match the APEX's name.
+ adb shell mv "$ART_TEST_CHROOT$apex_image_dir/$payload_filename" "$abs_image_filename"
+ # Check that the mount point is available.
+ adb shell mount | grep -q " on $abs_mount_point" && \
+ { echo "$abs_mount_point is already used as mount point"; exit 1; }
+ # Mount the ext4 image.
+ adb shell mkdir -p "$abs_mount_point"
+ adb shell mount -o loop,ro "$abs_image_filename" "$abs_mount_point"
+}
+
+# Activate the Android Runtime APEX.
+# Note: We use the Debug Runtime APEX (which is a superset of the Release Runtime APEX).
+activate_system_package com.android.runtime.debug.apex com.android.runtime
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index c7503bb..ac9f09a 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -125,6 +125,11 @@
# Vogar knows which VM to use on host.
vm_command=""
shift
+ elif [[ "$1" == "--mode=device" ]]; then
+ # Remove the --mode=device from the arguments and replace it with --mode=device_testdex
+ args=${args/$1}
+ args="$args --mode=device_testdex"
+ shift
elif [[ "$1" == "--mode=jvm" ]]; then
mode="ri"
make_target_name="apache-harmony-jdwp-tests-host"
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 68c4fd8..ea7464f 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -125,6 +125,9 @@
while true; do
if [[ "$1" == "--mode=device" ]]; then
device_mode=true
+ # Remove the --mode=device from the arguments and replace it with --mode=device_testdex
+ vogar_args=${vogar_args/$1}
+ vogar_args="$vogar_args --mode=device_testdex"
vogar_args="$vogar_args --vm-arg -Ximage:/data/art-test/core.art"
vogar_args="$vogar_args $(boot_classpath_arg /system/framework -testdex $BOOT_CLASSPATH_JARS)"
shift
diff --git a/tools/setup-buildbot-device.sh b/tools/setup-buildbot-device.sh
index ef958d6..92b3672 100755
--- a/tools/setup-buildbot-device.sh
+++ b/tools/setup-buildbot-device.sh
@@ -165,4 +165,9 @@
adb shell mkdir -p "$ART_TEST_CHROOT/dev"
adb shell mount | grep -q "^tmpfs on $ART_TEST_CHROOT/dev type tmpfs " \
|| adb shell mount -o bind /dev "$ART_TEST_CHROOT/dev"
+
+ # Create /apex tmpfs in chroot.
+ adb shell mkdir -p "$ART_TEST_CHROOT/apex"
+ adb shell mount | grep -q "^tmpfs on $ART_TEST_CHROOT/apex type tmpfs " \
+ || adb shell mount -t tmpfs -o nodev,noexec,nosuid tmpfs "$ART_TEST_CHROOT/apex"
fi
diff --git a/tools/teardown-buildbot-device.sh b/tools/teardown-buildbot-device.sh
index 6634fb4..7eb5cc3 100755
--- a/tools/teardown-buildbot-device.sh
+++ b/tools/teardown-buildbot-device.sh
@@ -89,6 +89,9 @@
fi
}
+ # Remove /apex from chroot.
+ remove_filesystem_from_chroot apex tmpfs true
+
# Remove /dev from chroot.
remove_filesystem_from_chroot dev tmpfs true
diff --git a/tools/unmount-buildbot-apexes.sh b/tools/unmount-buildbot-apexes.sh
new file mode 100755
index 0000000..8f0ad5f
--- /dev/null
+++ b/tools/unmount-buildbot-apexes.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 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.
+
+# Unmount Android Runtime and Core Libraries APEX packages required in the chroot directory.
+# This script emulates some the actions performed by `apexd`.
+
+# This script undoes the work done by tools/mount-buildbot-apexes.sh.
+# Make sure to keep these files in sync.
+
+green='\033[0;32m'
+nc='\033[0m'
+
+# Setup as root, as some actions performed here require it.
+adb root
+adb wait-for-device
+
+# Exit early if there is no chroot.
+[[ -n "$ART_TEST_CHROOT" ]] || exit
+
+# Check that ART_TEST_CHROOT is correctly defined.
+[[ "$ART_TEST_CHROOT" = /* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
+
+# Directory containing extracted APEX packages' payloads (ext4 images) under
+# the chroot directory.
+apex_image_dir="/tmp/apex"
+
+# deactivate_system_package APEX_NAME
+# -----------------------------------
+# Unmount APEX_NAME in `/apex` under the chroot directory and delete the
+# corresponding APEX package payload (ext4 image).
+deactivate_system_package() {
+ local apex_name=$1
+ local abs_image_filename="$ART_TEST_CHROOT$apex_image_dir/$apex_name.img"
+ local abs_mount_point="$ART_TEST_CHROOT/apex/$apex_name"
+
+ echo -e "${green}Deactivating package $apex_name${nc}"
+
+ # Unmount the package's payload (ext4 image).
+ if adb shell mount | grep -q "^/dev/block/loop[0-9]\+ on $abs_mount_point type ext4"; then
+ adb shell umount "$abs_mount_point"
+ adb shell rmdir "$abs_mount_point"
+ # Delete the ext4 image.
+ adb shell rm "$abs_image_filename"
+ fi
+}
+
+# Deactivate the Android Runtime APEX.
+deactivate_system_package com.android.runtime
+
+# Delete the image's directory.
+adb shell rmdir "$ART_TEST_CHROOT$apex_image_dir"