Merge "ART: Only log initialization failure on initialization"
diff --git a/Android.mk b/Android.mk
index ba131c6..237dcd8 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:
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/apex/Android.bp b/build/apex/Android.bp
index 193a3c1..79f67a2 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,7 +41,6 @@
"libopenjdkjvmd",
"libopenjdkjvmtid",
"libadbconnectiond",
- "libjavacrypto",
]
// Files associated with bionic / managed core library time zone APIs.
@@ -72,13 +57,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 +73,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 +100,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: {
@@ -141,7 +128,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,7 +142,7 @@
+ art_runtime_debug_binaries_prefer32,
},
first: {
- binaries: art_tools_binaries,
+ binaries: art_tools_device_binaries,
}
},
prebuilts: art_runtime_time_zone_prebuilts
@@ -177,7 +163,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 +171,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/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/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.cc b/dex2oat/dex2oat.cc
index ea4158a..35af918 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -382,6 +382,9 @@
UsageError(" --avoid-storing-invocation: Avoid storing the invocation args in the key value");
UsageError(" store. Used to test determinism with different args.");
UsageError("");
+ UsageError(" --write-invocation-to=<file>: Write the invocation commandline to the given file");
+ UsageError(" for later use. Used to test determinism with different host architectures.");
+ UsageError("");
UsageError(" --runtime-arg <argument>: used to specify various arguments for the runtime,");
UsageError(" such as initial heap size, maximum heap size, and verbose output.");
UsageError(" Use a separate --runtime-arg switch for each argument.");
@@ -1001,6 +1004,21 @@
CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
key_value_store_->Put(OatHeader::kConcurrentCopying,
kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+ if (invocation_file_.get() != -1) {
+ std::ostringstream oss;
+ for (int i = 0; i < argc; ++i) {
+ if (i > 0) {
+ oss << std::endl;
+ }
+ oss << argv[i];
+ }
+ std::string invocation(oss.str());
+ if (TEMP_FAILURE_RETRY(write(invocation_file_.get(),
+ invocation.c_str(),
+ invocation.size())) == -1) {
+ Usage("Unable to write invocation file");
+ }
+ }
}
// This simple forward is here so the string specializations below don't look out of place.
@@ -1116,6 +1134,16 @@
AssignTrueIfExists(args, M::Host, &is_host_);
AssignTrueIfExists(args, M::AvoidStoringInvocation, &avoid_storing_invocation_);
+ if (args.Exists(M::InvocationFile)) {
+ invocation_file_.reset(open(args.Get(M::InvocationFile)->c_str(),
+ O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC,
+ S_IRUSR|S_IWUSR));
+ if (invocation_file_.get() == -1) {
+ int err = errno;
+ Usage("Unable to open invocation file '%s' for writing due to %s.",
+ args.Get(M::InvocationFile)->c_str(), strerror(err));
+ }
+ }
AssignIfExists(args, M::CopyDexFiles, ©_dex_files_);
if (args.Exists(M::ForceDeterminism)) {
@@ -2712,6 +2740,7 @@
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
bool avoid_storing_invocation_;
+ android::base::unique_fd invocation_file_;
std::string swap_file_name_;
int swap_fd_;
size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 236c1fc..783b326 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -229,6 +229,9 @@
{"false", linker::CopyOption::kNever},
{"always", linker::CopyOption::kAlways}})
.IntoKey(M::CopyDexFiles)
+ .Define("--write-invocation-to=_")
+ .WithType<std::string>()
+ .IntoKey(M::InvocationFile)
.Define("--classpath-dir=_")
.WithType<std::string>()
.IntoKey(M::ClasspathDir)
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index c8cb7e7..0b77859 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -84,6 +84,7 @@
DEX2OAT_OPTIONS_KEY (std::string, NoInlineFrom)
DEX2OAT_OPTIONS_KEY (Unit, ForceDeterminism)
DEX2OAT_OPTIONS_KEY (std::string, ClasspathDir)
+DEX2OAT_OPTIONS_KEY (std::string, InvocationFile)
DEX2OAT_OPTIONS_KEY (std::string, ClassLoaderContext)
DEX2OAT_OPTIONS_KEY (std::string, StoredClassLoaderContext)
DEX2OAT_OPTIONS_KEY (std::string, DirtyImageObjects)
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/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/libartbase/Android.bp b/libartbase/Android.bp
index 0fcd6a5..109853c 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -64,6 +64,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 +83,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 +102,7 @@
// For common macros.
"libbase",
],
+ export_static_lib_headers: ["libbase"],
cflags: ["-Wno-thread-safety"],
},
},
@@ -115,7 +121,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 {
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/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/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/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/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..9949bf4 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -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
@@ -1140,15 +1145,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/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/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/thread_list.cc b/runtime/thread_list.cc
index 75462ac..1b3b037 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -1476,24 +1476,26 @@
// Remove and delete the Thread* while holding the thread_list_lock_ and
// thread_suspend_count_lock_ so that the unregistering thread cannot be suspended.
// Note: deliberately not using MutexLock that could hold a stale self pointer.
- MutexLock mu(self, *Locks::thread_list_lock_);
- if (!Contains(self)) {
- std::string thread_name;
- self->GetThreadName(thread_name);
- std::ostringstream os;
- DumpNativeStack(os, GetTid(), nullptr, " native: ", nullptr);
- LOG(ERROR) << "Request to unregister unattached thread " << thread_name << "\n" << os.str();
- break;
- } else {
- MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
- if (!self->IsSuspended()) {
- list_.remove(self);
+ {
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ if (!Contains(self)) {
+ std::string thread_name;
+ self->GetThreadName(thread_name);
+ std::ostringstream os;
+ DumpNativeStack(os, GetTid(), nullptr, " native: ", nullptr);
+ LOG(ERROR) << "Request to unregister unattached thread " << thread_name << "\n" << os.str();
break;
+ } else {
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+ if (!self->IsSuspended()) {
+ list_.remove(self);
+ break;
+ }
}
- // In the case where we are not suspended yet, sleep to leave other threads time to execute.
- // This is important if there are realtime threads. b/111277984
- usleep(1);
}
+ // In the case where we are not suspended yet, sleep to leave other threads time to execute.
+ // This is important if there are realtime threads. b/111277984
+ usleep(1);
// We failed to remove the thread due to a suspend request, loop and try again.
}
delete self;
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/tools/art b/tools/art
index eeb7c68..6e43863 100644
--- a/tools/art
+++ b/tools/art
@@ -222,6 +222,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 +236,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,7 +398,7 @@
done
PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-ANDROID_ROOT=$PROG_DIR/..
+ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
ANDROID_RUNTIME_ROOT=$ANDROID_ROOT/com.android.runtime
ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY
@@ -439,6 +451,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/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/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