summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2011-10-20 12:27:42 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-10-20 12:27:42 -0700
commitfb8a127fd2ca8eb6cbbc9d62b708c1fc2b3003a4 (patch)
treef93c76c6f734cd44a858d7cfa20fc4bf546736a8
parent7f88e76688c5d74959d99bf3db4b4b0af88bfe29 (diff)
parent40381fb9dc4b4cf274f1e58b2cdf4396202c6189 (diff)
downloadart-fb8a127fd2ca8eb6cbbc9d62b708c1fc2b3003a4.zip
art-fb8a127fd2ca8eb6cbbc9d62b708c1fc2b3003a4.tar.gz
art-fb8a127fd2ca8eb6cbbc9d62b708c1fc2b3003a4.tar.bz2
Merge "Reuse SIRT for C++ references" into dalvik-dev
-rw-r--r--src/class_linker.cc343
-rw-r--r--src/class_linker.h47
-rw-r--r--src/class_linker_test.cc69
-rw-r--r--src/class_loader.cc8
-rw-r--r--src/class_loader.h2
-rw-r--r--src/common_test.h22
-rw-r--r--src/compiler_test.cc8
-rw-r--r--src/dex2oat.cc14
-rw-r--r--src/dex_cache_test.cc4
-rw-r--r--src/dex_file.cc31
-rw-r--r--src/dex_file.h21
-rw-r--r--src/dex_verifier.cc24
-rw-r--r--src/dex_verifier_test.cc4
-rw-r--r--src/exception_test.cc4
-rw-r--r--src/heap_test.cc2
-rw-r--r--src/image_writer.cc20
-rw-r--r--src/intern_table_test.cc80
-rw-r--r--src/java_lang_reflect_Array.cc16
-rw-r--r--src/jni_compiler_test.cc118
-rw-r--r--src/jni_internal_test.cc82
-rw-r--r--src/mark_sweep.cc23
-rw-r--r--src/oat_test.cc10
-rw-r--r--src/object.cc17
-rw-r--r--src/object_test.cc121
-rw-r--r--src/runtime.cc4
-rw-r--r--src/stack_indirect_reference_table.h71
-rw-r--r--src/stub_arm.cc19
-rw-r--r--src/stub_x86.cc19
-rw-r--r--src/thread.cc42
-rw-r--r--src/thread.h9
-rw-r--r--src/utils_test.cc12
-rw-r--r--test/ReferenceMap/stack_walk_refmap_jni.cc2
32 files changed, 689 insertions, 579 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 7ca0361..44ca80c 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -22,6 +22,7 @@
#include "runtime_support.h"
#include "ScopedLocalRef.h"
#include "space.h"
+#include "stack_indirect_reference_table.h"
#include "stl_util.h"
#include "thread.h"
#include "UniquePtr.h"
@@ -228,38 +229,38 @@ void ClassLinker::Init(const std::string& boot_class_path) {
CHECK(!init_done_);
// java_lang_Class comes first, it's needed for AllocClass
- Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(ClassClass)));
- CHECK(java_lang_Class != NULL);
- java_lang_Class->SetClass(java_lang_Class);
+ SirtRef<Class> java_lang_Class(down_cast<Class*>(Heap::AllocObject(NULL, sizeof(ClassClass))));
+ CHECK(java_lang_Class.get() != NULL);
+ java_lang_Class->SetClass(java_lang_Class.get());
java_lang_Class->SetClassSize(sizeof(ClassClass));
// AllocClass(Class*) can now be used
// Class[] is used for reflection support.
- Class* class_array_class = AllocClass(java_lang_Class, sizeof(Class));
- class_array_class->SetComponentType(java_lang_Class);
+ SirtRef<Class> class_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+ class_array_class->SetComponentType(java_lang_Class.get());
// java_lang_Object comes next so that object_array_class can be created
- Class* java_lang_Object = AllocClass(java_lang_Class, sizeof(Class));
- CHECK(java_lang_Object != NULL);
+ SirtRef<Class> java_lang_Object(AllocClass(java_lang_Class.get(), sizeof(Class)));
+ CHECK(java_lang_Object.get() != NULL);
// backfill Object as the super class of Class
- java_lang_Class->SetSuperClass(java_lang_Object);
+ java_lang_Class->SetSuperClass(java_lang_Object.get());
java_lang_Object->SetStatus(Class::kStatusLoaded);
// Object[] next to hold class roots
- Class* object_array_class = AllocClass(java_lang_Class, sizeof(Class));
- object_array_class->SetComponentType(java_lang_Object);
+ SirtRef<Class> object_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+ object_array_class->SetComponentType(java_lang_Object.get());
// Setup the char class to be used for char[]
- Class* char_class = AllocClass(java_lang_Class, sizeof(Class));
+ SirtRef<Class> char_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
// Setup the char[] class to be used for String
- Class* char_array_class = AllocClass(java_lang_Class, sizeof(Class));
- char_array_class->SetComponentType(char_class);
- CharArray::SetArrayClass(char_array_class);
+ SirtRef<Class> char_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+ char_array_class->SetComponentType(char_class.get());
+ CharArray::SetArrayClass(char_array_class.get());
// Setup String
- Class* java_lang_String = AllocClass(java_lang_Class, sizeof(StringClass));
- String::SetClass(java_lang_String);
+ SirtRef<Class> java_lang_String(AllocClass(java_lang_Class.get(), sizeof(StringClass)));
+ String::SetClass(java_lang_String.get());
java_lang_String->SetObjectSize(sizeof(String));
java_lang_String->SetStatus(Class::kStatusResolved);
@@ -273,14 +274,14 @@ void ClassLinker::Init(const std::string& boot_class_path) {
// Create storage for root classes, save away our work so far (requires
// descriptors)
- class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax);
+ class_roots_ = ObjectArray<Class>::Alloc(object_array_class.get(), kClassRootsMax);
CHECK(class_roots_ != NULL);
- SetClassRoot(kJavaLangClass, java_lang_Class);
- SetClassRoot(kJavaLangObject, java_lang_Object);
- SetClassRoot(kClassArrayClass, class_array_class);
- SetClassRoot(kObjectArrayClass, object_array_class);
- SetClassRoot(kCharArrayClass, char_array_class);
- SetClassRoot(kJavaLangString, java_lang_String);
+ SetClassRoot(kJavaLangClass, java_lang_Class.get());
+ SetClassRoot(kJavaLangObject, java_lang_Object.get());
+ SetClassRoot(kClassArrayClass, class_array_class.get());
+ SetClassRoot(kObjectArrayClass, object_array_class.get());
+ SetClassRoot(kCharArrayClass, char_array_class.get());
+ SetClassRoot(kJavaLangString, java_lang_String.get());
// Setup the primitive type classes.
SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
@@ -297,11 +298,11 @@ void ClassLinker::Init(const std::string& boot_class_path) {
array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
// Create int array type for AllocDexCache (done in AppendToBootClassPath)
- Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
+ SirtRef<Class> int_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
int_array_class->SetDescriptor(intern_table_->InternStrong("[I"));
int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
- IntArray::SetArrayClass(int_array_class);
- SetClassRoot(kIntArrayClass, int_array_class);
+ IntArray::SetArrayClass(int_array_class.get());
+ SetClassRoot(kIntArrayClass, int_array_class.get());
// now that these are registered, we can use AllocClass() and AllocObjectArray
@@ -316,43 +317,43 @@ void ClassLinker::Init(const std::string& boot_class_path) {
}
// Constructor, Field, and Method are necessary so that FindClass can link members
- Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass));
+ SirtRef<Class> java_lang_reflect_Constructor(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
java_lang_reflect_Constructor->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Constructor;"));
- CHECK(java_lang_reflect_Constructor != NULL);
+ CHECK(java_lang_reflect_Constructor.get() != NULL);
java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
- SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor);
+ SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
- Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
- CHECK(java_lang_reflect_Field != NULL);
+ SirtRef<Class> java_lang_reflect_Field(AllocClass(java_lang_Class.get(), sizeof(FieldClass)));
+ CHECK(java_lang_reflect_Field.get() != NULL);
java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
java_lang_reflect_Field->SetObjectSize(sizeof(Field));
- SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
+ SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field.get());
java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
- Field::SetClass(java_lang_reflect_Field);
+ Field::SetClass(java_lang_reflect_Field.get());
- Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
+ SirtRef<Class> java_lang_reflect_Method(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
java_lang_reflect_Method->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
- CHECK(java_lang_reflect_Method != NULL);
+ CHECK(java_lang_reflect_Method.get() != NULL);
java_lang_reflect_Method->SetObjectSize(sizeof(Method));
- SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
+ SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
- Method::SetClasses(java_lang_reflect_Constructor, java_lang_reflect_Method);
+ Method::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get());
// now we can use FindSystemClass
// run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class, "C", Class::kPrimChar);
- SetClassRoot(kPrimitiveChar, char_class); // needs descriptor
+ InitializePrimitiveClass(char_class.get(), "C", Class::kPrimChar);
+ SetClassRoot(kPrimitiveChar, char_class.get()); // needs descriptor
// Object and String need to be rerun through FindSystemClass to finish init
java_lang_Object->SetStatus(Class::kStatusNotReady);
Class* Object_class = FindSystemClass("Ljava/lang/Object;");
- CHECK_EQ(java_lang_Object, Object_class);
+ CHECK_EQ(java_lang_Object.get(), Object_class);
CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(Object));
java_lang_String->SetStatus(Class::kStatusNotReady);
Class* String_class = FindSystemClass("Ljava/lang/String;");
- CHECK_EQ(java_lang_String, String_class);
+ CHECK_EQ(java_lang_String.get(), String_class);
CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(String));
// Setup the primitive array type classes - can't be done until Object has a vtable
@@ -363,13 +364,13 @@ void ClassLinker::Init(const std::string& boot_class_path) {
ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
Class* found_char_array_class = FindSystemClass("[C");
- CHECK_EQ(char_array_class, found_char_array_class);
+ CHECK_EQ(char_array_class.get(), found_char_array_class);
SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
Class* found_int_array_class = FindSystemClass("[I");
- CHECK_EQ(int_array_class, found_int_array_class);
+ CHECK_EQ(int_array_class.get(), found_int_array_class);
SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
@@ -381,10 +382,10 @@ void ClassLinker::Init(const std::string& boot_class_path) {
DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;");
- CHECK_EQ(class_array_class, found_class_array_class);
+ CHECK_EQ(class_array_class.get(), found_class_array_class);
Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
- CHECK_EQ(object_array_class, found_object_array_class);
+ CHECK_EQ(object_array_class.get(), found_object_array_class);
// Setup the single, global copies of "interfaces" and "iftable"
Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
@@ -409,19 +410,19 @@ void ClassLinker::Init(const std::string& boot_class_path) {
// run Class, Constructor, Field, and Method through FindSystemClass.
// this initializes their dex_cache_ fields and register them in classes_.
Class* Class_class = FindSystemClass("Ljava/lang/Class;");
- CHECK_EQ(java_lang_Class, Class_class);
+ CHECK_EQ(java_lang_Class.get(), Class_class);
java_lang_reflect_Constructor->SetStatus(Class::kStatusNotReady);
Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;");
- CHECK_EQ(java_lang_reflect_Constructor, Constructor_class);
+ CHECK_EQ(java_lang_reflect_Constructor.get(), Constructor_class);
java_lang_reflect_Field->SetStatus(Class::kStatusNotReady);
Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
- CHECK_EQ(java_lang_reflect_Field, Field_class);
+ CHECK_EQ(java_lang_reflect_Field.get(), Field_class);
java_lang_reflect_Method->SetStatus(Class::kStatusNotReady);
Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
- CHECK_EQ(java_lang_reflect_Method, Method_class);
+ CHECK_EQ(java_lang_reflect_Method.get(), Method_class);
// End of special init trickery, subsequent classes may be loaded via FindSystemClass
@@ -647,7 +648,7 @@ void ClassLinker::InitFromImage() {
CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));
for (int i = 0; i < dex_caches->GetLength(); i++) {
- DexCache* dex_cache = dex_caches->Get(i);
+ SirtRef<DexCache> dex_cache(dex_caches->Get(i));
const std::string& dex_file_location = dex_cache->GetLocation()->ToModifiedUtf8();
std::string dex_filename;
@@ -741,6 +742,7 @@ void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
}
visitor(array_interfaces_, arg);
+ visitor(array_iftable_, arg);
}
ClassLinker::~ClassLinker() {
@@ -762,23 +764,47 @@ ClassLinker::~ClassLinker() {
}
DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
- String* location = intern_table_->InternStrong(dex_file.GetLocation().c_str());
- if (location == NULL) {
+ SirtRef<DexCache> dex_cache(down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray())));
+ if (dex_cache.get() == NULL) {
return NULL;
}
- DexCache* dex_cache = down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray()));
- if (dex_cache == NULL) {
+ SirtRef<String> location(intern_table_->InternStrong(dex_file.GetLocation().c_str()));
+ if (location.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<ObjectArray<String> > strings(AllocObjectArray<String>(dex_file.NumStringIds()));
+ if (strings.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<ObjectArray<Class> > types(AllocClassArray(dex_file.NumTypeIds()));
+ if (types.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<ObjectArray<Method> > methods(AllocObjectArray<Method>(dex_file.NumMethodIds()));
+ if (methods.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<ObjectArray<Field> > fields(AllocObjectArray<Field>(dex_file.NumFieldIds()));
+ if (fields.get() == NULL) {
return NULL;
}
- // TODO: lots of missing null checks hidden in this call...
- dex_cache->Init(location,
- AllocObjectArray<String>(dex_file.NumStringIds()),
- AllocClassArray(dex_file.NumTypeIds()),
- AllocObjectArray<Method>(dex_file.NumMethodIds()),
- AllocObjectArray<Field>(dex_file.NumFieldIds()),
- AllocCodeAndDirectMethods(dex_file.NumMethodIds()),
- AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds()));
- return dex_cache;
+ SirtRef<CodeAndDirectMethods> code_and_direct_methods(AllocCodeAndDirectMethods(dex_file.NumMethodIds()));
+ if (code_and_direct_methods.get() == NULL) {
+ return NULL;
+ }
+ SirtRef<ObjectArray<StaticStorageBase> > initialized_static_storage(AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds()));
+ if (initialized_static_storage.get() == NULL) {
+ return NULL;
+ }
+
+ dex_cache->Init(location.get(),
+ strings.get(),
+ types.get(),
+ methods.get(),
+ fields.get(),
+ code_and_direct_methods.get(),
+ initialized_static_storage.get());
+ return dex_cache.get();
}
CodeAndDirectMethods* ClassLinker::AllocCodeAndDirectMethods(size_t length) {
@@ -787,18 +813,18 @@ CodeAndDirectMethods* ClassLinker::AllocCodeAndDirectMethods(size_t length) {
InterfaceEntry* ClassLinker::AllocInterfaceEntry(Class* interface) {
DCHECK(interface->IsInterface());
- ObjectArray<Object>* array = AllocObjectArray<Object>(InterfaceEntry::LengthAsArray());
- InterfaceEntry* interface_entry = down_cast<InterfaceEntry*>(array);
+ SirtRef<ObjectArray<Object> > array(AllocObjectArray<Object>(InterfaceEntry::LengthAsArray()));
+ SirtRef<InterfaceEntry> interface_entry(down_cast<InterfaceEntry*>(array.get()));
interface_entry->SetInterface(interface);
- return interface_entry;
+ return interface_entry.get();
}
Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
DCHECK_GE(class_size, sizeof(Class));
- Class* klass = Heap::AllocObject(java_lang_Class, class_size)->AsClass();
+ SirtRef<Class> klass(Heap::AllocObject(java_lang_Class, class_size)->AsClass());
klass->SetPrimitiveType(Class::kPrimNot); // default to not being primitive
klass->SetClassSize(class_size);
- return klass;
+ return klass.get();
}
Class* ClassLinker::AllocClass(size_t class_size) {
@@ -907,27 +933,27 @@ Class* ClassLinker::DefineClass(const std::string& descriptor,
const ClassLoader* class_loader,
const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
- Class* klass;
+ SirtRef<Class> klass(NULL);
// Load the class from the dex file.
if (!init_done_) {
// finish up init of hand crafted class_roots_
if (descriptor == "Ljava/lang/Object;") {
- klass = GetClassRoot(kJavaLangObject);
+ klass.reset(GetClassRoot(kJavaLangObject));
} else if (descriptor == "Ljava/lang/Class;") {
- klass = GetClassRoot(kJavaLangClass);
+ klass.reset(GetClassRoot(kJavaLangClass));
} else if (descriptor == "Ljava/lang/String;") {
- klass = GetClassRoot(kJavaLangString);
+ klass.reset(GetClassRoot(kJavaLangString));
} else if (descriptor == "Ljava/lang/reflect/Constructor;") {
- klass = GetClassRoot(kJavaLangReflectConstructor);
+ klass.reset(GetClassRoot(kJavaLangReflectConstructor));
} else if (descriptor == "Ljava/lang/reflect/Field;") {
- klass = GetClassRoot(kJavaLangReflectField);
+ klass.reset(GetClassRoot(kJavaLangReflectField));
} else if (descriptor == "Ljava/lang/reflect/Method;") {
- klass = GetClassRoot(kJavaLangReflectMethod);
+ klass.reset(GetClassRoot(kJavaLangReflectMethod));
} else {
- klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
+ klass.reset(AllocClass(SizeOfClass(dex_file, dex_class_def)));
}
} else {
- klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
+ klass.reset(AllocClass(SizeOfClass(dex_file, dex_class_def)));
}
klass->SetDexCache(FindDexCache(dex_file));
LoadClass(dex_file, dex_class_def, klass, class_loader);
@@ -936,16 +962,16 @@ Class* ClassLinker::DefineClass(const std::string& descriptor,
if (self->IsExceptionPending()) {
return NULL;
}
- ObjectLock lock(klass);
+ ObjectLock lock(klass.get());
klass->SetClinitThreadId(self->GetTid());
// Add the newly loaded class to the loaded classes table.
- bool success = InsertClass(descriptor, klass); // TODO: just return collision
+ bool success = InsertClass(descriptor, klass.get()); // TODO: just return collision
if (!success) {
// We may fail to insert if we raced with another thread.
klass->SetClinitThreadId(0);
- klass = LookupClass(descriptor, class_loader);
- CHECK(klass != NULL);
- return klass;
+ klass.reset(LookupClass(descriptor, class_loader));
+ CHECK(klass.get() != NULL);
+ return klass.get();
}
// Finish loading (if necessary) by finding parents
CHECK(!klass->IsLoaded());
@@ -965,7 +991,7 @@ Class* ClassLinker::DefineClass(const std::string& descriptor,
return NULL;
}
CHECK(klass->IsResolved());
- return klass;
+ return klass.get();
}
// Precomputes size that will be needed for Class, matching LinkStaticFields
@@ -1015,11 +1041,11 @@ size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
return size;
}
-void LinkCode(Method* method, const OatFile::OatClass* oat_class, uint32_t method_index) {
+void LinkCode(SirtRef<Method>& method, const OatFile::OatClass* oat_class, uint32_t method_index) {
// Every kind of method should at least get an invoke stub from the oat_method.
// non-abstract methods also get their code pointers.
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
- oat_method.LinkMethod(method);
+ oat_method.LinkMethod(method.get());
if (method->IsAbstract()) {
method->SetCode(Runtime::Current()->GetAbstractMethodErrorStubArray()->GetData());
@@ -1034,9 +1060,9 @@ void LinkCode(Method* method, const OatFile::OatClass* oat_class, uint32_t metho
void ClassLinker::LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- Class* klass,
+ SirtRef<Class>& klass,
const ClassLoader* class_loader) {
- CHECK(klass != NULL);
+ CHECK(klass.get() != NULL);
CHECK(klass->GetDexCache() != NULL);
CHECK_EQ(Class::kStatusNotReady, klass->GetStatus());
const byte* class_data = dex_file.GetClassData(dex_class_def);
@@ -1088,8 +1114,8 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
for (size_t i = 0; i < num_static_fields; ++i) {
DexFile::Field dex_field;
dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
- Field* sfield = AllocField();
- klass->SetStaticField(i, sfield);
+ SirtRef<Field> sfield(AllocField());
+ klass->SetStaticField(i, sfield.get());
LoadField(dex_file, dex_field, klass, sfield);
}
}
@@ -1101,8 +1127,8 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
for (size_t i = 0; i < num_instance_fields; ++i) {
DexFile::Field dex_field;
dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
- Field* ifield = AllocField();
- klass->SetInstanceField(i, ifield);
+ SirtRef<Field> ifield(AllocField());
+ klass->SetInstanceField(i, ifield.get());
LoadField(dex_file, dex_field, klass, ifield);
}
}
@@ -1131,8 +1157,8 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
for (size_t i = 0; i < num_direct_methods; ++i, ++method_index) {
DexFile::Method dex_method;
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- Method* method = AllocMethod();
- klass->SetDirectMethod(i, method);
+ SirtRef<Method> method(AllocMethod());
+ klass->SetDirectMethod(i, method.get());
LoadMethod(dex_file, dex_method, klass, method);
if (oat_class.get() != NULL) {
LinkCode(method, oat_class.get(), method_index);
@@ -1148,8 +1174,8 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
for (size_t i = 0; i < num_virtual_methods; ++i, ++method_index) {
DexFile::Method dex_method;
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
- Method* method = AllocMethod();
- klass->SetVirtualMethod(i, method);
+ SirtRef<Method> method(AllocMethod());
+ klass->SetVirtualMethod(i, method.get());
LoadMethod(dex_file, dex_method, klass, method);
if (oat_class.get() != NULL) {
LinkCode(method, oat_class.get(), method_index);
@@ -1160,7 +1186,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
void ClassLinker::LoadInterfaces(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- Class* klass) {
+ SirtRef<Class>& klass) {
const DexFile::TypeList* list = dex_file.GetInterfacesList(dex_class_def);
if (list != NULL) {
klass->SetInterfaces(AllocClassArray(list->Size()));
@@ -1175,10 +1201,10 @@ void ClassLinker::LoadInterfaces(const DexFile& dex_file,
void ClassLinker::LoadField(const DexFile& dex_file,
const DexFile::Field& src,
- Class* klass,
- Field* dst) {
+ SirtRef<Class>& klass,
+ SirtRef<Field>& dst) {
const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_);
- dst->SetDeclaringClass(klass);
+ dst->SetDeclaringClass(klass.get());
dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
dst->SetTypeIdx(field_id.type_idx_);
dst->SetAccessFlags(src.access_flags_);
@@ -1188,17 +1214,17 @@ void ClassLinker::LoadField(const DexFile& dex_file,
const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
if (descriptor[1] == '\0') {
// only the descriptors of primitive types should be 1 character long
- Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass);
+ Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass.get());
DCHECK(resolved->IsPrimitive());
}
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
const DexFile::Method& src,
- Class* klass,
- Method* dst) {
+ SirtRef<Class>& klass,
+ SirtRef<Method>& dst) {
const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
- dst->SetDeclaringClass(klass);
+ dst->SetDeclaringClass(klass.get());
String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
if (method_name == NULL) {
@@ -1268,11 +1294,12 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
}
void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
- AppendToBootClassPath(dex_file, AllocDexCache(dex_file));
+ SirtRef<DexCache> dex_cache(AllocDexCache(dex_file));
+ AppendToBootClassPath(dex_file, dex_cache);
}
-void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache) {
- CHECK(dex_cache != NULL) << dex_file.GetLocation();
+void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) {
+ CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
boot_class_path_.push_back(&dex_file);
RegisterDexFile(dex_file, dex_cache);
}
@@ -1292,12 +1319,12 @@ bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const {
return IsDexFileRegisteredLocked(dex_file);
}
-void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, DexCache* dex_cache) {
+void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) {
dex_lock_.AssertHeld();
- CHECK(dex_cache != NULL) << dex_file.GetLocation();
+ CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
dex_files_.push_back(&dex_file);
- dex_caches_.push_back(dex_cache);
+ dex_caches_.push_back(dex_cache.get());
}
void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
@@ -1310,7 +1337,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
// Don't alloc while holding the lock, since allocation may need to
// suspend all threads and another thread may need the dex_lock_ to
// get to a suspend point.
- DexCache* dex_cache = AllocDexCache(dex_file);
+ SirtRef<DexCache> dex_cache(AllocDexCache(dex_file));
{
MutexLock mu(dex_lock_);
if (IsDexFileRegisteredLocked(dex_file)) {
@@ -1320,7 +1347,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
}
}
-void ClassLinker::RegisterDexFile(const DexFile& dex_file, DexCache* dex_cache) {
+void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) {
MutexLock mu(dex_lock_);
RegisterDexFileLocked(dex_file, dex_cache);
}
@@ -1420,22 +1447,22 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor,
// Array classes are simple enough that we don't need to do a full
// link step.
- Class* new_class = NULL;
+ SirtRef<Class> new_class(NULL);
if (!init_done_) {
// Classes that were hand created, ie not by FindSystemClass
if (descriptor == "[Ljava/lang/Class;") {
- new_class = GetClassRoot(kClassArrayClass);
+ new_class.reset(GetClassRoot(kClassArrayClass));
} else if (descriptor == "[Ljava/lang/Object;") {
- new_class = GetClassRoot(kObjectArrayClass);
+ new_class.reset(GetClassRoot(kObjectArrayClass));
} else if (descriptor == "[C") {
- new_class = GetClassRoot(kCharArrayClass);
+ new_class.reset(GetClassRoot(kCharArrayClass));
} else if (descriptor == "[I") {
- new_class = GetClassRoot(kIntArrayClass);
+ new_class.reset(GetClassRoot(kIntArrayClass));
}
}
- if (new_class == NULL) {
- new_class = AllocClass(sizeof(Class));
- if (new_class == NULL) {
+ if (new_class.get() == NULL) {
+ new_class.reset(AllocClass(sizeof(Class)));
+ if (new_class.get() == NULL) {
return NULL;
}
new_class->SetComponentType(component_type);
@@ -1486,8 +1513,8 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor,
new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() &
~kAccInterface) | kAccFinal) & kAccJavaFlagsMask);
- if (InsertClass(descriptor, new_class)) {
- return new_class;
+ if (InsertClass(descriptor, new_class.get())) {
+ return new_class.get();
}
// Another thread must have loaded the class after we
// started but before we finished. Abandon what we've
@@ -1570,8 +1597,8 @@ void ClassLinker::VerifyClass(Class* klass) {
Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
ClassLoader* loader, ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws) {
- Class* klass = AllocClass(GetClassRoot(kJavaLangClass), sizeof(ProxyClass));
- CHECK(klass != NULL);
+ SirtRef<Class> klass(AllocClass(GetClassRoot(kJavaLangClass), sizeof(ProxyClass)));
+ CHECK(klass.get() != NULL);
klass->SetObjectSize(sizeof(Proxy));
const char* descriptor = DotToDescriptor(name->ToModifiedUtf8().c_str()).c_str();;
klass->SetDescriptor(intern_table_->InternStrong(descriptor));
@@ -1590,7 +1617,7 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface
size_t num_virtual_methods = methods->GetLength();
klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
for (size_t i = 0; i < num_virtual_methods; ++i) {
- Method* prototype = methods->Get(i);
+ SirtRef<Method> prototype(methods->Get(i));
klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype, throws->Get(i)));
}
// Link the virtual methods, creating vtable and iftables
@@ -1598,10 +1625,10 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
- return klass;
+ return klass.get();
}
-Method* ClassLinker::CreateProxyConstructor(Class* klass) {
+Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass) {
// Create constructor for Proxy that must initialize h
Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
ObjectArray<Method>* proxy_direct_methods = proxy_class->GetDirectMethods();
@@ -1612,7 +1639,7 @@ Method* ClassLinker::CreateProxyConstructor(Class* klass) {
Method* constructor = down_cast<Method*>(proxy_constructor->Clone());
// Make this constructor public and fix the class to be our Proxy version
constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
- constructor->SetDeclaringClass(klass);
+ constructor->SetDeclaringClass(klass.get());
// Sanity checks
CHECK(constructor->IsConstructor());
CHECK(constructor->GetName()->Equals("<init>"));
@@ -1621,7 +1648,7 @@ Method* ClassLinker::CreateProxyConstructor(Class* klass) {
return constructor;
}
-Method* ClassLinker::CreateProxyMethod(Class* klass, Method* prototype,
+Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype,
ObjectArray<Class>* throws) {
// We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialise
// as necessary
@@ -1629,7 +1656,7 @@ Method* ClassLinker::CreateProxyMethod(Class* klass, Method* prototype,
// Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
// the intersection of throw exceptions as defined in Proxy
- method->SetDeclaringClass(klass);
+ method->SetDeclaringClass(klass.get());
method->SetAccessFlags((method->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
method->SetExceptionTypes(throws);
@@ -1993,7 +2020,7 @@ void ClassLinker::InitializeStaticFields(Class* klass) {
}
}
-bool ClassLinker::LinkClass(Class* klass) {
+bool ClassLinker::LinkClass(SirtRef<Class>& klass) {
CHECK_EQ(Class::kStatusLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
return false;
@@ -2014,10 +2041,10 @@ bool ClassLinker::LinkClass(Class* klass) {
return true;
}
-bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file) {
+bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) {
CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex) {
- Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass);
+ Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass.get());
if (super_class == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return false;
@@ -2026,7 +2053,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file)
}
for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
uint32_t idx = klass->GetInterfacesTypeIdx()->Get(i);
- Class* interface = ResolveType(dex_file, idx, klass);
+ Class* interface = ResolveType(dex_file, idx, klass.get());
klass->SetInterface(i, interface);
if (interface == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
@@ -2047,7 +2074,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file)
return true;
}
-bool ClassLinker::LinkSuperClass(Class* klass) {
+bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) {
CHECK(!klass->IsPrimitive());
Class* super = klass->GetSuperClass();
if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
@@ -2108,7 +2135,7 @@ bool ClassLinker::LinkSuperClass(Class* klass) {
}
// Populate the class vtable and itable. Compute return type indices.
-bool ClassLinker::LinkMethods(Class* klass) {
+bool ClassLinker::LinkMethods(SirtRef<Class>& klass) {
if (klass->IsInterface()) {
// No vtable.
size_t count = klass->NumVirtualMethods();
@@ -2128,7 +2155,7 @@ bool ClassLinker::LinkMethods(Class* klass) {
return true;
}
-bool ClassLinker::LinkVirtualMethods(Class* klass) {
+bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) {
if (klass->HasSuperClass()) {
uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength();
@@ -2179,18 +2206,18 @@ bool ClassLinker::LinkVirtualMethods(Class* klass) {
ThrowClassFormatError("Too many methods: %d", num_virtual_methods);
return false;
}
- ObjectArray<Method>* vtable = AllocObjectArray<Method>(num_virtual_methods);
+ SirtRef<ObjectArray<Method> > vtable(AllocObjectArray<Method>(num_virtual_methods));
for (size_t i = 0; i < num_virtual_methods; ++i) {
Method* virtual_method = klass->GetVirtualMethodDuringLinking(i);
vtable->Set(i, virtual_method);
virtual_method->SetMethodIndex(i & 0xFFFF);
}
- klass->SetVTable(vtable);
+ klass->SetVTable(vtable.get());
}
return true;
}
-bool ClassLinker::LinkInterfaceMethods(Class* klass) {
+bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass) {
size_t super_ifcount;
if (klass->HasSuperClass()) {
super_ifcount = klass->GetSuperClass()->GetIfTableCount();
@@ -2208,7 +2235,7 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
// DCHECK(klass->GetIfTable() == NULL);
return true;
}
- ObjectArray<InterfaceEntry>* iftable = AllocObjectArray<InterfaceEntry>(ifcount);
+ SirtRef<ObjectArray<InterfaceEntry> > iftable(AllocObjectArray<InterfaceEntry>(ifcount));
if (super_ifcount != 0) {
ObjectArray<InterfaceEntry>* super_iftable = klass->GetSuperClass()->GetIfTable();
for (size_t i = 0; i < super_ifcount; i++) {
@@ -2234,7 +2261,7 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
iftable->Set(idx++, AllocInterfaceEntry(interface->GetIfTable()->Get(j)->GetInterface()));
}
}
- klass->SetIfTable(iftable);
+ klass->SetIfTable(iftable.get());
CHECK_EQ(idx, ifcount);
// If we're an interface, we don't need the vtable pointers, so we're done.
@@ -2272,20 +2299,20 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
}
}
if (k < 0) {
- Method* miranda_method = NULL;
+ SirtRef<Method> miranda_method(NULL);
for (size_t mir = 0; mir < miranda_list.size(); mir++) {
if (miranda_list[mir]->HasSameNameAndSignature(interface_method)) {
- miranda_method = miranda_list[mir];
+ miranda_method.reset(miranda_list[mir]);
break;
}
}
- if (miranda_method == NULL) {
+ if (miranda_method.get() == NULL) {
// point the interface table at a phantom slot
- miranda_method = AllocMethod();
- memcpy(miranda_method, interface_method, sizeof(Method));
- miranda_list.push_back(miranda_method);
+ miranda_method.reset(AllocMethod());
+ memcpy(miranda_method.get(), interface_method, sizeof(Method));
+ miranda_list.push_back(miranda_method.get());
}
- method_array->Set(j, miranda_method);
+ method_array->Set(j, miranda_method.get());
}
}
}
@@ -2303,7 +2330,7 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
vtable = vtable->CopyOf(new_vtable_count);
for (size_t i = 0; i < miranda_list.size(); ++i) {
Method* method = miranda_list[i];
- method->SetDeclaringClass(klass);
+ method->SetDeclaringClass(klass.get());
method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
klass->SetVirtualMethod(old_method_count + i, method);
@@ -2323,13 +2350,13 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
return true;
}
-bool ClassLinker::LinkInstanceFields(Class* klass) {
- CHECK(klass != NULL);
+bool ClassLinker::LinkInstanceFields(SirtRef<Class>& klass) {
+ CHECK(klass.get() != NULL);
return LinkFields(klass, false);
}
-bool ClassLinker::LinkStaticFields(Class* klass) {
- CHECK(klass != NULL);
+bool ClassLinker::LinkStaticFields(SirtRef<Class>& klass) {
+ CHECK(klass.get() != NULL);
size_t allocated_class_size = klass->GetClassSize();
bool success = LinkFields(klass, true);
CHECK_EQ(allocated_class_size, klass->GetClassSize());
@@ -2358,7 +2385,7 @@ struct LinkFieldsComparator {
}
};
-bool ClassLinker::LinkFields(Class* klass, bool is_static) {
+bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) {
size_t num_fields =
is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
@@ -2467,7 +2494,7 @@ bool ClassLinker::LinkFields(Class* klass, bool is_static) {
Field* field = fields->Get(i);
if (false) { // enable to debug field layout
LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
- << " class=" << PrettyClass(klass)
+ << " class=" << PrettyClass(klass.get())
<< " field=" << PrettyField(field)
<< " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
}
@@ -2505,7 +2532,7 @@ bool ClassLinker::LinkFields(Class* klass, bool is_static) {
// Set the bitmap of reference offsets, refOffsets, from the ifields
// list.
-void ClassLinker::CreateReferenceInstanceOffsets(Class* klass) {
+void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<Class>& klass) {
uint32_t reference_offsets = 0;
Class* super_class = klass->GetSuperClass();
if (super_class != NULL) {
@@ -2519,11 +2546,11 @@ void ClassLinker::CreateReferenceInstanceOffsets(Class* klass) {
CreateReferenceOffsets(klass, false, reference_offsets);
}
-void ClassLinker::CreateReferenceStaticOffsets(Class* klass) {
+void ClassLinker::CreateReferenceStaticOffsets(SirtRef<Class>& klass) {
CreateReferenceOffsets(klass, true, 0);
}
-void ClassLinker::CreateReferenceOffsets(Class* klass, bool is_static,
+void ClassLinker::CreateReferenceOffsets(SirtRef<Class>& klass, bool is_static,
uint32_t reference_offsets) {
size_t num_reference_fields =
is_static ? klass->NumReferenceStaticFieldsDuringLinking()
diff --git a/src/class_linker.h b/src/class_linker.h
index f14b770..12d7b37 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -28,6 +28,7 @@
#include "mutex.h"
#include "oat_file.h"
#include "object.h"
+#include "stack_indirect_reference_table.h"
#include "unordered_map.h"
#include "unordered_set.h"
@@ -196,7 +197,7 @@ class ClassLinker {
void RunRootClinits();
void RegisterDexFile(const DexFile& dex_file);
- void RegisterDexFile(const DexFile& dex_file, DexCache* dex_cache);
+ void RegisterDexFile(const DexFile& dex_file, SirtRef<DexCache>& dex_cache);
const std::vector<const DexFile*>& GetBootClassPath() {
return boot_class_path_;
@@ -274,7 +275,7 @@ class ClassLinker {
const ClassLoader* class_loader);
void AppendToBootClassPath(const DexFile& dex_file);
- void AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache);
+ void AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache);
void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
Class* c, std::map<int, Field*>& field_map);
@@ -284,28 +285,28 @@ class ClassLinker {
void LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- Class* klass,
+ SirtRef<Class>& klass,
const ClassLoader* class_loader);
void LoadInterfaces(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- Class *klass);
+ SirtRef<Class>& klass);
void LoadField(const DexFile& dex_file,
const DexFile::Field& dex_field,
- Class* klass,
- Field* dst);
+ SirtRef<Class>& klass,
+ SirtRef<Field>& dst);
void LoadMethod(const DexFile& dex_file,
const DexFile::Method& dex_method,
- Class* klass,
- Method* dst);
+ SirtRef<Class>& klass,
+ SirtRef<Method>& dst);
// Inserts a class into the class table. Returns true if the class
// was inserted.
bool InsertClass(const std::string& descriptor, Class* klass);
- void RegisterDexFileLocked(const DexFile& dex_file, DexCache* dex_cache);
+ void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCache>& dex_cache);
bool IsDexFileRegisteredLocked(const DexFile& dex_file) const;
bool InitializeClass(Class* klass, bool can_run_clinit);
@@ -322,26 +323,26 @@ class ClassLinker {
const Class* klass1,
const Class* klass2);
- bool LinkClass(Class* klass);
+ bool LinkClass(SirtRef<Class>& klass);
- bool LinkSuperClass(Class* klass);
+ bool LinkSuperClass(SirtRef<Class>& klass);
- bool LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file);
+ bool LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file);
- bool LinkMethods(Class* klass);
+ bool LinkMethods(SirtRef<Class>& klass);
- bool LinkVirtualMethods(Class* klass);
+ bool LinkVirtualMethods(SirtRef<Class>& klass);
- bool LinkInterfaceMethods(Class* klass);
+ bool LinkInterfaceMethods(SirtRef<Class>& klass);
- bool LinkStaticFields(Class* klass);
- bool LinkInstanceFields(Class* klass);
- bool LinkFields(Class *klass, bool is_static);
+ bool LinkStaticFields(SirtRef<Class>& klass);
+ bool LinkInstanceFields(SirtRef<Class>& klass);
+ bool LinkFields(SirtRef<Class>& klass, bool is_static);
- void CreateReferenceInstanceOffsets(Class* klass);
- void CreateReferenceStaticOffsets(Class* klass);
- void CreateReferenceOffsets(Class *klass, bool is_static,
+ void CreateReferenceInstanceOffsets(SirtRef<Class>& klass);
+ void CreateReferenceStaticOffsets(SirtRef<Class>& klass);
+ void CreateReferenceOffsets(SirtRef<Class>& klass, bool is_static,
uint32_t reference_offsets);
// For use by ImageWriter to find DexCaches for its roots
@@ -351,8 +352,8 @@ class ClassLinker {
const OatFile* FindOpenedOatFile(const std::string& location);
- Method* CreateProxyConstructor(Class* klass);
- Method* CreateProxyMethod(Class* klass, Method* prototype, ObjectArray<Class>* throws);
+ Method* CreateProxyConstructor(SirtRef<Class>& klass);
+ Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype, ObjectArray<Class>* throws);
std::vector<const DexFile*> boot_class_path_;
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 75f2740..d1be1de 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -144,7 +144,8 @@ class ClassLinkerTest : public CommonTest {
void AssertClass(const std::string& descriptor, Class* klass) {
EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
- if (klass->GetDescriptor()->Equals(String::AllocFromModifiedUtf8("Ljava/lang/Object;"))) {
+ SirtRef<String> Object_descriptor(String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
+ if (klass->GetDescriptor()->Equals(Object_descriptor.get())) {
EXPECT_FALSE(klass->HasSuperClass());
} else {
EXPECT_TRUE(klass->HasSuperClass());
@@ -661,14 +662,14 @@ TEST_F(ClassLinkerTest, FindClassNonexistent) {
}
TEST_F(ClassLinkerTest, FindClassNested) {
- const ClassLoader* class_loader = LoadDex("Nested");
+ SirtRef<ClassLoader> class_loader(LoadDex("Nested"));
- Class* outer = class_linker_->FindClass("LNested;", class_loader);
+ Class* outer = class_linker_->FindClass("LNested;", class_loader.get());
ASSERT_TRUE(outer != NULL);
EXPECT_EQ(0U, outer->NumVirtualMethods());
EXPECT_EQ(1U, outer->NumDirectMethods());
- Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
+ Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader.get());
ASSERT_TRUE(inner != NULL);
EXPECT_EQ(0U, inner->NumVirtualMethods());
EXPECT_EQ(1U, inner->NumDirectMethods());
@@ -720,9 +721,9 @@ TEST_F(ClassLinkerTest, FindClass) {
EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
- const ClassLoader* class_loader = LoadDex("MyClass");
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClass"));
AssertNonExistentClass("LMyClass;");
- Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
+ Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader.get());
ASSERT_TRUE(MyClass != NULL);
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
@@ -730,7 +731,7 @@ TEST_F(ClassLinkerTest, FindClass) {
ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
- EXPECT_EQ(class_loader, MyClass->GetClassLoader());
+ EXPECT_EQ(class_loader.get(), MyClass->GetClassLoader());
EXPECT_EQ(Class::kStatusResolved, MyClass->GetStatus());
EXPECT_FALSE(MyClass->IsErroneous());
EXPECT_TRUE(MyClass->IsLoaded());
@@ -758,7 +759,7 @@ TEST_F(ClassLinkerTest, FindClass) {
AssertArrayClass("[Ljava/lang/Object;", "Ljava/lang/Object;", NULL);
// synthesized on the fly
AssertArrayClass("[[C", "[C", NULL);
- AssertArrayClass("[[[LMyClass;", "[[LMyClass;", class_loader);
+ AssertArrayClass("[[[LMyClass;", "[[LMyClass;", class_loader.get());
// or not available at all
AssertNonExistentClass("[[[[LNonExistentClass;");
}
@@ -779,9 +780,9 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
}
TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) {
- LongArray* array = LongArray::Alloc(0);
+ SirtRef<LongArray> array(LongArray::Alloc(0));
EXPECT_EQ(class_linker_->FindSystemClass("[J"), array->GetClass());
- uint32_t array_offset = reinterpret_cast<uint32_t>(array);
+ uint32_t array_offset = reinterpret_cast<uint32_t>(array.get());
uint32_t data_offset = reinterpret_cast<uint32_t>(array->GetData());
EXPECT_EQ(16U, data_offset - array_offset);
}
@@ -809,18 +810,18 @@ TEST_F(ClassLinkerTest, ValidateBoxedTypes) {
}
TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
- const ClassLoader* class_loader_1 = LoadDex("MyClass");
- const ClassLoader* class_loader_2 = LoadDex("MyClass");
- Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1);
- Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2);
+ SirtRef<ClassLoader> class_loader_1(LoadDex("MyClass"));
+ SirtRef<ClassLoader> class_loader_2(LoadDex("MyClass"));
+ Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1.get());
+ Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2.get());
EXPECT_TRUE(MyClass_1 != NULL);
EXPECT_TRUE(MyClass_2 != NULL);
EXPECT_NE(MyClass_1, MyClass_2);
}
TEST_F(ClassLinkerTest, StaticFields) {
- const ClassLoader* class_loader = LoadDex("Statics");
- Class* statics = class_linker_->FindClass("LStatics;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("Statics"));
+ Class* statics = class_linker_->FindClass("LStatics;", class_loader.get());
class_linker_->EnsureInitialized(statics, true);
// Static final primitives that are initialized by a compile-time constant
@@ -831,48 +832,48 @@ TEST_F(ClassLinkerTest, StaticFields) {
EXPECT_EQ(9U, statics->NumStaticFields());
- Field* s0 = statics->FindStaticField("s0", class_linker_->FindClass("Z", class_loader));
+ Field* s0 = statics->FindStaticField("s0", class_linker_->FindClass("Z", class_loader.get()));
EXPECT_TRUE(s0->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Field;"));
EXPECT_TRUE(s0->GetType()->IsPrimitiveBoolean());
EXPECT_EQ(true, s0->GetBoolean(NULL));
s0->SetBoolean(NULL, false);
- Field* s1 = statics->FindStaticField("s1", class_linker_->FindClass("B", class_loader));
+ Field* s1 = statics->FindStaticField("s1", class_linker_->FindClass("B", class_loader.get()));
EXPECT_TRUE(s1->GetType()->IsPrimitiveByte());
EXPECT_EQ(5, s1->GetByte(NULL));
s1->SetByte(NULL, 6);
- Field* s2 = statics->FindStaticField("s2", class_linker_->FindClass("C", class_loader));
+ Field* s2 = statics->FindStaticField("s2", class_linker_->FindClass("C", class_loader.get()));
EXPECT_TRUE(s2->GetType()->IsPrimitiveChar());
EXPECT_EQ('a', s2->GetChar(NULL));
s2->SetChar(NULL, 'b');
- Field* s3 = statics->FindStaticField("s3", class_linker_->FindClass("S", class_loader));
+ Field* s3 = statics->FindStaticField("s3", class_linker_->FindClass("S", class_loader.get()));
EXPECT_TRUE(s3->GetType()->IsPrimitiveShort());
EXPECT_EQ(-536, s3->GetShort(NULL));
s3->SetShort(NULL, -535);
- Field* s4 = statics->FindStaticField("s4", class_linker_->FindClass("I", class_loader));
+ Field* s4 = statics->FindStaticField("s4", class_linker_->FindClass("I", class_loader.get()));
EXPECT_TRUE(s4->GetType()->IsPrimitiveInt());
EXPECT_EQ(2000000000, s4->GetInt(NULL));
s4->SetInt(NULL, 2000000001);
- Field* s5 = statics->FindStaticField("s5", class_linker_->FindClass("J", class_loader));
+ Field* s5 = statics->FindStaticField("s5", class_linker_->FindClass("J", class_loader.get()));
EXPECT_TRUE(s5->GetType()->IsPrimitiveLong());
EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL));
s5->SetLong(NULL, 0x34567890abcdef12LL);
- Field* s6 = statics->FindStaticField("s6", class_linker_->FindClass("F", class_loader));
+ Field* s6 = statics->FindStaticField("s6", class_linker_->FindClass("F", class_loader.get()));
EXPECT_TRUE(s6->GetType()->IsPrimitiveFloat());
EXPECT_EQ(0.5, s6->GetFloat(NULL));
s6->SetFloat(NULL, 0.75);
- Field* s7 = statics->FindStaticField("s7", class_linker_->FindClass("D", class_loader));
+ Field* s7 = statics->FindStaticField("s7", class_linker_->FindClass("D", class_loader.get()));
EXPECT_TRUE(s7->GetType()->IsPrimitiveDouble());
EXPECT_EQ(16777217, s7->GetDouble(NULL));
s7->SetDouble(NULL, 16777219);
- Field* s8 = statics->FindStaticField("s8", class_linker_->FindClass("Ljava/lang/String;", class_loader));
+ Field* s8 = statics->FindStaticField("s8", class_linker_->FindClass("Ljava/lang/String;", class_loader.get()));
EXPECT_FALSE(s8->GetType()->IsPrimitive());
EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android"));
s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
@@ -889,12 +890,12 @@ TEST_F(ClassLinkerTest, StaticFields) {
}
TEST_F(ClassLinkerTest, Interfaces) {
- const ClassLoader* class_loader = LoadDex("Interfaces");
- Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader);
- Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader);
- Class* K = class_linker_->FindClass("LInterfaces$K;", class_loader);
- Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader);
- Class* B = class_linker_->FindClass("LInterfaces$B;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("Interfaces"));
+ Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader.get());
+ Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader.get());
+ Class* K = class_linker_->FindClass("LInterfaces$K;", class_loader.get());
+ Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader.get());
+ Class* B = class_linker_->FindClass("LInterfaces$B;", class_loader.get());
EXPECT_TRUE(I->IsAssignableFrom(A));
EXPECT_TRUE(J->IsAssignableFrom(A));
EXPECT_TRUE(J->IsAssignableFrom(K));
@@ -938,11 +939,11 @@ TEST_F(ClassLinkerTest, InitializeStaticStorageFromCode) {
// case 1, get the uninitialized storage from StaticsFromCode.<clinit>
// case 2, get the initialized storage from StaticsFromCode.getS0
- const ClassLoader* class_loader = LoadDex("StaticsFromCode");
- const DexFile* dex_file = ClassLoader::GetCompileTimeClassPath(class_loader)[0];
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticsFromCode"));
+ const DexFile* dex_file = ClassLoader::GetCompileTimeClassPath(class_loader.get())[0];
CHECK(dex_file != NULL);
- Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
Method* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
uint32_t type_idx = FindTypeIdxByDescriptor(*dex_file, "LStaticsFromCode;");
diff --git a/src/class_loader.cc b/src/class_loader.cc
index 94a212f..1623303 100644
--- a/src/class_loader.cc
+++ b/src/class_loader.cc
@@ -31,12 +31,12 @@ void ClassLoader::SetCompileTimeClassPath(const ClassLoader* class_loader,
// TODO: get global references for these
Class* PathClassLoader::dalvik_system_PathClassLoader_ = NULL;
-const PathClassLoader* PathClassLoader::AllocCompileTime(std::vector<const DexFile*>& dex_files) {
+PathClassLoader* PathClassLoader::AllocCompileTime(std::vector<const DexFile*>& dex_files) {
CHECK(!Runtime::Current()->IsStarted());
DCHECK(dalvik_system_PathClassLoader_ != NULL);
- PathClassLoader* p = down_cast<PathClassLoader*>(dalvik_system_PathClassLoader_->AllocObject());
- SetCompileTimeClassPath(p, dex_files);
- return p;
+ SirtRef<PathClassLoader> p(down_cast<PathClassLoader*>(dalvik_system_PathClassLoader_->AllocObject()));
+ SetCompileTimeClassPath(p.get(), dex_files);
+ return p.get();
}
void PathClassLoader::SetClass(Class* dalvik_system_PathClassLoader) {
diff --git a/src/class_loader.h b/src/class_loader.h
index 2904e3e..a5436fa 100644
--- a/src/class_loader.h
+++ b/src/class_loader.h
@@ -51,7 +51,7 @@ class BaseDexClassLoader : public ClassLoader {
// TODO: add MANAGED when class_path_ removed
class PathClassLoader : public BaseDexClassLoader {
public:
- static const PathClassLoader* AllocCompileTime(std::vector<const DexFile*>& dex_files);
+ static PathClassLoader* AllocCompileTime(std::vector<const DexFile*>& dex_files);
static void SetClass(Class* dalvik_system_PathClassLoader);
static void ResetClass();
private:
diff --git a/src/common_test.h b/src/common_test.h
index fc02a49..3f56aab 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -297,14 +297,6 @@ class CommonTest : public testing::Test {
return 0;
}
- const ClassLoader* AllocPathClassLoader(const DexFile* dex_file) {
- CHECK(dex_file != NULL);
- class_linker_->RegisterDexFile(*dex_file);
- std::vector<const DexFile*> dex_files;
- dex_files.push_back(dex_file);
- return PathClassLoader::AllocCompileTime(dex_files);
- }
-
const DexFile* OpenTestDexFile(const char* name) {
CHECK(name != NULL);
std::string filename;
@@ -320,17 +312,17 @@ class CommonTest : public testing::Test {
return dex_file;
}
- const ClassLoader* LoadDex(const char* dex_name) {
+ ClassLoader* LoadDex(const char* dex_name) {
const DexFile* dex_file = OpenTestDexFile(dex_name);
CHECK(dex_file != NULL);
loaded_dex_files_.push_back(dex_file);
class_linker_->RegisterDexFile(*dex_file);
std::vector<const DexFile*> class_path;
class_path.push_back(dex_file);
- const ClassLoader* class_loader = PathClassLoader::AllocCompileTime(class_path);
- CHECK(class_loader != NULL);
- Thread::Current()->SetClassLoaderOverride(class_loader);
- return class_loader;
+ SirtRef<ClassLoader> class_loader(PathClassLoader::AllocCompileTime(class_path));
+ CHECK(class_loader.get() != NULL);
+ Thread::Current()->SetClassLoaderOverride(class_loader.get());
+ return class_loader.get();
}
void CompileClass(const ClassLoader* class_loader, const char* class_name) {
@@ -353,7 +345,7 @@ class CommonTest : public testing::Test {
MakeExecutable(runtime_->GetJniStubArray());
}
- void CompileDirectMethod(const ClassLoader* class_loader,
+ void CompileDirectMethod(ClassLoader* class_loader,
const char* class_name,
const char* method_name,
const char* signature) {
@@ -366,7 +358,7 @@ class CommonTest : public testing::Test {
CompileMethod(method);
}
- void CompileVirtualMethod(const ClassLoader* class_loader,
+ void CompileVirtualMethod(ClassLoader* class_loader,
const char* class_name,
const char* method_name,
const char* signature) {
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 1066783..35da6f2 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -127,9 +127,9 @@ TEST_F(CompilerTest, DISABLED_LARGE_CompileDexLibCore) {
TEST_F(CompilerTest, AbstractMethodErrorStub) {
CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
- const ClassLoader* class_loader = LoadDex("AbstractMethod");
- ASSERT_TRUE(class_loader != NULL);
- EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);
+ SirtRef<ClassLoader> class_loader(LoadDex("AbstractMethod"));
+ ASSERT_TRUE(class_loader.get() != NULL);
+ EnsureCompiled(class_loader.get(), "AbstractClass", "foo", "()V", true);
// Create a jobj_ of ConcreteClass, NOT AbstractClass.
jclass c_class = env_->FindClass("ConcreteClass");
@@ -138,7 +138,7 @@ TEST_F(CompilerTest, AbstractMethodErrorStub) {
ASSERT_TRUE(jobj_ != NULL);
#if defined(__arm__)
- Class* jlame = class_linker_->FindClass("Ljava/lang/AbstractMethodError;", class_loader);
+ Class* jlame = class_linker_->FindClass("Ljava/lang/AbstractMethodError;", class_loader.get());
// Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
EXPECT_TRUE(Thread::Current()->IsExceptionPending());
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index aca8e8c..455b8b9 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -191,16 +191,14 @@ int dex2oat(int argc, char** argv) {
}
// ClassLoader creation needs to come after Runtime::Create
- const ClassLoader* class_loader;
- if (boot_image_option.empty()) {
- class_loader = NULL;
- } else {
+ SirtRef<ClassLoader> class_loader(NULL);
+ if (!boot_image_option.empty()) {
std::vector<const DexFile*> dex_files;
DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
for (size_t i = 0; i < dex_files.size(); i++) {
class_linker->RegisterDexFile(*dex_files[i]);
}
- class_loader = PathClassLoader::AllocCompileTime(dex_files);
+ class_loader.reset(PathClassLoader::AllocCompileTime(dex_files));
}
// if we loaded an existing image, we will reuse values from the image roots.
@@ -224,7 +222,7 @@ int dex2oat(int argc, char** argv) {
}
Compiler compiler(kThumb2, image_filename != NULL);
if (method_names.empty()) {
- compiler.CompileAll(class_loader);
+ compiler.CompileAll(class_loader.get());
} else {
for (size_t i = 0; i < method_names.size(); i++) {
// names are actually class_descriptor + name + signature.
@@ -246,7 +244,7 @@ int dex2oat(int argc, char** argv) {
end_of_name - end_of_class_descriptor).ToString();
std::string signature = method_name.substr(end_of_name).ToString();
- Class* klass = class_linker->FindClass(class_descriptor, class_loader);
+ Class* klass = class_linker->FindClass(class_descriptor, class_loader.get());
if (klass == NULL) {
fprintf(stderr, "could not find class for descriptor %s in method %s\n",
class_descriptor.c_str(), method_name.data());
@@ -268,7 +266,7 @@ int dex2oat(int argc, char** argv) {
}
}
- if (!OatWriter::Create(oat_filename, class_loader, compiler)) {
+ if (!OatWriter::Create(oat_filename, class_loader.get(), compiler)) {
fprintf(stderr, "Failed to create oat file %s\n", oat_filename.c_str());
return EXIT_FAILURE;
}
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
index 25f194a..054f991 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -13,8 +13,8 @@ namespace art {
class DexCacheTest : public CommonTest {};
TEST_F(DexCacheTest, Open) {
- DexCache* dex_cache = class_linker_->AllocDexCache(*java_lang_dex_file_.get());
- ASSERT_TRUE(dex_cache != NULL);
+ SirtRef<DexCache> dex_cache(class_linker_->AllocDexCache(*java_lang_dex_file_.get()));
+ ASSERT_TRUE(dex_cache.get() != NULL);
EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings());
EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), dex_cache->NumResolvedTypes());
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 220c111..83866a9 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -596,13 +596,6 @@ DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
return static_cast<ValueType>(type);
}
-String* DexFile::dexArtStringById(int32_t idx) const {
- if (idx == -1) {
- return NULL;
- }
- return String::AllocFromModifiedUtf8(dexStringById(idx));
-}
-
int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
// For native method, lineno should be -2 to indicate it is native. Note that
// "line number == -2" is how libcore tells from StackTraceElement.
@@ -630,9 +623,11 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
if (!method->IsStatic()) {
if (need_locals) {
- local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
- local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
- local_in_reg[arg_reg].signature_ = NULL;
+ std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8();
+ const ClassDef* class_def = FindClassDef(descriptor);
+ CHECK(class_def != NULL) << descriptor;
+ local_in_reg[arg_reg].name_ = "this";
+ local_in_reg[arg_reg].descriptor_ = GetClassDescriptor(*class_def);
local_in_reg[arg_reg].start_address_ = 0;
local_in_reg[arg_reg].is_live_ = true;
}
@@ -646,17 +641,15 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
return;
}
int32_t id = DecodeUnsignedLeb128P1(&stream);
- const char* descriptor_utf8 = it->GetDescriptor();
+ const char* descriptor = it->GetDescriptor();
if (need_locals) {
- String* descriptor = String::AllocFromModifiedUtf8(descriptor_utf8);
- String* name = dexArtStringById(id);
+ const char* name = dexStringById(id);
local_in_reg[arg_reg].name_ = name;
local_in_reg[arg_reg].descriptor_ = descriptor;
- local_in_reg[arg_reg].signature_ = NULL;
local_in_reg[arg_reg].start_address_ = address;
local_in_reg[arg_reg].is_live_ = true;
}
- switch (*descriptor_utf8) {
+ switch (*descriptor) {
case 'D':
case 'J':
arg_reg += 2;
@@ -700,12 +693,10 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
if (need_locals) {
InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
- local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
- local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
+ local_in_reg[reg].name_ = dexStringById(DecodeUnsignedLeb128P1(&stream));
+ local_in_reg[reg].descriptor_ = dexStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
if (opcode == DBG_START_LOCAL_EXTENDED) {
- local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
- } else {
- local_in_reg[reg].signature_ = NULL;
+ local_in_reg[reg].signature_ = dexStringById(DecodeUnsignedLeb128P1(&stream));
}
local_in_reg[reg].start_address_ = address;
local_in_reg[reg].is_live_ = true;
diff --git a/src/dex_file.h b/src/dex_file.h
index f41040e..070901b 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -575,8 +575,6 @@ class DexFile {
return dexStringById(idx, &unicode_length);
}
- String* dexArtStringById(int32_t idx) const;
-
// Get the descriptor string associated with a given type index.
const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
const TypeId& type_id = GetTypeId(idx);
@@ -588,11 +586,6 @@ class DexFile {
return dexStringById(type_id.descriptor_idx_);
}
- String* dexArtStringByTypeIdx(int32_t idx) const {
- const TypeId& type_id = GetTypeId(idx);
- return dexArtStringById(type_id.descriptor_idx_);
- }
-
// TODO: encoded_field is actually a stream of bytes
void dexReadClassDataField(const byte** encoded_field,
DexFile::Field* field,
@@ -712,9 +705,9 @@ class DexFile {
typedef void (*DexDebugNewLocalCb)(void* cnxt, uint16_t reg,
uint32_t startAddress,
uint32_t endAddress,
- const String* name,
- const String* descriptor,
- const String* signature);
+ const char* name,
+ const char* descriptor,
+ const char* signature);
static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
@@ -751,16 +744,16 @@ class DexFile {
};
struct LocalInfo {
- LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0), is_live_(false) {}
+ LocalInfo() : name_(NULL), start_address_(0), is_live_(false) {}
// E.g., list
- const String* name_;
+ const char* name_;
// E.g., Ljava/util/LinkedList;
- const String* descriptor_;
+ const char* descriptor_;
// E.g., java.util.LinkedList<java.lang.Integer>
- const String* signature_;
+ const char* signature_;
// PC location where the local is first defined.
uint16_t start_address_;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 3e41d23..6c7335e 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -345,14 +345,20 @@ bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) {
/* Generate a register map and add it to the method. */
UniquePtr<RegisterMap> map(GenerateRegisterMapV(vdata));
- ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
- ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map.get()));
+ SirtRef<ByteArray> header(ByteArray::Alloc(sizeof(RegisterMapHeader)));
+ if (header.get() == NULL) {
+ return false;
+ }
+ SirtRef<ByteArray> data(ByteArray::Alloc(ComputeRegisterMapSize(map.get())));
+ if (data.get() == NULL) {
+ return false;
+ }
memcpy(header->GetData(), map.get()->header_, sizeof(RegisterMapHeader));
memcpy(data->GetData(), map.get()->data_, ComputeRegisterMapSize(map.get()));
- method->SetRegisterMapHeader(header);
- method->SetRegisterMapData(data);
+ method->SetRegisterMapHeader(header.get());
+ method->SetRegisterMapData(data.get());
return true;
}
@@ -5305,8 +5311,14 @@ DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
}
/* Update method, and free compressed map if it was sitting on the heap. */
- //ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
- //ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map));
+ //SirtRef<ByteArray> header(ByteArray::Alloc(sizeof(RegisterMapHeader)));
+ //if (header.get() == NULL) {
+ // return NULL;
+ //}
+ //SirtRef<ByteArray> data(ByteArray::Alloc(ComputeRegisterMapSize(map)));
+ //if (data.get() == NULL) {
+ // return NULL;
+ //}
//memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
//memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
diff --git a/src/dex_verifier_test.cc b/src/dex_verifier_test.cc
index b72f495..0560abf 100644
--- a/src/dex_verifier_test.cc
+++ b/src/dex_verifier_test.cc
@@ -38,8 +38,8 @@ TEST_F(DexVerifierTest, LibCore) {
}
TEST_F(DexVerifierTest, IntMath) {
- const ClassLoader* class_loader = LoadDex("IntMath");
- Class* klass = class_linker_->FindClass("LIntMath;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("IntMath"));
+ Class* klass = class_linker_->FindClass("LIntMath;", class_loader.get());
ASSERT_TRUE(DexVerifier::VerifyClass(klass));
}
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 29d91bb..ab462a9 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -19,8 +19,8 @@ class ExceptionTest : public CommonTest {
virtual void SetUp() {
CommonTest::SetUp();
- const ClassLoader* class_loader = LoadDex("ExceptionHandle");
- my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("ExceptionHandle"));
+ my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader.get());
ASSERT_TRUE(my_klass_ != NULL);
dex_ = &Runtime::Current()->GetClassLinker()->FindDexFile(my_klass_->GetDexCache());
diff --git a/src/heap_test.cc b/src/heap_test.cc
index 8e869be..addbc0b 100644
--- a/src/heap_test.cc
+++ b/src/heap_test.cc
@@ -11,7 +11,7 @@ TEST_F(HeapTest, GarbageCollectClassLinkerInit) {
Class* c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
for (size_t i = 0; i < 1024; ++i) {
- ObjectArray<Object>* array = ObjectArray<Object>::Alloc(c, 2048);
+ SirtRef<ObjectArray<Object> > array(ObjectArray<Object>::Alloc(c, 2048));
for (size_t j = 0; j < 2048; ++j) {
array->Set(j, String::AllocFromModifiedUtf8("hello, world!"));
}
diff --git a/src/image_writer.cc b/src/image_writer.cc
index f3ecda0..d8385ca 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -89,14 +89,14 @@ void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) {
DCHECK_EQ(obj, obj->AsString()->Intern());
return;
}
- String* interned = obj->AsString()->Intern();
- if (obj != interned) {
- if (!IsImageOffsetAssigned(interned)) {
+ SirtRef<String> interned(obj->AsString()->Intern());
+ if (obj != interned.get()) {
+ if (!IsImageOffsetAssigned(interned.get())) {
// interned obj is after us, allocate its location early
- image_writer->AssignImageOffset(interned);
+ image_writer->AssignImageOffset(interned.get());
}
// point those looking for this object to the interned version.
- SetImageOffset(obj, GetImageOffset(interned));
+ SetImageOffset(obj, GetImageOffset(interned.get()));
return;
}
// else (obj == interned), nothing to do but fall through to the normal case
@@ -137,8 +137,8 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const {
}
// build an Object[] of the roots needed to restore the runtime
- ObjectArray<Object>* image_roots = ObjectArray<Object>::Alloc(object_array_class,
- ImageHeader::kImageRootsMax);
+ SirtRef<ObjectArray<Object> > image_roots(
+ ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax));
image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniStubArray());
image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
runtime->GetAbstractMethodErrorStubArray());
@@ -163,11 +163,11 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const {
for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
CHECK(image_roots->Get(i) != NULL);
}
- return image_roots;
+ return image_roots.get();
}
void ImageWriter::CalculateNewObjectOffsets() {
- ObjectArray<Object>* image_roots = CreateImageRoots();
+ SirtRef<ObjectArray<Object> > image_roots(CreateImageRoots());
HeapBitmap* heap_bitmap = Heap::GetLiveBits();
DCHECK(heap_bitmap != NULL);
@@ -186,7 +186,7 @@ void ImageWriter::CalculateNewObjectOffsets() {
// return to write header at start of image with future location of image_roots
ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_),
- reinterpret_cast<uint32_t>(GetImageAddress(image_roots)),
+ reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())),
oat_file_->GetOatHeader().GetChecksum(),
reinterpret_cast<uint32_t>(oat_base_),
reinterpret_cast<uint32_t>(oat_limit));
diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc
index d9a6a45..a0c47ec 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -11,26 +11,27 @@ class InternTableTest : public CommonTest {};
TEST_F(InternTableTest, Intern) {
InternTable intern_table;
- const String* foo_1 = intern_table.InternStrong(3, "foo");
- const String* foo_2 = intern_table.InternStrong(3, "foo");
- const String* foo_3 = String::AllocFromModifiedUtf8("foo");
- const String* bar = intern_table.InternStrong(3, "bar");
+ SirtRef<String> foo_1(intern_table.InternStrong(3, "foo"));
+ SirtRef<String> foo_2(intern_table.InternStrong(3, "foo"));
+ SirtRef<String> foo_3(String::AllocFromModifiedUtf8("foo"));
+ SirtRef<String> bar(intern_table.InternStrong(3, "bar"));
EXPECT_TRUE(foo_1->Equals("foo"));
EXPECT_TRUE(foo_2->Equals("foo"));
EXPECT_TRUE(foo_3->Equals("foo"));
- EXPECT_TRUE(foo_1 != NULL);
- EXPECT_TRUE(foo_2 != NULL);
- EXPECT_EQ(foo_1, foo_2);
- EXPECT_NE(foo_1, bar);
- EXPECT_NE(foo_2, bar);
- EXPECT_NE(foo_3, bar);
+ EXPECT_TRUE(foo_1.get() != NULL);
+ EXPECT_TRUE(foo_2.get() != NULL);
+ EXPECT_EQ(foo_1.get(), foo_2.get());
+ EXPECT_NE(foo_1.get(), bar.get());
+ EXPECT_NE(foo_2.get(), bar.get());
+ EXPECT_NE(foo_3.get(), bar.get());
}
TEST_F(InternTableTest, Size) {
InternTable t;
EXPECT_EQ(0U, t.Size());
t.InternStrong(3, "foo");
- t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
+ t.InternWeak(foo.get());
EXPECT_EQ(1U, t.Size());
t.InternStrong(3, "bar");
EXPECT_EQ(2U, t.Size());
@@ -72,21 +73,24 @@ TEST_F(InternTableTest, SweepInternTableWeaks) {
InternTable t;
t.InternStrong(3, "foo");
t.InternStrong(3, "bar");
- const String* s0 = t.InternWeak(String::AllocFromModifiedUtf8("hello"));
- const String* s1 = t.InternWeak(String::AllocFromModifiedUtf8("world"));
+ SirtRef<String> hello(String::AllocFromModifiedUtf8("hello"));
+ SirtRef<String> world(String::AllocFromModifiedUtf8("world"));
+ SirtRef<String> s0(t.InternWeak(hello.get()));
+ SirtRef<String> s1(t.InternWeak(world.get()));
EXPECT_EQ(4U, t.Size());
// We should traverse only the weaks...
TestPredicate p;
- p.Expect(s0);
- p.Expect(s1);
+ p.Expect(s0.get());
+ p.Expect(s1.get());
t.SweepInternTableWeaks(IsMarked, &p);
EXPECT_EQ(2U, t.Size());
// Just check that we didn't corrupt the unordered_multimap.
- t.InternWeak(String::AllocFromModifiedUtf8("still here"));
+ SirtRef<String> still_here(String::AllocFromModifiedUtf8("still here"));
+ t.InternWeak(still_here.get());
EXPECT_EQ(3U, t.Size());
}
@@ -94,41 +98,45 @@ TEST_F(InternTableTest, ContainsWeak) {
{
// Strongs are never weak.
InternTable t;
- String* foo_1 = t.InternStrong(3, "foo");
- EXPECT_FALSE(t.ContainsWeak(foo_1));
- String* foo_2 = t.InternStrong(3, "foo");
- EXPECT_FALSE(t.ContainsWeak(foo_2));
- EXPECT_EQ(foo_1, foo_2);
+ SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
+ EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
+ SirtRef<String> interned_foo_2(t.InternStrong(3, "foo"));
+ EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
+ EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
}
{
// Weaks are always weak.
InternTable t;
- String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
- EXPECT_TRUE(t.ContainsWeak(foo_1));
- String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
- EXPECT_TRUE(t.ContainsWeak(foo_2));
- EXPECT_EQ(foo_1, foo_2);
+ SirtRef<String> foo_1(String::AllocFromModifiedUtf8("foo"));
+ SirtRef<String> foo_2(String::AllocFromModifiedUtf8("foo"));
+ EXPECT_NE(foo_1.get(), foo_2.get());
+ SirtRef<String> interned_foo_1(t.InternWeak(foo_1.get()));
+ SirtRef<String> interned_foo_2(t.InternWeak(foo_2.get()));
+ EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
+ EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
}
{
// A weak can be promoted to a strong.
InternTable t;
- String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
- EXPECT_TRUE(t.ContainsWeak(foo_1));
- String* foo_2 = t.InternStrong(3, "foo");
- EXPECT_FALSE(t.ContainsWeak(foo_2));
- EXPECT_EQ(foo_1, foo_2);
+ SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
+ SirtRef<String> interned_foo_1(t.InternWeak(foo.get()));
+ EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get()));
+ SirtRef<String> interned_foo_2(t.InternStrong(3, "foo"));
+ EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
+ EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
}
{
// Interning a weak after a strong gets you the strong.
InternTable t;
- String* foo_1 = t.InternStrong(3, "foo");
- EXPECT_FALSE(t.ContainsWeak(foo_1));
- String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
- EXPECT_FALSE(t.ContainsWeak(foo_2));
- EXPECT_EQ(foo_1, foo_2);
+ SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
+ EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
+ SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
+ SirtRef<String> interned_foo_2(t.InternWeak(foo.get()));
+ EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
+ EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
}
}
diff --git a/src/java_lang_reflect_Array.cc b/src/java_lang_reflect_Array.cc
index f1456b1..d157282 100644
--- a/src/java_lang_reflect_Array.cc
+++ b/src/java_lang_reflect_Array.cc
@@ -29,13 +29,13 @@ namespace {
// Objects or primitive types.
Array* CreateMultiArray(Class* array_class, int current_dimension, IntArray* dimensions) {
int32_t array_length = dimensions->Get(current_dimension++);
- Array* new_array = Array::Alloc(array_class, array_length);
- if (new_array == NULL) {
+ SirtRef<Array> new_array(Array::Alloc(array_class, array_length));
+ if (new_array.get() == NULL) {
CHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
if (current_dimension == dimensions->GetLength()) {
- return new_array;
+ return new_array.get();
}
if (!array_class->GetComponentType()->IsArrayClass()) {
@@ -53,16 +53,16 @@ Array* CreateMultiArray(Class* array_class, int current_dimension, IntArray* dim
}
DCHECK(sub_array_class->IsArrayClass());
// Create a new sub-array in every element of the array.
- ObjectArray<Array>* object_array = new_array->AsObjectArray<Array>();
+ SirtRef<ObjectArray<Array> > object_array(new_array->AsObjectArray<Array>());
for (int32_t i = 0; i < array_length; i++) {
- Array* sub_array = CreateMultiArray(sub_array_class, current_dimension, dimensions);
- if (sub_array == NULL) {
+ SirtRef<Array> sub_array(CreateMultiArray(sub_array_class, current_dimension, dimensions));
+ if (sub_array.get() == NULL) {
CHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
- object_array->Set(i, sub_array);
+ object_array->Set(i, sub_array.get());
}
- return new_array;
+ return new_array.get();
}
// Create a multi-dimensional array of Objects or primitive types.
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index ecc2f88..938d733 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -21,14 +21,11 @@ namespace art {
class JniCompilerTest : public CommonTest {
protected:
- virtual void SetUp() {
- CommonTest::SetUp();
- class_loader_ = LoadDex("MyClassNatives");
- }
- void CompileForTest(bool direct, const char* method_name, const char* method_sig) {
+ void CompileForTest(ClassLoader* class_loader, bool direct,
+ const char* method_name, const char* method_sig) {
// Compile the native method before starting the runtime
- Class* c = class_linker_->FindClass("LMyClass;", class_loader_);
+ Class* c = class_linker_->FindClass("LMyClass;", class_loader);
Method* method;
if (direct) {
method = c->FindDirectMethod(method_name, method_sig);
@@ -43,9 +40,10 @@ class JniCompilerTest : public CommonTest {
ASSERT_TRUE(method->GetCode() != NULL);
}
- void SetupForTest(bool direct, const char* method_name, const char* method_sig,
+ void SetupForTest(ClassLoader* class_loader, bool direct,
+ const char* method_name, const char* method_sig,
void* native_fnptr) {
- CompileForTest(direct, method_name, method_sig);
+ CompileForTest(class_loader, direct, method_name, method_sig);
if (!runtime_->IsStarted()) {
runtime_->Start();
}
@@ -78,7 +76,6 @@ class JniCompilerTest : public CommonTest {
static jclass jklass_;
static jobject jobj_;
protected:
- const ClassLoader* class_loader_;
JNIEnv* env_;
jmethodID jmethod_;
};
@@ -88,7 +85,8 @@ jobject JniCompilerTest::jobj_;
int gJava_MyClass_foo_calls = 0;
void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + thisObj
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -97,7 +95,9 @@ void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
}
TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
- SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "foo", "()V",
+ reinterpret_cast<void*>(&Java_MyClass_foo));
EXPECT_EQ(0, gJava_MyClass_foo_calls);
env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
@@ -107,15 +107,13 @@ TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
}
TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
- SetupForTest(false,
- "bar",
- "(I)I",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "bar", "(I)I",
NULL /* dlsym will find &Java_MyClass_bar later */);
std::string path("libarttest.so");
std::string reason;
- ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(
- path, const_cast<ClassLoader*>(class_loader_), reason))
+ ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(path, class_loader.get(), reason))
<< path << ": " << reason;
jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
@@ -124,7 +122,8 @@ TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
int gJava_MyClass_fooI_calls = 0;
jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + thisObj
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -134,7 +133,8 @@ jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
}
TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
- SetupForTest(false, "fooI", "(I)I",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooI", "(I)I",
reinterpret_cast<void*>(&Java_MyClass_fooI));
EXPECT_EQ(0, gJava_MyClass_fooI_calls);
@@ -148,7 +148,8 @@ TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
int gJava_MyClass_fooII_calls = 0;
jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + thisObj
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -158,7 +159,8 @@ jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
}
TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
- SetupForTest(false, "fooII", "(II)I",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooII", "(II)I",
reinterpret_cast<void*>(&Java_MyClass_fooII));
EXPECT_EQ(0, gJava_MyClass_fooII_calls);
@@ -173,7 +175,8 @@ TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
int gJava_MyClass_fooJJ_calls = 0;
jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + thisObj
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -183,7 +186,8 @@ jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
}
TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
- SetupForTest(false, "fooJJ", "(JJ)J",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooJJ", "(JJ)J",
reinterpret_cast<void*>(&Java_MyClass_fooJJ));
EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
@@ -199,7 +203,8 @@ TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
int gJava_MyClass_fooDD_calls = 0;
jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + thisObj
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -209,7 +214,8 @@ jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
}
TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
- SetupForTest(false, "fooDD", "(DD)D",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooDD", "(DD)D",
reinterpret_cast<void*>(&Java_MyClass_fooDD));
EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
@@ -227,7 +233,8 @@ TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
int gJava_MyClass_fooIOO_calls = 0;
jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
jobject z) {
- EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
+ // 4 = SirtRef<ClassLoader> + this + y + z
+ EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(thisObj != NULL);
@@ -244,7 +251,8 @@ jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
}
TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
- SetupForTest(false, "fooIOO",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooIOO",
"(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
reinterpret_cast<void*>(&Java_MyClass_fooIOO));
@@ -276,7 +284,8 @@ TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
int gJava_MyClass_fooSII_calls = 0;
jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + klass
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
@@ -286,8 +295,8 @@ jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
}
TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
- SetupForTest(true, "fooSII",
- "(II)I",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), true, "fooSII", "(II)I",
reinterpret_cast<void*>(&Java_MyClass_fooSII));
EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
@@ -298,7 +307,8 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
int gJava_MyClass_fooSDD_calls = 0;
jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
- EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
+ // 2 = SirtRef<ClassLoader> + klass
+ EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
@@ -308,7 +318,8 @@ jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
}
TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
- SetupForTest(true, "fooSDD", "(DD)D",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), true, "fooSDD", "(DD)D",
reinterpret_cast<void*>(&Java_MyClass_fooSDD));
EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
@@ -325,7 +336,8 @@ TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
int gJava_MyClass_fooSIOO_calls = 0;
jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
jobject z) {
- EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
+ // 4 = SirtRef<ClassLoader> + klass + y + z
+ EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
@@ -343,7 +355,8 @@ jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
- SetupForTest(true, "fooSIOO",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), true, "fooSIOO",
"(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
@@ -376,7 +389,8 @@ TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
int gJava_MyClass_fooSSIOO_calls = 0;
jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
jobject z) {
- EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
+ // 4 = SirtRef<ClassLoader> + klass + y + z
+ EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
EXPECT_TRUE(klass != NULL);
@@ -393,7 +407,8 @@ jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
}
TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
- SetupForTest(true, "fooSSIOO",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), true, "fooSSIOO",
"(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
@@ -429,22 +444,25 @@ void Java_MyClass_throwException(JNIEnv* env, jobject) {
}
TEST_F(JniCompilerTest, ExceptionHandling) {
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+
// all compilation needs to happen before SetupForTest calls Runtime::Start
- CompileForTest(false, "foo", "()V");
- CompileForTest(false, "throwException", "()V");
- CompileForTest(false, "foo", "()V");
+ CompileForTest(class_loader.get(), false, "foo", "()V");
+ CompileForTest(class_loader.get(), false, "throwException", "()V");
+ CompileForTest(class_loader.get(), false, "foo", "()V");
gJava_MyClass_foo_calls = 0;
// Check a single call of a JNI method is ok
- SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
+ SetupForTest(class_loader.get(), false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
EXPECT_EQ(1, gJava_MyClass_foo_calls);
EXPECT_FALSE(Thread::Current()->IsExceptionPending());
// Get class for exception we expect to be thrown
- Class* jlre = class_linker_->FindClass("Ljava/lang/RuntimeException;", class_loader_);
- SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
+ Class* jlre = class_linker_->FindClass("Ljava/lang/RuntimeException;", class_loader.get());
+ SetupForTest(class_loader.get(), false, "throwException", "()V",
+ reinterpret_cast<void*>(&Java_MyClass_throwException));
// Call Java_MyClass_throwException (JNI method that throws exception)
env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
EXPECT_EQ(1, gJava_MyClass_foo_calls);
@@ -453,7 +471,7 @@ TEST_F(JniCompilerTest, ExceptionHandling) {
Thread::Current()->ClearException();
// Check a single call of a JNI method is ok
- SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
+ SetupForTest(class_loader.get(), false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
EXPECT_EQ(2, gJava_MyClass_foo_calls);
}
@@ -497,7 +515,9 @@ jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
}
TEST_F(JniCompilerTest, NativeStackTraceElement) {
- SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooI", "(I)I",
+ reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
}
@@ -507,7 +527,8 @@ jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
}
TEST_F(JniCompilerTest, ReturnGlobalRef) {
- SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
reinterpret_cast<void*>(&Java_MyClass_fooO));
jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
@@ -523,7 +544,8 @@ jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
}
TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
- SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
// 1000 invocations of a method that adds 10 local references
for (int i=0; i < 1000; i++) {
jint result = env_->CallIntMethod(jobj_, jmethod_, i);
@@ -541,7 +563,8 @@ void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject
}
TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
- SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
reinterpret_cast<void*>(&my_arraycopy));
env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
}
@@ -556,7 +579,8 @@ jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint ex
}
TEST_F(JniCompilerTest, CompareAndSwapInt) {
- SetupForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
+ SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
+ SetupForTest(class_loader.get(), false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
reinterpret_cast<void*>(&my_casi));
jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
EXPECT_EQ(result, JNI_TRUE);
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index e1ab9db..18d8e0a 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -652,7 +652,7 @@ TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
- LoadDex("AllFields");
+ SirtRef<ClassLoader> class_loader(LoadDex("AllFields"));
runtime_->Start();
jclass c = env_->FindClass("AllFields");
@@ -680,7 +680,7 @@ TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
}
TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
- LoadDex("AllFields");
+ SirtRef<ClassLoader> class_loader(LoadDex("AllFields"));
runtime_->Start();
jclass c = env_->FindClass("AllFields");
@@ -865,10 +865,10 @@ TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
#if defined(__arm__)
TEST_F(JniInternalTest, StaticMainMethod) {
- const ClassLoader* class_loader = LoadDex("Main");
- CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
+ SirtRef<ClassLoader> class_loader(LoadDex("Main"));
+ CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
- Class* klass = class_linker_->FindClass("LMain;", class_loader);
+ Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
@@ -882,10 +882,10 @@ TEST_F(JniInternalTest, StaticMainMethod) {
}
TEST_F(JniInternalTest, StaticNopMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "nop", "()V");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "nop", "()V");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("nop", "()V");
@@ -897,10 +897,10 @@ TEST_F(JniInternalTest, StaticNopMethod) {
}
TEST_F(JniInternalTest, StaticIdentityByteMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(B)B");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "identity", "(B)B");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("identity", "(B)B");
@@ -933,10 +933,10 @@ TEST_F(JniInternalTest, StaticIdentityByteMethod) {
}
TEST_F(JniInternalTest, StaticIdentityIntMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(I)I");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "identity", "(I)I");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("identity", "(I)I");
@@ -969,10 +969,10 @@ TEST_F(JniInternalTest, StaticIdentityIntMethod) {
}
TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(D)D");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "identity", "(D)D");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("identity", "(D)D");
@@ -1005,10 +1005,10 @@ TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
}
TEST_F(JniInternalTest, StaticSumIntIntMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(II)I");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(II)I");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(II)I");
@@ -1051,10 +1051,10 @@ TEST_F(JniInternalTest, StaticSumIntIntMethod) {
}
TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(III)I");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(III)I");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(III)I");
@@ -1102,10 +1102,10 @@ TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
}
TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(IIII)I");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(IIII)I");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(IIII)I");
@@ -1158,10 +1158,10 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
}
TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(IIIII)I");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(IIIII)I");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(IIIII)I");
@@ -1219,10 +1219,10 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
}
TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DD)D");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(DD)D");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(DD)D");
@@ -1265,10 +1265,10 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
}
TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDD)D");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(DDD)D");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(DDD)D");
@@ -1302,10 +1302,10 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
}
TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDDD)D");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(DDDD)D");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(DDDD)D");
@@ -1342,10 +1342,10 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
}
TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
- const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
- CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDDDD)D");
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
+ CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(DDDDD)D");
- Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader.get());
ASSERT_TRUE(klass != NULL);
Method* method = klass->FindDirectMethod("sum", "(DDDDD)D");
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 71983fe..d70d10d 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -216,29 +216,8 @@ inline void MarkSweep::ScanFields(const Object* obj, uint32_t ref_offsets, bool
// Scans the header, static field references, and interface pointers
// of a class object.
inline void MarkSweep::ScanClass(const Object* obj) {
- DCHECK(obj != NULL);
- DCHECK(obj->IsClass());
- const Class* klass = obj->AsClass();
- MarkObject(klass->GetClass());
ScanInstanceFields(obj);
- MarkObject(klass->GetDescriptor());
- MarkObject(klass->GetDexCache());
- MarkObject(klass->GetVerifyErrorClass());
- if (klass->IsArrayClass()) {
- MarkObject(klass->GetComponentType());
- }
- if (klass->IsLoaded()) {
- MarkObject(klass->GetSuperClass());
- }
- MarkObject(klass->GetClassLoader());
- if (klass->IsLoaded()) {
- MarkObject(klass->GetInterfaces());
- MarkObject(klass->GetDirectMethods());
- MarkObject(klass->GetVirtualMethods());
- MarkObject(klass->GetIFields());
- MarkObject(klass->GetSFields());
- }
- ScanStaticFields(klass);
+ ScanStaticFields(obj->AsClass());
}
// Scans the header of all array objects. If the array object is
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 392a822..3433e44 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -12,18 +12,18 @@ class OatTest : public CommonTest {};
TEST_F(OatTest, WriteRead) {
const bool compile = false; // DISABLED_ due to the time to compile libcore
- const ClassLoader* class_loader = NULL;
+ SirtRef<ClassLoader> class_loader(NULL);
if (compile) {
compiler_.reset(new Compiler(kThumb2, false));
- compiler_->CompileAll(class_loader);
+ compiler_->CompileAll(class_loader.get());
}
ScratchFile tmp;
- bool success = OatWriter::Create(tmp.GetFilename(), class_loader, *compiler_.get());
+ bool success = OatWriter::Create(tmp.GetFilename(), class_loader.get(), *compiler_.get());
ASSERT_TRUE(success);
if (compile) { // OatWriter strips the code, regenerate to compare
- compiler_->CompileAll(class_loader);
+ compiler_->CompileAll(class_loader.get());
}
UniquePtr<OatFile> oat_file(OatFile::Open(std::string(tmp.GetFilename()), "", NULL));
ASSERT_TRUE(oat_file.get() != NULL);
@@ -43,7 +43,7 @@ TEST_F(OatTest, WriteRead) {
UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
- Class* klass = class_linker->FindClass(descriptor, class_loader);
+ Class* klass = class_linker->FindClass(descriptor, class_loader.get());
size_t method_index = 0;
for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
diff --git a/src/object.cc b/src/object.cc
index b28594a..6ea1f59 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -30,23 +30,23 @@ Object* Object::Clone() {
// Object::SizeOf gets the right size even if we're an array.
// Using c->AllocObject() here would be wrong.
size_t num_bytes = SizeOf();
- Object* copy = Heap::AllocObject(c, num_bytes);
- if (copy == NULL) {
+ SirtRef<Object> copy(Heap::AllocObject(c, num_bytes));
+ if (copy.get() == NULL) {
return NULL;
}
// Copy instance data. We assume memcpy copies by words.
// TODO: expose and use move32.
byte* src_bytes = reinterpret_cast<byte*>(this);
- byte* dst_bytes = reinterpret_cast<byte*>(copy);
+ byte* dst_bytes = reinterpret_cast<byte*>(copy.get());
size_t offset = sizeof(Object);
memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
if (c->IsFinalizable()) {
- Heap::AddFinalizerReference(copy);
+ Heap::AddFinalizerReference(copy.get());
}
- return copy;
+ return copy.get();
}
uint32_t Object::GetThinLockId() {
@@ -1329,14 +1329,15 @@ String* String::AllocFromModifiedUtf8(int32_t utf16_length,
}
String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
- CharArray* array = CharArray::Alloc(utf16_length);
- if (array == NULL) {
+ SirtRef<CharArray> array(CharArray::Alloc(utf16_length));
+ if (array.get() == NULL) {
return NULL;
}
- return Alloc(java_lang_String, array);
+ return Alloc(java_lang_String, array.get());
}
String* String::Alloc(Class* java_lang_String, CharArray* array) {
+ SirtRef<CharArray> array_ref(array); // hold reference in case AllocObject causes GC
String* string = down_cast<String*>(java_lang_String->AllocObject());
if (string == NULL) {
return NULL;
diff --git a/src/object_test.cc b/src/object_test.cc
index e5af663..c493126 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -27,7 +27,7 @@ class ObjectTest : public CommonTest {
utf16_expected[i] = ch;
}
- String* string = String::AllocFromModifiedUtf8(length, utf8_in);
+ SirtRef<String> string(String::AllocFromModifiedUtf8(length, utf8_in));
ASSERT_EQ(length, string->GetLength());
ASSERT_TRUE(string->GetCharArray() != NULL);
ASSERT_TRUE(string->GetCharArray()->GetData() != NULL);
@@ -42,20 +42,22 @@ class ObjectTest : public CommonTest {
TEST_F(ObjectTest, IsInSamePackage) {
// Matches
- EXPECT_TRUE(Class::IsInSamePackage(String::AllocFromModifiedUtf8("Ljava/lang/Object;"),
- String::AllocFromModifiedUtf8("Ljava/lang/Class")));
- EXPECT_TRUE(Class::IsInSamePackage(String::AllocFromModifiedUtf8("LFoo;"),
- String::AllocFromModifiedUtf8("LBar;")));
+ SirtRef<String> Object_descriptor(String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
+ SirtRef<String> Class_descriptor(String::AllocFromModifiedUtf8("Ljava/lang/Class;"));
+ EXPECT_TRUE(Class::IsInSamePackage(Object_descriptor.get(), Class_descriptor.get()));
+ SirtRef<String> Foo_descriptor(String::AllocFromModifiedUtf8("LFoo;"));
+ SirtRef<String> Bar_descriptor(String::AllocFromModifiedUtf8("LBar;"));
+ EXPECT_TRUE(Class::IsInSamePackage(Foo_descriptor.get(), Bar_descriptor.get()));
// Mismatches
- EXPECT_FALSE(Class::IsInSamePackage(String::AllocFromModifiedUtf8("Ljava/lang/Object;"),
- String::AllocFromModifiedUtf8("Ljava/io/File;")));
- EXPECT_FALSE(Class::IsInSamePackage(String::AllocFromModifiedUtf8("Ljava/lang/Object;"),
- String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;")));
+ SirtRef<String> File_descriptor(String::AllocFromModifiedUtf8("Ljava/io/File;"));
+ EXPECT_FALSE(Class::IsInSamePackage(Object_descriptor.get(), File_descriptor.get()));
+ SirtRef<String> Method_descriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;"));
+ EXPECT_FALSE(Class::IsInSamePackage(Object_descriptor.get(), Method_descriptor.get()));
}
TEST_F(ObjectTest, Clone) {
- ObjectArray<Object>* a1 = class_linker_->AllocObjectArray<Object>(256);
+ SirtRef<ObjectArray<Object> > a1(class_linker_->AllocObjectArray<Object>(256));
size_t s1 = a1->SizeOf();
Object* clone = a1->Clone();
EXPECT_EQ(s1, clone->SizeOf());
@@ -63,16 +65,16 @@ TEST_F(ObjectTest, Clone) {
}
TEST_F(ObjectTest, AllocObjectArray) {
- ObjectArray<Object>* oa = class_linker_->AllocObjectArray<Object>(2);
+ SirtRef<ObjectArray<Object> > oa(class_linker_->AllocObjectArray<Object>(2));
EXPECT_EQ(2, oa->GetLength());
EXPECT_TRUE(oa->Get(0) == NULL);
EXPECT_TRUE(oa->Get(1) == NULL);
- oa->Set(0, oa);
- EXPECT_TRUE(oa->Get(0) == oa);
+ oa->Set(0, oa.get());
+ EXPECT_TRUE(oa->Get(0) == oa.get());
EXPECT_TRUE(oa->Get(1) == NULL);
- oa->Set(1, oa);
- EXPECT_TRUE(oa->Get(0) == oa);
- EXPECT_TRUE(oa->Get(1) == oa);
+ oa->Set(1, oa.get());
+ EXPECT_TRUE(oa->Get(0) == oa.get());
+ EXPECT_TRUE(oa->Get(1) == oa.get());
Thread* self = Thread::Current();
Class* aioobe = class_linker_->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
@@ -97,15 +99,15 @@ TEST_F(ObjectTest, AllocObjectArray) {
TEST_F(ObjectTest, AllocArray) {
Class* c = class_linker_->FindSystemClass("[I");
- Array* a = Array::Alloc(c, 1);
+ SirtRef<Array> a(Array::Alloc(c, 1));
ASSERT_TRUE(c == a->GetClass());
c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
- a = Array::Alloc(c, 1);
+ a.reset(Array::Alloc(c, 1));
ASSERT_TRUE(c == a->GetClass());
c = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
- a = Array::Alloc(c, 1);
+ a.reset(Array::Alloc(c, 1));
ASSERT_TRUE(c == a->GetClass());
}
@@ -177,20 +179,20 @@ TEST_F(ObjectTest, CheckAndAllocArrayFromCode) {
TEST_F(ObjectTest, StaticFieldFromCode) {
// pretend we are trying to access 'Static.s0' from StaticsFromCode.<clinit>
- const ClassLoader* class_loader = LoadDex("StaticsFromCode");
- const DexFile* dex_file = ClassLoader::GetCompileTimeClassPath(class_loader)[0];
+ SirtRef<ClassLoader> class_loader(LoadDex("StaticsFromCode"));
+ const DexFile* dex_file = ClassLoader::GetCompileTimeClassPath(class_loader.get())[0];
CHECK(dex_file != NULL);
- Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader);
+ Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
uint32_t field_idx = FindFieldIdxByDescriptorAndName(*dex_file, "LStaticsFromCode;", "s0");
Field* field = FindFieldFromCode(field_idx, clinit, true);
Object* s0 = field->GetObj(NULL);
EXPECT_EQ(NULL, s0);
- CharArray* char_array = CharArray::Alloc(0);
- field->SetObj(NULL, char_array);
- EXPECT_EQ(char_array, field->GetObj(NULL));
+ SirtRef<CharArray> char_array(CharArray::Alloc(0));
+ field->SetObj(NULL, char_array.get());
+ EXPECT_EQ(char_array.get(), field->GetObj(NULL));
field->SetObj(NULL, NULL);
EXPECT_EQ(NULL, field->GetObj(NULL));
@@ -222,7 +224,7 @@ TEST_F(ObjectTest, String) {
}
TEST_F(ObjectTest, StringEqualsUtf8) {
- String* string = String::AllocFromModifiedUtf8("android");
+ SirtRef<String> string(String::AllocFromModifiedUtf8("android"));
EXPECT_TRUE(string->Equals("android"));
EXPECT_FALSE(string->Equals("Android"));
EXPECT_FALSE(string->Equals("ANDROID"));
@@ -230,21 +232,22 @@ TEST_F(ObjectTest, StringEqualsUtf8) {
EXPECT_FALSE(string->Equals("and"));
EXPECT_FALSE(string->Equals("androids"));
- String* empty = String::AllocFromModifiedUtf8("");
+ SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
EXPECT_TRUE(empty->Equals(""));
EXPECT_FALSE(empty->Equals("a"));
}
TEST_F(ObjectTest, StringEquals) {
- String* string = String::AllocFromModifiedUtf8("android");
- EXPECT_TRUE(string->Equals(String::AllocFromModifiedUtf8("android")));
+ SirtRef<String> string(String::AllocFromModifiedUtf8("android"));
+ SirtRef<String> string_2(String::AllocFromModifiedUtf8("android"));
+ EXPECT_TRUE(string->Equals(string_2.get()));
EXPECT_FALSE(string->Equals("Android"));
EXPECT_FALSE(string->Equals("ANDROID"));
EXPECT_FALSE(string->Equals(""));
EXPECT_FALSE(string->Equals("and"));
EXPECT_FALSE(string->Equals("androids"));
- String* empty = String::AllocFromModifiedUtf8("");
+ SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
EXPECT_TRUE(empty->Equals(""));
EXPECT_FALSE(empty->Equals("a"));
}
@@ -252,12 +255,12 @@ TEST_F(ObjectTest, StringEquals) {
TEST_F(ObjectTest, DescriptorCompare) {
ClassLinker* linker = class_linker_;
- const ClassLoader* class_loader_1 = LoadDex("ProtoCompare");
- const ClassLoader* class_loader_2 = LoadDex("ProtoCompare2");
+ SirtRef<ClassLoader> class_loader_1(LoadDex("ProtoCompare"));
+ SirtRef<ClassLoader> class_loader_2(LoadDex("ProtoCompare2"));
- Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
+ Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1.get());
ASSERT_TRUE(klass1 != NULL);
- Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
+ Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2.get());
ASSERT_TRUE(klass2 != NULL);
Method* m1_1 = klass1->GetVirtualMethod(0);
@@ -293,22 +296,26 @@ TEST_F(ObjectTest, DescriptorCompare) {
TEST_F(ObjectTest, StringHashCode) {
- EXPECT_EQ(0, String::AllocFromModifiedUtf8("")->GetHashCode());
- EXPECT_EQ(65, String::AllocFromModifiedUtf8("A")->GetHashCode());
- EXPECT_EQ(64578, String::AllocFromModifiedUtf8("ABC")->GetHashCode());
+ SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
+ SirtRef<String> A(String::AllocFromModifiedUtf8("A"));
+ SirtRef<String> ABC(String::AllocFromModifiedUtf8("ABC"));
+
+ EXPECT_EQ(0, empty->GetHashCode());
+ EXPECT_EQ(65, A->GetHashCode());
+ EXPECT_EQ(64578, ABC->GetHashCode());
}
TEST_F(ObjectTest, InstanceOf) {
- const ClassLoader* class_loader = LoadDex("XandY");
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("XandY"));
+ Class* X = class_linker_->FindClass("LX;", class_loader.get());
+ Class* Y = class_linker_->FindClass("LY;", class_loader.get());
ASSERT_TRUE(X != NULL);
ASSERT_TRUE(Y != NULL);
- Object* x = X->AllocObject();
- Object* y = Y->AllocObject();
- ASSERT_TRUE(x != NULL);
- ASSERT_TRUE(y != NULL);
+ SirtRef<Object> x(X->AllocObject());
+ SirtRef<Object> y(Y->AllocObject());
+ ASSERT_TRUE(x.get() != NULL);
+ ASSERT_TRUE(y.get() != NULL);
EXPECT_EQ(1U, IsAssignableFromCode(X, x->GetClass()));
EXPECT_EQ(0U, IsAssignableFromCode(Y, x->GetClass()));
@@ -335,9 +342,9 @@ TEST_F(ObjectTest, InstanceOf) {
}
TEST_F(ObjectTest, IsAssignableFrom) {
- const ClassLoader* class_loader = LoadDex("XandY");
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("XandY"));
+ Class* X = class_linker_->FindClass("LX;", class_loader.get());
+ Class* Y = class_linker_->FindClass("LY;", class_loader.get());
EXPECT_TRUE(X->IsAssignableFrom(X));
EXPECT_TRUE(X->IsAssignableFrom(Y));
@@ -346,18 +353,18 @@ TEST_F(ObjectTest, IsAssignableFrom) {
}
TEST_F(ObjectTest, IsAssignableFromArray) {
- const ClassLoader* class_loader = LoadDex("XandY");
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ SirtRef<ClassLoader> class_loader(LoadDex("XandY"));
+ Class* X = class_linker_->FindClass("LX;", class_loader.get());
+ Class* Y = class_linker_->FindClass("LY;", class_loader.get());
ASSERT_TRUE(X != NULL);
ASSERT_TRUE(Y != NULL);
- Class* YA = class_linker_->FindClass("[LY;", class_loader);
- Class* YAA = class_linker_->FindClass("[[LY;", class_loader);
+ Class* YA = class_linker_->FindClass("[LY;", class_loader.get());
+ Class* YAA = class_linker_->FindClass("[[LY;", class_loader.get());
ASSERT_TRUE(YA != NULL);
ASSERT_TRUE(YAA != NULL);
- Class* XAA = class_linker_->FindClass("[[LX;", class_loader);
+ Class* XAA = class_linker_->FindClass("[[LX;", class_loader.get());
ASSERT_TRUE(XAA != NULL);
Class* O = class_linker_->FindSystemClass("Ljava/lang/Object;");
@@ -397,8 +404,8 @@ TEST_F(ObjectTest, IsAssignableFromArray) {
}
TEST_F(ObjectTest, FindInstanceField) {
- String* s = String::AllocFromModifiedUtf8("ABC");
- ASSERT_TRUE(s != NULL);
+ SirtRef<String> s(String::AllocFromModifiedUtf8("ABC"));
+ ASSERT_TRUE(s.get() != NULL);
Class* c = s->GetClass();
ASSERT_TRUE(c != NULL);
@@ -429,8 +436,8 @@ TEST_F(ObjectTest, FindInstanceField) {
}
TEST_F(ObjectTest, FindStaticField) {
- String* s = String::AllocFromModifiedUtf8("ABC");
- ASSERT_TRUE(s != NULL);
+ SirtRef<String> s(String::AllocFromModifiedUtf8("ABC"));
+ ASSERT_TRUE(s.get() != NULL);
Class* c = s->GetClass();
ASSERT_TRUE(c != NULL);
diff --git a/src/runtime.cc b/src/runtime.cc
index 6148ae7..64823fd 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -726,7 +726,7 @@ void Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, Trampolin
Method* Runtime::CreateCalleeSaveMethod(InstructionSet insns, CalleeSaveType type) {
Class* method_class = Method::GetMethodClass();
- Method* method = down_cast<Method*>(method_class->AllocObject());
+ SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
method->SetDeclaringClass(method_class);
const char* name;
if (type == kSaveAll) {
@@ -777,7 +777,7 @@ Method* Runtime::CreateCalleeSaveMethod(InstructionSet insns, CalleeSaveType typ
} else {
UNIMPLEMENTED(FATAL);
}
- return method;
+ return method.get();
}
bool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const {
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index f0b6698..8b98763 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -23,22 +23,55 @@ namespace art {
class Object;
-// Stack allocated indirect reference table, allocated within the bridge frame
-// between managed and native code.
+// Stack allocated indirect reference table. It can allocated within
+// the bridge frame between managed and native code backed by stack
+// storage or manually allocated by SirtRef to hold one reference.
class StackIndirectReferenceTable {
public:
+
+ StackIndirectReferenceTable(Object* object) {
+ number_of_references_ = 1;
+ references_[0] = object;
+ Thread::Current()->PushSirt(this);
+ }
+
+ ~StackIndirectReferenceTable() {
+ StackIndirectReferenceTable* sirt = Thread::Current()->PopSirt();
+ CHECK_EQ(this, sirt);
+ }
+
// Number of references contained within this SIRT
- size_t NumberOfReferences() {
+ size_t NumberOfReferences() const {
return number_of_references_;
}
// Link to previous SIRT or NULL
- StackIndirectReferenceTable* Link() {
+ StackIndirectReferenceTable* GetLink() const {
return link_;
}
- Object** References() {
- return references_;
+ void SetLink(StackIndirectReferenceTable* sirt) {
+ DCHECK_NE(this, sirt);
+ link_ = sirt;
+ }
+
+ Object* GetReference(size_t i) const {
+ DCHECK_LT(i, number_of_references_);
+ return references_[i];
+ }
+
+ void SetReference(size_t i, Object* object) {
+ DCHECK_LT(i, number_of_references_);
+ references_[i] = object;
+ }
+
+ bool Contains(Object** sirt_entry) const {
+ // A SIRT should always contain something. One created by the
+ // jni_compiler should have a jobject/jclass as a native method is
+ // passed in a this pointer or a class
+ DCHECK_GT(number_of_references_, 0U);
+ return ((&references_[0] <= sirt_entry)
+ && (sirt_entry <= (&references_[number_of_references_ - 1])));
}
// Offset of length within SIRT, used by generated code
@@ -57,12 +90,34 @@ private:
size_t number_of_references_;
StackIndirectReferenceTable* link_;
- // Fake array, really allocated and filled in by jni_compiler.
- Object* references_[0];
+ // number_of_references_ are available if this is allocated and filled in by jni_compiler.
+ Object* references_[1];
DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
};
+template<class T>
+class SirtRef {
+public:
+ SirtRef(T* object) : sirt_(object) {}
+ ~SirtRef() {}
+
+ T& operator*() const { return *get(); }
+ T* operator->() const { return get(); }
+ T* get() const {
+ return down_cast<T*>(sirt_.GetReference(0));
+ }
+
+ void reset(T* object = NULL) {
+ sirt_.SetReference(0, object);
+ }
+
+private:
+ StackIndirectReferenceTable sirt_;
+
+ DISALLOW_COPY_AND_ASSIGN(SirtRef);
+};
+
} // namespace art
#endif // ART_SRC_STACK_INDIRECT_REFERENCE_TABLE_H_
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index dfbd524..3768721 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -3,6 +3,7 @@
#include "assembler_arm.h"
#include "jni_internal.h"
#include "object.h"
+#include "stack_indirect_reference_table.h"
#define __ assembler->
@@ -38,12 +39,12 @@ ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* resolution_trampoline = ByteArray::Alloc(cs);
- CHECK(resolution_trampoline != NULL);
+ SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
+ CHECK(resolution_trampoline.get() != NULL);
MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
assembler->FinalizeInstructions(code);
- return resolution_trampoline;
+ return resolution_trampoline.get();
}
typedef void (*ThrowAme)(Method*, Thread*);
@@ -69,13 +70,13 @@ ByteArray* CreateAbstractMethodErrorStub() {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* abstract_stub = ByteArray::Alloc(cs);
- CHECK(abstract_stub != NULL);
+ SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
+ CHECK(abstract_stub.get() != NULL);
CHECK(abstract_stub->GetClass()->GetDescriptor());
MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
assembler->FinalizeInstructions(code);
- return abstract_stub;
+ return abstract_stub.get();
}
ByteArray* CreateJniStub() {
@@ -98,12 +99,12 @@ ByteArray* CreateJniStub() {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* jni_stub = ByteArray::Alloc(cs);
- CHECK(jni_stub != NULL);
+ SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
+ CHECK(jni_stub.get() != NULL);
MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
assembler->FinalizeInstructions(code);
- return jni_stub;
+ return jni_stub.get();
}
} // namespace arm
diff --git a/src/stub_x86.cc b/src/stub_x86.cc
index ea745ee..7660f6f 100644
--- a/src/stub_x86.cc
+++ b/src/stub_x86.cc
@@ -3,6 +3,7 @@
#include "assembler_x86.h"
#include "jni_internal.h"
#include "object.h"
+#include "stack_indirect_reference_table.h"
#define __ assembler->
@@ -17,12 +18,12 @@ ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType) {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* resolution_trampoline = ByteArray::Alloc(cs);
- CHECK(resolution_trampoline != NULL);
+ SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
+ CHECK(resolution_trampoline.get() != NULL);
MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
assembler->FinalizeInstructions(code);
- return resolution_trampoline;
+ return resolution_trampoline.get();
}
typedef void (*ThrowAme)(Method*, Thread*);
@@ -46,12 +47,12 @@ ByteArray* CreateAbstractMethodErrorStub() {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* abstract_stub = ByteArray::Alloc(cs);
- CHECK(abstract_stub != NULL);
+ SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
+ CHECK(abstract_stub.get() != NULL);
MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
assembler->FinalizeInstructions(code);
- return abstract_stub;
+ return abstract_stub.get();
}
ByteArray* CreateJniStub() {
@@ -79,12 +80,12 @@ ByteArray* CreateJniStub() {
assembler->EmitSlowPaths();
size_t cs = assembler->CodeSize();
- ByteArray* jni_stub = ByteArray::Alloc(cs);
- CHECK(jni_stub != NULL);
+ SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
+ CHECK(jni_stub.get() != NULL);
MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
assembler->FinalizeInstructions(code);
- return jni_stub;
+ return jni_stub.get();
}
} // namespace x86
diff --git a/src/thread.cc b/src/thread.cc
index 73b8a94..7dc8104 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -826,7 +826,7 @@ void Thread::HandleUncaughtExceptions() {
size_t Thread::NumSirtReferences() {
size_t count = 0;
- for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
+ for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) {
count += cur->NumberOfReferences();
}
return count;
@@ -834,13 +834,8 @@ size_t Thread::NumSirtReferences() {
bool Thread::SirtContains(jobject obj) {
Object** sirt_entry = reinterpret_cast<Object**>(obj);
- for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
- size_t num_refs = cur->NumberOfReferences();
- // A SIRT should always have a jobject/jclass as a native method is passed
- // in a this pointer or a class
- DCHECK_GT(num_refs, 0u);
- if ((&cur->References()[0] <= sirt_entry) &&
- (sirt_entry <= (&cur->References()[num_refs - 1]))) {
+ for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) {
+ if (cur->Contains(sirt_entry)) {
return true;
}
}
@@ -848,10 +843,10 @@ bool Thread::SirtContains(jobject obj) {
}
void Thread::SirtVisitRoots(Heap::RootVisitor* visitor, void* arg) {
- for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
+ for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) {
size_t num_refs = cur->NumberOfReferences();
for (size_t j = 0; j < num_refs; j++) {
- Object* object = cur->References()[j];
+ Object* object = cur->GetReference(j);
if (object != NULL) {
visitor(object, arg);
}
@@ -1025,6 +1020,18 @@ uintptr_t DemanglePc(uintptr_t pc) {
return pc + 2;
}
+void Thread::PushSirt(StackIndirectReferenceTable* sirt) {
+ sirt->SetLink(top_sirt_);
+ top_sirt_ = sirt;
+}
+
+StackIndirectReferenceTable* Thread::PopSirt() {
+ CHECK(top_sirt_ != NULL);
+ StackIndirectReferenceTable* sirt = top_sirt_;
+ top_sirt_ = top_sirt_->GetLink();
+ return sirt;
+}
+
void Thread::WalkStack(StackVisitor* visitor) const {
Frame frame = GetTopOfStack();
uintptr_t pc = ManglePc(top_of_managed_stack_pc_);
@@ -1129,9 +1136,15 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job
line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(native_pc));
}
// Allocate element, potentially triggering GC
- StackTraceElement* obj =
- StackTraceElement::Alloc(String::AllocFromModifiedUtf8(class_name.c_str()),
- method->GetName(), klass->GetSourceFile(), line_number);
+ // TODO: reuse class_name_object via Class::name_?
+ SirtRef<String> class_name_object(String::AllocFromModifiedUtf8(class_name.c_str()));
+ if (class_name_object.get() == NULL) {
+ return NULL;
+ }
+ StackTraceElement* obj = StackTraceElement::Alloc(class_name_object.get(),
+ method->GetName(),
+ klass->GetSourceFile(),
+ line_number);
if (obj == NULL) {
return NULL;
}
@@ -1417,6 +1430,9 @@ void Thread::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
if (pre_allocated_OutOfMemoryError_ != NULL) {
visitor(pre_allocated_OutOfMemoryError_, arg);
}
+ if (class_loader_override_ != NULL) {
+ visitor(class_loader_override_, arg);
+ }
jni_env_->locals.VisitRoots(visitor, arg);
jni_env_->monitors.VisitRoots(visitor, arg);
diff --git a/src/thread.h b/src/thread.h
index f30d092..37c1042 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -47,12 +47,12 @@ class Method;
class Monitor;
class Object;
class Runtime;
-class Thread;
-class ThreadList;
-class Throwable;
class StackIndirectReferenceTable;
class StackTraceElement;
class StaticStorageBase;
+class Thread;
+class ThreadList;
+class Throwable;
template<class T> class ObjectArray;
template<class T> class PrimitiveArray;
@@ -446,6 +446,9 @@ class PACKED Thread {
return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_pc_));
}
+ void PushSirt(StackIndirectReferenceTable* sirt);
+ StackIndirectReferenceTable* PopSirt();
+
static ThreadOffset TopSirtOffset() {
return ThreadOffset(OFFSETOF_MEMBER(Thread, top_sirt_));
}
diff --git a/src/utils_test.cc b/src/utils_test.cc
index 0869b89..bf66d05 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -11,8 +11,8 @@ class UtilsTest : public CommonTest {
#define EXPECT_DESCRIPTOR(pretty_descriptor, descriptor) \
do { \
- String* s = String::AllocFromModifiedUtf8(descriptor); \
- std::string result(PrettyDescriptor(s)); \
+ SirtRef<String> s(String::AllocFromModifiedUtf8(descriptor)); \
+ std::string result(PrettyDescriptor(s.get())); \
EXPECT_EQ(pretty_descriptor, result); \
} while (false)
@@ -59,11 +59,11 @@ TEST_F(UtilsTest, PrettyDescriptor_PrimitiveScalars) {
TEST_F(UtilsTest, PrettyTypeOf) {
EXPECT_EQ("null", PrettyTypeOf(NULL));
- String* s = String::AllocFromModifiedUtf8("");
- EXPECT_EQ("java.lang.String", PrettyTypeOf(s));
+ SirtRef<String> s(String::AllocFromModifiedUtf8(""));
+ EXPECT_EQ("java.lang.String", PrettyTypeOf(s.get()));
- ShortArray* a = ShortArray::Alloc(2);
- EXPECT_EQ("short[]", PrettyTypeOf(a));
+ SirtRef<ShortArray> a(ShortArray::Alloc(2));
+ EXPECT_EQ("short[]", PrettyTypeOf(a.get()));
Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;");
ASSERT_TRUE(c != NULL);
diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc
index c19ccf9..ca46569 100644
--- a/test/ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/ReferenceMap/stack_walk_refmap_jni.cc
@@ -29,7 +29,7 @@ struct ReferenceMap2Visitor : public Thread::StackVisitor {
void VisitFrame(const Frame& frame, uintptr_t pc) {
Method* m = frame.GetMethod();
- if (!m ||m->IsNative()) {
+ if (!m || m->IsNative()) {
return;
}
LOG(INFO) << "At " << PrettyMethod(m, false);