Compacting collector.
The compacting collector is currently similar to semispace. It works by
copying objects back and forth between two bump pointer spaces. There
are types of objects which are "non-movable" due to current runtime
limitations. These are Classes, Methods, and Fields.
Bump pointer spaces are a new type of continuous alloc space which have
no lock in the allocation code path. When you allocate from these it uses
atomic operations to increase an index. Traversing the objects in the bump
pointer space relies on Object::SizeOf matching the allocated size exactly.
Runtime changes:
JNI::GetArrayElements returns copies objects if you attempt to get the
backing data of a movable array. For GetArrayElementsCritical, we return
direct backing storage for any types of arrays, but temporarily disable
the GC until the critical region is completed.
Added a new runtime call called VisitObjects, this is used in place of
the old pattern which was flushing the allocation stack and walking
the bitmaps.
Changed image writer to be compaction safe and use object monitor word
for forwarding addresses.
Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc..
TODO: Enable switching allocators, compacting on background, etc..
Bug: 8981901
Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index ab5eab3..c9e0e83 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -161,7 +161,7 @@
ScopedObjectAccess soa(env);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
class_linker->RegisterDexFile(*dex_file);
- mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(javaLoader));
mirror::Class* result = class_linker->DefineClass(descriptor.c_str(), class_loader, *dex_file,
*dex_class_def);
VLOG(class_linker) << "DexFile_defineClassNative returning " << result;
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index aef000c..f0efdc2 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -53,18 +53,9 @@
static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) {
}
-static jobject VMRuntime_newNonMovableArray(JNIEnv* env,
- jobject,
- jclass javaElementClass,
+static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass,
jint length) {
ScopedFastNativeObjectAccess soa(env);
-#ifdef MOVING_GARBAGE_COLLECTOR
- // TODO: right now, we don't have a copying collector, so there's no need
- // to do anything special here, but we ought to pass the non-movability
- // through to the allocator.
- UNIMPLEMENTED(FATAL);
-#endif
-
mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
if (element_class == NULL) {
ThrowNullPointerException(NULL, "element class == null");
@@ -74,13 +65,13 @@
ThrowNegativeArraySizeException(length);
return NULL;
}
-
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
std::string descriptor;
descriptor += "[";
descriptor += ClassHelper(element_class).GetDescriptor();
- mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL);
- mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length);
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
+ mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+ mirror::Array* result = mirror::Array::Alloc<false, true>(soa.Self(), array_class, length);
return soa.AddLocalReference<jobject>(result);
}
@@ -94,7 +85,10 @@
ThrowIllegalArgumentException(NULL, "not an array");
return 0;
}
- // TODO: we should also check that this is a non-movable array.
+ if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
+ ThrowRuntimeException("Trying to get address of movable array object");
+ return 0;
+ }
return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize()));
}
@@ -172,28 +166,7 @@
}
static void VMRuntime_trimHeap(JNIEnv*, jobject) {
- uint64_t start_ns = NanoTime();
-
- // Trim the managed heap.
- gc::Heap* heap = Runtime::Current()->GetHeap();
- float managed_utilization = (static_cast<float>(heap->GetBytesAllocated()) /
- heap->GetTotalMemory());
- size_t managed_reclaimed = heap->Trim();
-
- uint64_t gc_heap_end_ns = NanoTime();
-
- // Trim the native heap.
- dlmalloc_trim(0);
- size_t native_reclaimed = 0;
- dlmalloc_inspect_all(DlmallocMadviseCallback, &native_reclaimed);
-
- uint64_t end_ns = NanoTime();
-
- LOG(INFO) << "Heap trim of managed (duration=" << PrettyDuration(gc_heap_end_ns - start_ns)
- << ", advised=" << PrettySize(managed_reclaimed) << ") and native (duration="
- << PrettyDuration(end_ns - gc_heap_end_ns) << ", advised=" << PrettySize(native_reclaimed)
- << ") heaps. Managed heap utilization of " << static_cast<int>(100 * managed_utilization)
- << "%.";
+ Runtime::Current()->GetHeap()->Trim();
}
static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
@@ -212,7 +185,7 @@
}
// Based on ClassLinker::ResolveString.
-static void PreloadDexCachesResolveString(mirror::DexCache* dex_cache,
+static void PreloadDexCachesResolveString(SirtRef<mirror::DexCache>& dex_cache,
uint32_t string_idx,
StringTable& strings)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -260,7 +233,7 @@
}
// Based on ClassLinker::ResolveField.
-static void PreloadDexCachesResolveField(mirror::DexCache* dex_cache,
+static void PreloadDexCachesResolveField(SirtRef<mirror::DexCache>& dex_cache,
uint32_t field_idx,
bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -275,9 +248,9 @@
return;
}
if (is_static) {
- field = klass->FindStaticField(dex_cache, field_idx);
+ field = klass->FindStaticField(dex_cache.get(), field_idx);
} else {
- field = klass->FindInstanceField(dex_cache, field_idx);
+ field = klass->FindInstanceField(dex_cache.get(), field_idx);
}
if (field == NULL) {
return;
@@ -287,7 +260,7 @@
}
// Based on ClassLinker::ResolveMethod.
-static void PreloadDexCachesResolveMethod(mirror::DexCache* dex_cache,
+static void PreloadDexCachesResolveMethod(SirtRef<mirror::DexCache>& dex_cache,
uint32_t method_idx,
InvokeType invoke_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -304,14 +277,14 @@
switch (invoke_type) {
case kDirect:
case kStatic:
- method = klass->FindDirectMethod(dex_cache, method_idx);
+ method = klass->FindDirectMethod(dex_cache.get(), method_idx);
break;
case kInterface:
- method = klass->FindInterfaceMethod(dex_cache, method_idx);
+ method = klass->FindInterfaceMethod(dex_cache.get(), method_idx);
break;
case kSuper:
case kVirtual:
- method = klass->FindVirtualMethod(dex_cache, method_idx);
+ method = klass->FindVirtualMethod(dex_cache.get(), method_idx);
break;
default:
LOG(FATAL) << "Unreachable - invocation type: " << invoke_type;
@@ -430,6 +403,7 @@
Runtime* runtime = Runtime::Current();
ClassLinker* linker = runtime->GetClassLinker();
+ Thread* self = ThreadForEnv(env);
// We use a std::map to avoid heap allocating StringObjects to lookup in gDvm.literalStrings
StringTable strings;
@@ -441,7 +415,7 @@
for (size_t i = 0; i< boot_class_path.size(); i++) {
const DexFile* dex_file = boot_class_path[i];
CHECK(dex_file != NULL);
- mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
+ SirtRef<mirror::DexCache> dex_cache(self, linker->FindDexCache(*dex_file));
if (kPreloadDexCachesStrings) {
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
@@ -451,7 +425,7 @@
if (kPreloadDexCachesTypes) {
for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
- PreloadDexCachesResolveType(dex_cache, i);
+ PreloadDexCachesResolveType(dex_cache.get(), i);
}
}
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 3591611..3389107 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -61,7 +61,8 @@
}
std::string descriptor(DotToDescriptor(name.c_str()));
- mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
+ soa.Decode<mirror::ClassLoader*>(javaLoader));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
mirror::Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
if (c == NULL) {
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index a2d6b18..808c917 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -52,13 +52,15 @@
descriptor += ClassHelper(element_class).GetDescriptor();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader());
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(), element_class->GetClassLoader());
+ mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
if (UNLIKELY(array_class == NULL)) {
CHECK(soa.Self()->IsExceptionPending());
return NULL;
}
DCHECK(array_class->IsArrayClass());
- mirror::Array* new_array = mirror::Array::Alloc(soa.Self(), array_class, length);
+ mirror::Array* new_array = mirror::Array::Alloc<kMovingCollector, true>(
+ soa.Self(), array_class, length);
return soa.AddLocalReference<jobject>(new_array);
}
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index a92823a..809369a 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -23,20 +23,12 @@
namespace art {
-static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring javaName,
- jobjectArray javaInterfaces, jobject javaLoader,
- jobjectArray javaMethods, jobjectArray javaThrows) {
+static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring name, jobjectArray interfaces,
+ jobject loader, jobjectArray methods, jobjectArray throws) {
ScopedObjectAccess soa(env);
- mirror::String* name = soa.Decode<mirror::String*>(javaName);
- mirror::ObjectArray<mirror::Class>* interfaces =
- soa.Decode<mirror::ObjectArray<mirror::Class>*>(javaInterfaces);
- mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
- mirror::ObjectArray<mirror::ArtMethod>* methods =
- soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(javaMethods);
- mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >* throws =
- soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(javaThrows);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* result = class_linker->CreateProxyClass(name, interfaces, loader, methods, throws);
+ mirror::Class* result = class_linker->CreateProxyClass(soa, name, interfaces, loader, methods,
+ throws);
return soa.AddLocalReference<jclass>(result);
}
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index d941ec3..1658d96 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -63,10 +63,6 @@
Locks::mutator_lock_->AssertSharedHeld(Self());
// Don't work with raw objects in non-runnable states.
DCHECK_EQ(Self()->GetState(), kRunnable);
-#ifdef MOVING_GARBAGE_COLLECTOR
- // TODO: we should make these unique weak globals if Field instances can ever move.
- UNIMPLEMENTED(WARNING);
-#endif
return reinterpret_cast<mirror::ArtField*>(fid);
}
@@ -83,6 +79,10 @@
return NULL;
}
+ if (kIsDebugBuild) {
+ Runtime::Current()->GetHeap()->VerifyObject(obj);
+ }
+
DCHECK_NE((reinterpret_cast<uintptr_t>(obj) & 0xffff0000), 0xebad0000);
IndirectReferenceTable& locals = Env()->locals;