Add HeapTest and make GC work enough to pass it
Change-Id: If06eaef2921b64b3226bfd347acaec60ec993e67
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9bbcb0c..89b425f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -7,6 +7,7 @@
#include "UniquePtr.h"
#include "casts.h"
+#include "class_loader.h"
#include "dex_cache.h"
#include "dex_file.h"
#include "dex_verifier.h"
@@ -14,6 +15,7 @@
#include "logging.h"
#include "monitor.h"
#include "object.h"
+#include "runtime.h"
#include "space.h"
#include "thread.h"
#include "utils.h"
@@ -242,14 +244,44 @@
SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
- SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;"));
- SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;"));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+
+ // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
+ Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
+ Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;");
+ Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;");
+ Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;");
+ java_lang_ref_FinalizerReference->access_flags_ |= kAccClassIsReference | kAccClassIsFinalizerReference;
+ java_lang_ref_PhantomReference->access_flags_ |= kAccClassIsReference | kAccClassIsPhantomReference;
+ java_lang_ref_SoftReference->access_flags_ |= kAccClassIsReference;
+ java_lang_ref_WeakReference->access_flags_ |= kAccClassIsReference | kAccClassIsWeakReference;
+
+ // Let the heap know some key offsets into java.lang.ref instances
+ Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
+ Field* referent = java_lang_ref_Reference->FindDeclaredInstanceField(
+ "referent", "Ljava/lang/Object;");
+ Field* queue = java_lang_ref_Reference->FindDeclaredInstanceField(
+ "queue", "Ljava/lang/ref/ReferenceQueue;");
+ Field* queueNext = java_lang_ref_Reference->FindDeclaredInstanceField(
+ "queueNext", "Ljava/lang/ref/Reference;");
+ Field* pendingNext = java_lang_ref_Reference->FindDeclaredInstanceField(
+ "pendingNext", "Ljava/lang/ref/Reference;");
+ Field* zombie = java_lang_ref_FinalizerReference->FindDeclaredInstanceField(
+ "zombie", "Ljava/lang/Object;");
+ Heap::SetReferenceOffsets(referent->GetOffset(),
+ queue->GetOffset(),
+ queueNext->GetOffset(),
+ pendingNext->GetOffset(),
+ zombie->GetOffset());
+
+ // Optimization for quick stack trace allocation
+ SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;"));
+ SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;"));
StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
FinishInit();
@@ -455,11 +487,11 @@
}
Field* ClassLinker::AllocField() {
- return down_cast<Field*>(GetClassRoot(kJavaLangReflectField)->NewInstance());
+ return down_cast<Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject());
}
Method* ClassLinker::AllocMethod() {
- return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->NewInstance());
+ return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject());
}
ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(size_t length) {
@@ -649,6 +681,9 @@
klass->primitive_type_ = Class::kPrimNot;
klass->status_ = Class::kStatusIdx;
+ // Make sure the aren't any "bonus" flags set, since we use them for runtime state.
+ CHECK_EQ(klass->access_flags_ & ~kAccClassFlagsMask, 0U);
+
klass->super_class_ = NULL;
klass->super_class_type_idx_ = dex_class_def.superclass_idx_;
@@ -701,7 +736,7 @@
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
Method* meth = AllocMethod();
klass->SetDirectMethod(i, meth);
- LoadMethod(dex_file, dex_method, klass, meth, true);
+ LoadMethod(dex_file, dex_method, klass, meth);
// TODO: register maps
}
}
@@ -717,7 +752,7 @@
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
Method* meth = AllocMethod();
klass->SetVirtualMethod(i, meth);
- LoadMethod(dex_file, dex_method, klass, meth, false);
+ LoadMethod(dex_file, dex_method, klass, meth);
// TODO: register maps
}
}
@@ -754,8 +789,7 @@
void ClassLinker::LoadMethod(const DexFile& dex_file,
const DexFile::Method& src,
Class* klass,
- Method* dst,
- bool is_direct) {
+ Method* dst) {
const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
dst->declaring_class_ = klass;
dst->name_ = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
@@ -776,8 +810,6 @@
dst->dex_cache_code_and_direct_methods_ = klass->dex_cache_->GetCodeAndDirectMethods();
dst->dex_cache_initialized_static_storage_ = klass->dex_cache_->GetInitializedStaticStorage();
- dst->is_direct_ = is_direct;
-
// TODO: check for finalize method
const DexFile::CodeItem* code_item = dex_file.GetCodeItem(src);