Merge "Remove core-simple from the boot classpath"
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 47729c1..aa199d3 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -34,14 +34,17 @@
"dexoptanalyzerd",
"profmand",
]
+// - Debug variants (libraries).
art_runtime_debug_native_shared_libs = [
"libartd",
"libartd-compiler",
- "libopenjdkd",
"libopenjdkjvmd",
"libopenjdkjvmtid",
"libadbconnectiond",
]
+libcore_debug_native_shared_libs = [
+ "libopenjdkd",
+]
// Data files associated with bionic / managed core library APIs.
art_runtime_data_file_prebuilts = [
@@ -77,6 +80,11 @@
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
+// (Some) Libcore native libraries.
+libcore_native_shared_libs = [
+ "libopenjdk",
+]
+
apex_key {
name: "com.android.runtime.key",
public_key: "com.android.runtime.avbpubkey",
@@ -101,7 +109,8 @@
compile_multilib: "both",
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
- + bionic_native_shared_libs,
+ + bionic_native_shared_libs
+ + libcore_native_shared_libs,
multilib: {
both: {
// TODO: Add logic to create a `dalvikvm` symlink to `dalvikvm32` or `dalvikvm64`
@@ -130,7 +139,9 @@
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
+ art_runtime_debug_native_shared_libs
- + bionic_native_shared_libs,
+ + bionic_native_shared_libs
+ + libcore_native_shared_libs
+ + libcore_debug_native_shared_libs,
multilib: {
both: {
// TODO: Add logic to create a `dalvikvm` symlink to `dalvikvm32` or `dalvikvm64`
@@ -164,7 +175,9 @@
device_supported: false,
manifest: "manifest.json",
native_shared_libs: art_runtime_base_native_shared_libs
- + art_runtime_debug_native_shared_libs,
+ + art_runtime_debug_native_shared_libs
+ + libcore_native_shared_libs
+ + libcore_debug_native_shared_libs,
multilib: {
both: {
// TODO: Add logic to create a `dalvikvm` symlink to `dalvikvm32` or `dalvikvm64`
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index 9db325a..b2aa4df 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -157,6 +157,7 @@
check_library libprofile.so
# Check that the mounted image contains Android Core libraries.
check_library libjavacrypto.so
+ check_library libopenjdk.so
# Check that the mounted image contains additional required libraries.
check_library libadbconnection.so
@@ -193,11 +194,12 @@
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 libprofiled.so
- # Check that the mounted image contains additional required libraries.
+ # Check that the mounted image contains Android Core debug libraries.
+ check_library libopenjdkd.so
+ # Check that the mounted image contains additional required debug libraries.
check_library libadbconnectiond.so
}
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 341f16a..52c9386 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -441,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);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 5ad5f52..4a2dbf5 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -342,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_;
}
@@ -382,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
@@ -446,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)
@@ -527,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));
}
}
@@ -538,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 {
@@ -546,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);
}
}
@@ -559,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);
@@ -583,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);
}
}
@@ -606,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);
@@ -615,7 +615,11 @@
}
private:
- ReferenceVisitor reference_visitor_;
+ // Heap objects visitor.
+ HeapVisitor heap_visitor_;
+
+ // Native objects visitor.
+ NativeVisitor native_visitor_;
};
template <typename ObjectVisitor>
@@ -829,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`.
@@ -982,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);
@@ -1012,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_) {
@@ -1087,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(
@@ -1118,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));
}
}
@@ -1131,7 +1117,7 @@
if (obj != nullptr) {
ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
mirror::Reference::ReferentOffset(),
- ForwardObject(obj));
+ forward_(obj));
}
}
@@ -1148,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
@@ -1257,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.
@@ -1288,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
@@ -1303,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);
@@ -1312,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>();
@@ -1326,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);
}
}
@@ -1343,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)->
@@ -1364,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());
@@ -1397,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);
}
@@ -1619,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 42ac3e2..bb19097 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -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/handle_scope.h b/runtime/handle_scope.h
index dae8e29..ec1d166 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -259,20 +259,17 @@
void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
private:
- static constexpr size_t kLocalScopeSize = 64u;
- static constexpr size_t kSizeOfReferencesPerScope =
- kLocalScopeSize
- - /* BaseHandleScope::link_ */ sizeof(BaseHandleScope*)
- - /* BaseHandleScope::number_of_references_ */ sizeof(int32_t)
- - /* FixedSizeHandleScope<>::pos_ */ sizeof(uint32_t);
- static constexpr size_t kNumReferencesPerScope =
- kSizeOfReferencesPerScope / sizeof(StackReference<mirror::Object>);
+ static constexpr size_t kMaxLocalScopeSize = 64u;
+ // In order to have consistent compilation with both 32bit and 64bit dex2oat
+ // binaries we need this to be an actual constant. We picked this because it
+ // will ensure that we use <64bit internal scopes.
+ static constexpr size_t kNumReferencesPerScope = 12u;
Thread* const self_;
// Linked list of fixed size handle scopes.
using LocalScopeType = FixedSizeHandleScope<kNumReferencesPerScope>;
- static_assert(sizeof(LocalScopeType) == kLocalScopeSize, "Unexpected size of LocalScopeType");
+ static_assert(sizeof(LocalScopeType) <= kMaxLocalScopeSize, "Unexpected size of LocalScopeType");
LocalScopeType* current_scope_;
DISALLOW_COPY_AND_ASSIGN(VariableSizedHandleScope);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index eea7c67..d79793b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -324,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
@@ -341,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)
diff --git a/tools/art b/tools/art
index 518bc77..58a8150 100644
--- a/tools/art
+++ b/tools/art
@@ -400,34 +400,39 @@
PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
-# 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.
+
+# 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 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"
+ # 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
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index a2777e8..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"]
},
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",